Envoy 的 redis_proxy 过滤器不支持 Redis Pub/Sub,因其基于同步请求-响应设计,无法处理 SUBSCRIBE 等长连接、多响应、无明确 reply boundary 的异步广播语义;官方明确标注不支持相关命令,遇之返回 NOT_SUPPORTED。

Envoy 本身不支持 Redis 协议的发布订阅(Pub/Sub)流量路由,因为它的内置过滤器链中没有 Redis L7 解析能力,envoy.filters.network.redis_proxy 仅支持请求-响应式命令(如 GET、SET),无法处理 SUBSCRIBE、PSUBSCRIBE 等长连接、多响应、无明确 reply boundary 的交互模式。
为什么 envoy.filters.network.redis_proxy 不能代理 Pub/Sub 流量
Redis Pub/Sub 的语义与传统 RPC 完全不同:
-
SUBSCRIBE后客户端进入“接收推送”状态,服务端持续发消息,没有 request-reply 对应关系 - Envoy 的
redis_proxy过滤器基于同步命令解析 + 回复匹配设计,依赖每个请求有且仅有一个可预期的响应;它会把SUBSCRIBE当作普通命令处理,收到第一个message就尝试结束流,导致后续推送丢弃或连接重置 - 该过滤器不维护客户端订阅状态映射,也无法将一条
PUBLISH广播到多个下游SUBSCRIBE连接 - 官方文档和 v1.36.2 源码中明确标注:该过滤器 不支持
SUBSCRIBE/PSUBSCRIBE/UNSUBSCRIBE等命令,遇到时直接返回错误NOT_SUPPORTED
替代方案:用 TCP 层透传 + 外部控制面做路由决策
若必须用 Envoy 承载 Redis Pub/Sub 流量,唯一可行路径是绕过协议解析,走纯 TCP 代理,并将路由逻辑外移到控制面:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 使用
envoy.filters.network.tcp_proxy替代redis_proxy,关闭所有协议感知,只做四层转发 - 在 Listener 上配置
use_original_dst: true或结合original_dst_cluster实现基于目标 IP 的初步分流(例如按 Redis 实例角色区分 Master/Slave) - 通过
RTDS(Runtime Discovery Service)动态开关某类 channel 的路由策略,比如runtime_key: "redis_pubsub.channel.news"控制是否允许该 channel 流量进入某个集群 - 观测只能依赖连接级指标:
downstream_cx_total、upstream_cx_active、downstream_flow_control_paused_reading_total—— 无法统计 “多少 client 订阅了 news.*” 这类业务维度数据
真正可行的观测与动态路由要靠 Redis 自身 + 外部组件
想实现“按 channel 动态路由”或“订阅行为可观测”,必须放弃在 Envoy 做 L7 解析这条路:
- 让应用直连 Redis,用 Redis 的
PUBSUB NUMSUB、PUBSUB CHANNELS等命令主动上报订阅拓扑,写入 Prometheus 或 OpenTelemetry - 用轻量代理(如自研 Go 服务或 Node-Redis 的
redis-pubsub-proxy)拦截并解析SUBSCRIBE请求,提取 channel 名,再查配置中心决定转发目标,同时记录日志和 metric - Envoy 可作为这个轻量代理的前置 LB(即
tcp_proxy→ 自研 proxy → Redis),此时 Envoy 只负责健康检查、熔断、连接池管理,不碰 Redis 协议 - 如果用 Istio,
VirtualService和DestinationRule对 Redis TCP 流量完全无效;Istio 的 mTLS 和 Telemetry 也仅限于 HTTP/gRPC,对 Redis 无意义
真正卡点不在配置怎么写,而在于 Redis Pub/Sub 的异步广播模型和 Envoy 的同步过滤器模型根本冲突。硬塞进去只会得到不可靠的连接中断和丢失消息 —— 这个边界比 TLS 配置错误或 xDS 版本不兼容更底层,也更难调试。


















