新闻详情

新闻详情

首页 / 资讯中心 / 详情

Envoy Redis Proxy 的 RESP3 协议支持:HELLO 握手、配置与降级兼容全解析

发布时间:2026/9/12 20:37:16来源:尧图网络
Envoy Redis Proxy 的 RESP3 协议支持:HELLO 握手、配置与降级兼容全解析
Envoy Redis Proxy 的 RESP3 协议支持HELLO 握手、配置与降级兼容全解析【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读本文围绕 Envoy 项目中 Redis 代理过滤器Redis Proxy Filter新增的RESP3 协议支持展开讲解如何通过新的protocol_version监听器配置让代理以 RESP3 协议与下游客户端、上游 Redis 后端通信并深入剖析其底层的HELLO 3握手机制、-NOPROTO拒绝策略、downstream_rq_noproto与upstream_resp3_hello_failure两个新统计项以及 RESP3 编解码器对全部帧类型的支持与对 RESP2 连接的降级转换。读完本文你将掌握在 Envoy 中启用 Redis RESP3 的配置方法、理解其连接生命周期与故障行为并能在生产环境中正确排障。一、背景Redis 协议演进与代理的角色Redis 自 6.0 起引入 RESP3 协议相比 RESP2 增加了 Map、Set、Push、Double、BigNumber、VerbatimString、BlobError、Boolean 等新数据类型为客户端提供了更丰富的语义如推式消息、精确浮点。然而 Redis 代理长期停留在 RESP2 时代。Envoy 的 Redis 代理过滤器网络过滤器envoy.filters.network.redis_proxy新增的 RESP3 支持让代理既能作为 RESP3 入口为现代客户端服务又能在后端仍是 RESP2 场景下平滑工作。该特性对应的变更记录见 redis_proxy__resp3-protocol-support.rst其核心能力可归纳为四件事新增监听器级配置protocol_version默认RESP2保持原有行为下游客户端需通过显式HELLO 3完成协议协商每个新建的上游连接自动执行HELLO 3握手可叠加AUTH、AWS IAM 凭证与READONLY编解码器理解全部 RESP3 帧类型并对 RESP2 连接做降级转换。下面逐一深入。二、核心配置protocol_version字段2.1 配置位置与默认值RESP3 支持由RedisProxy.protocol_version字段控制位于 proto 定义 api/envoy/extensions/filters/network/redis_proxy/v3/redis_proxy.proto 中字段编号 12[#next-free-field: 13]。它是一个枚举类型enum ProtocolVersion { // Default. 监听器在上下游都讲 RESP2不向上游发送 HELLO 3 // 下游发来的 HELLO 3 以 -NOPROTO 拒绝。 RESP2 0; // 监听器在上下游都讲 RESP3。上游连接池在新连接上协商 HELLO 3 // 下游客户端必须在任何数据命令前完成显式 HELLO 3 握手。 RESP3 1; }默认值为RESP2即不配置该字段时行为与以往完全一致不向上游发送HELLO 3下游HELLO 3也会被-NOPROTO拒绝。这一点保证了向后兼容已有配置无需任何改动即可平滑升级。注意 proto 注释中的关键语义RESP3 感知的周边能力本地HELLO应答、CLIENT SETINFO/SETNAME接受、RESP3 解码器在两种模式下始终存在该字段只控制实际协商的线上协议版本。也就是说即使保持 RESP2现代客户端也能完成连接初始化见第五节。2.2 完整配置示例在 Envoy 的监听器过滤器链中配置一个 RESP3 Redis 代理static_resources: listeners: - name: redis_resp3_listener address: socket_address: address: 0.0.0.0 port_value: 6379 filter_chains: - filters: - name: envoy.filters.network.redis_proxy typed_config: type: type.googleapis.com/envoy.extensions.filters.network.redis_proxy.v3.RedisProxy stat_prefix: redis_proxy_resp3 protocol_version: RESP3 # 关键开关默认 RESP2 settings: op_timeout: 5s prefix_routes: catch_all_route: cluster: redis_cluster字段含义protocol_version: RESP3本监听器的上下游连接均使用 RESP3 线上协议stat_prefix统计前缀下文新增计数器的完整名称即redis_proxy_resp3.downstream_rq_noproto等settings.op_timeout上游命令超时prefix_routes.catch_all_route.cluster路由到的 Redis 上游集群。2.3 配置生效范围从 redis_proxy.proto 的字段注释可以看出protocol_version同时约束下游连接与所有被路由的上游连接池下游版本不匹配的协商在HELLO处即被拒绝HELLO N中N不匹配返回-NOPROTO上游当设为RESP3时每个新建连接都执行HELLO 3协商任何不支持 RESP3 的后端如 Redis 5.x都会协商失败表现为upstream_resp3_hello_failure计数递增因此启用 RESP3 前必须确认所有上游 Redis 兼容后端支持HELLO 3/ RESP3Redis 6.0RESP3 在该版本引入。上游要求的RedisProtocolOptions认证凭据与protocol_version相互独立RESP3 模式下上游连接会先携带凭据执行HELLO 3见第四节。三、下游握手显式HELLO 3与-NOPROTO门控3.1 协商规则当监听器设为RESP3时下游客户端必须先发出显式的HELLO 3命令完成握手之后才能发送任何数据命令。握手前的规则允许通过的命令只有HELLO、AUTH、QUIT三个其余任何命令数组都会被拒绝返回-NOPROTO裸HELLO不带版本参数继承当前连接已协商的版本因此新连接上的裸HELLO会因版本不匹配同样被拒绝。3.2 源码中的门控实现这一门控逻辑实现在ProxyFilter::processRespValue()见 proxy_filter.cc// Pre-HELLO gate on RESP3 listeners: only HELLO / AUTH / QUIT pass until HELLO 3 lands; if (config_-protocolVersion() Common::Redis::RespProtocolVersion::Resp3 downstream_resp_version_ 3 value-type() Common::Redis::RespType::Array !value-asArray().empty() value-asArray()[0].type() Common::Redis::RespType::BulkString) { const std::string cmd absl::AsciiStrToLower(value-asArray()[0].asString()); if (cmd ! Common::Redis::SupportedCommands::hello() cmd ! Common::Redis::SupportedCommands::auth() cmd ! Common::Redis::SupportedCommands::quit()) { // Operational signal: a client sent a data command on a RESP3 listener before // completing the HELLO 3 handshake. config_-stats_.downstream_rq_noproto_.inc(); request.onResponse( Common::Redis::Utility::makeError(CommandSplitter::Response::get().UnsupportedProtocol)); return; } }关键点仅当a监听器为 RESP3、b当前下游协商版本 3、c命令为数组且首元素为 BulkString 时触发。命令被小写化后与白名单比较命中白名单hello/auth/quit放行否则递增downstream_rq_noproto并返回-NOPROTO错误。畸形请求则落入 splitter 的无效请求处理路径。3.3 计数器downstream_rq_noproto该计数器在 proxy_filter.h 的ALL_REDIS_PROXY_STATS宏中定义COUNTER(downstream_cx_tx_bytes_total) COUNTER(downstream_rq_noproto) COUNTER(downstream_rq_total)downstream_rq_noproto统计的是预握手门控拒绝的请求数即客户端在 RESP3 监听器上、完成HELLO 3之前就发送的数据命令数量。注意它不计入 HELLO 版本不匹配的情况——proto 注释与源码注释都明确区分了这两类拒绝“Counts only this pre-HELLO gate, not HELLO-version mismatches”。在运维层面该计数器持续增长通常意味着下游客户端库未显式执行HELLO 3、或客户端配置的协议版本与监听器设置不一致。四、上游连接自动HELLO 3握手与请求重放4.1 握手流程与下游要求显式协商不同上游方向由代理自动发起HELLO 3每当连接池为某个 host 新建连接时都会在ClientImpl::initialize中执行 RESP3HELLO 3协商流程为发送HELLO 3若配置了RedisProtocolOptions凭据username/password则与AUTH合并执行若配置了 AWS IAM 认证则携带 IAM 凭证执行适用场景下如集群分片后端随后发送READONLY全部成功后连接才对外服务流量。握手时机由upstream_protocol_version_参数驱动见 conn_pool_impl.ccclient-redis_client_ client_factory_.create(host, dispatcher_, config_, redis_command_stats_, *(stats_scope_), credentials.username, credentials.password, false, aws_iam_config_, aws_iam_authenticator_, upstream_protocol_version_, makeOptRef(redis_cluster_stats_.upstream_resp3_hello_failure_)); // RESP3 HELLO 3 negotiation runs inside ClientImpl::initialize (driven by the // upstream_protocol_version_ argument passed into create above). User requests // dispatched against this client before the handshake completes are held by // ClientImpls held-user-request queue and replayed in order on negotiation success.4.2 握手期间的请求处理排队与按序重放握手完成前到达的用户请求不会丢失也不会乱序执行它们被存放在ClientImpl的 held-user-request 队列中待协商成功后按原始顺序依次重放。conn_pool_impl.cc注释明确说明事务客户端交易型客户端走与数据客户端相同的ClientImpl初始化路径在HELLO 3以及适用时的READONLY成功之前请求同样被保持。这种设计保证了 RESP3 切换对业务请求的透明性——握手只是增加了连接的初始化延迟而不改变命令的语义与顺序。4.3 计数器upstream_resp3_hello_failure上游协商失败由按集群统计的upstream_resp3_hello_failure追踪定义于 conn_pool_impl.hCOUNTER(upstream_resp3_hello_failure)在 conn_pool_impl.cc 与第 474 行该计数器被作为可选引用传入客户端工厂。当监听器设为 RESP3 而某个上游不支持HELLO 3典型如 Redis 5.x 及更早版本时该集群的每条连接都会在协商阶段失败并递增该计数。这是判断“上游是否支持 RESP3”最直接的观测指标若该计数器持续增长应检查对应集群的 Redis 版本需 6.0与认证配置。4.4 上游认证的叠加上游HELLO 3并非孤立执行而是与既有认证体系合流RedisProtocolOptions.Credential按地址匹配的username/password会在HELLO 3中一并完成AUTHAWS IAM 认证同样支持配置了 IAM 时握手携带 AWS IAM 凭证对只读分片后端会在适用时追加READONLY。这意味着升级到 RESP3 不需要改变上游认证方式只需确保后端协议版本达标。五、本地应答HELLO / CLIENT SETNAME / CLIENT SETINFO5.1 动机现代 Redis 客户端库如 lettuce、node-redis v4、redis-py protocol3在连接初始化时通常会主动发送HELLO、CLIENT SETNAME、CLIENT SETINFO等命令。若代理将这些命令原样转发给上游不仅多一次往返还可能因上游与客户端属性不同而产生语义错位。因此无论protocol_version取值如何代理都会本地应答这三类命令让现代客户端顺利完成连接初始化。5.2 HELLO 的本地应答细节HELLO 命令由命令拆分器CommandSplitter本地处理见 command_splitter_impl.cc 相关逻辑。关键行为版本精确匹配HELLO N中显式的N或裸HELLO继承的当前连接版本必须与protocol_version完全一致否则返回错误内联认证HELLO N AUTH user pass可内联认证。该命令在connectionAllowed门控之前处理因为 RESP3 客户端node-redis v4、redis-py protocol3习惯通过 HELLO 认证——若先跑认证门控这类首条命令会被NOAUTH拒绝外部认证协同当配置了外部认证服务RedisExternalAuthProvider时HELLO N AUTH ...会走外部认证往返期间返回控制权随后由ProxyFilter补发延迟的 HELLO 应答成功为 HELLO Map失败为错误见 command_splitter.h 的接口注释SETNAME 选项HELLO N SETNAME name被接受但有意忽略——代理不需要记录客户端名接受它仅为避免 RESP3 客户端的握手报错见 command_splitter_impl.cc重复的 AUTH 或 SETNAME 选项返回语法错误未知选项返回ERR Syntax error: unknown HELLO optionHELLO 应答在本地构建为MapRESP3 下游直接获得%7\r\n...形式的 Map编码器会对 RESP2 下游降级转换字段名集中定义在 command_splitter_impl.cc 的 constexpr string_view 中。HELLO 应答中还包含server: redis、版本信息等字段。值得注意的实现细节HELLO 的应答版本号只广告 RESP3 引入版本 6.0.0 这一下限而非具体上限见 command_splitter_impl.cc 的注释——因为代理无法知晓背后集群的真实版本广告一个“地板”而非“天花板”更诚实且兼容。另外command_splitter.h的接口注释强调HELLO 在故障注入之前被分发“HELLO is dispatched before fault injection runs and so does not flow through”见 command_splitter_impl.h。也就是说即使配置了 Redis 故障注入握手命令也不会被注入故障保证协商路径的确定性。5.3 CLIENT SETNAME / SETINFO 的本地应答CLIENT命令中仅有SETNAME与SETINFO两个子命令被本地拦截见 command_splitter_impl.ccCLIENT SETNAME name3 个 tokenCLIENT SETINFO attr value4 个 token其余CLIENT子命令走通用处理器。拦截后代理返回本地成功应答避免这些“连接级元数据”命令产生上游往返。5.4 HELLO Map 与版本翻转连接上的下游版本翻转由setDownstreamRespVersion()完成见 command_splitter.h。源码注释强调在发出 HELLO Map 之前先翻转下游版本这样应答本身以及随后的流水线命令都能用新版本正确编码——这避免了“先答旧版本、再切新版本”导致的客户端解析错乱见 proxy_filter.cc 附近注释。六、编解码器RESP3 全帧类型与 RESP2 降级6.1 RESP3 帧类型全覆盖编解码器位于 source/extensions/filters/network/common/redis/codec.hRespType枚举完整覆盖 RESP3 规范注释直接引用 redis-specifications 的 RESP3 文档enum class RespType { // RESP2 types Null, SimpleString, BulkString, Integer, Error, Array, CompositeArray, // RESP3 types Boolean, // #t\r\n or #f\r\n Double, // ,floating-point-number\r\n BigNumber, // (big number\r\n BlobError, // !length\r\nerror\r\n VerbatimString, // length\r\nencoding:data\r\n Map, // %count\r\n (count key-value pairs, stored as 2*count array elements) Set, // ~count\r\n Push, // count\r\n };除了继承自 RESP2 的基础类型其中CompositeArray是为性能优化而生的零拷贝变体RESP3 新增的Boolean、Double、BigNumber、BlobError、VerbatimString、Map、Set、Push全部被解析。RespValue采用 C11 union 变体实现见 codec.h避免不必要的堆分配保证高吞吐场景下的性能。6.2 错误语义与推送帧错误类型统一判断isError()同时覆盖 RESP2 的Error与 RESP3 的BlobError见 codec.h上层逻辑无需区分两种错误帧Push 帧RESP3 的推式消息如 Pub/Sub 推送以RespType::Push表示客户端实现client_impl.cc会对 Push 类型做专门处理。6.3 对 RESP2 连接的降级转换RESP2 没有 Map、Set、Double 等类型因此 RESP3 帧在发往 RESP2 下游时必须降级。codec.h 中的注释给出转换规则Double/BigNumber在 RESP2 下编码为 BulkString如 BigNumber 由(digits\r\n转为$len\r\ndigits\r\n见 codec.hVerbatimString在 RESP2 下编码时剥离xxx:编码前缀见 codec.h 注释Map/Set 在 RESP2 下转为扁平 Array这在命令拆分器的响应处理中有明确体现见 cluster_response_handler.cc 的注释——即使分片返回 RESP3 Map也会扁平化为 Array 再发出理由有三一是避免 RESP2 客户端对重复 key 的重复处理二是与 RESP2 时代的基线行为保持稳定三是代理接受 RESP3 上游分片的 Map 是因为底层存储本就返回这类结构。因此在混合版本场景上游 RESP3、下游 RESP2下客户端拿到的仍是兼容的 Array 结构。这种“上游取新、下游兼容”的设计使代理可以在后端与客户端协议不一致的复杂拓扑中充当版本翻译层。七、可观测性与排障指引7.1 新增统计项一览统计项定义文件触发场景运维含义downstream_rq_noprotoproxy_filter.hRESP3 监听器上客户端在完成HELLO 3前发送数据命令客户端未执行显式 HELLO 3或客户端协议设置与监听器不一致upstream_resp3_hello_failureconn_pool_impl.h上游新建连接执行HELLO 3协商失败按集群统计上游 Redis 版本低于 6.0或认证/AWS IAM 配置与后端不匹配注意downstream_rq_noproto只统计预握手门控的拒绝不包含 HELLO 版本不匹配的拒绝upstream_resp3_hello_failure按集群维度统计可用于区分哪个上游集群不兼容。7.2 典型排障场景客户端报-NOPROTO检查客户端是否在发送数据命令前执行了HELLO 3同时核对客户端配置的协议版本与监听器protocol_version是否一致HELLO 版本精确匹配HELLO 2打到 RESP3 监听器同样被拒。upstream_resp3_hello_failure增长确认对应集群的 Redis 版本 ≥ 6.0若使用 AWS IAM 或账号密码认证核对RedisProtocolOptions配置与 IAM 凭证是否有效。命令顺序与丢请求担忧无需担心——握手期间的请求被 held 队列保存并按序重放协商成功后按原顺序执行。7.3 升级路径建议保持默认RESP2先升级 Envoy 二进制本地 HELLO 应答、CLIENT SETNAME/SETINFO拦截、RESP3 解码能力已默认启用客户端连接初始化会变顺畅确认所有上游集群 Redis 版本 ≥ 6.0 后将监听器protocol_version切换为RESP3灰度观察downstream_rq_noproto与upstream_resp3_hello_failure两个计数器确认下游客户端均完成显式HELLO 3、上游协商全部成功后再全量推广。八、总结Envoy Redis 代理的 RESP3 支持以protocol_version为开关构建了一套完整的双端协议协商体系下游要求显式HELLO 3前置数据命令被-NOPROTO拒绝并计数上游连接自动完成HELLO 3叠加 AUTH/AWS IAM/READONLY失败由upstream_resp3_hello_failure追踪握手期间的请求被安全排队并按序重放同时代理本地应答HELLO、CLIENT SETNAME、CLIENT SETINFO以兼容现代客户端初始化编解码器完整支持 RESP3 全帧类型并对 RESP2 连接做优雅降级。这一设计让代理既能作为 RESP3 的统一入口又能在混合版本拓扑中充当协议翻译层是升级 Redis 基础设施时值得优先采用的特性。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Umi-OCR 快速上手:Linux 离线文字识别工具,5 分钟装好,截图、批量、扫码一次跑通 2026/9/12 21:31:23

Umi-OCR 快速上手:Linux 离线文字识别工具,5 分钟装好,截图、批量、扫码一次跑通

Umi-OCR 快速上手:Linux 离线文字识别工具,5 分钟装好,截图、批量、扫码一次跑通 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页…

阅读更多 →
2026数学建模国赛D题:时频冲突检测与消解 论文解析 2026/9/12 21:31:23

2026数学建模国赛D题:时频冲突检测与消解 论文解析

专栏内持续更新ABCDE题思路代码论文,只需订阅一次,无需重读订阅 演示视频: 时频冲突检测与消解 2026年高教社杯全国大学生数学建模竞赛

阅读更多 →
实测 3 大 Python API 框架:1000 万请求后,一个直接被 OOM killer 干崩 2026/9/12 21:31:23

实测 3 大 Python API 框架:1000 万请求后,一个直接被 OOM killer 干崩

一、凌晨 2 点的告警,击碎 “生产就绪” 的谎言进行后端开发的人群当中, 有谁未曾听闻过“现代ASGI 框架稳定坚固得如同老狗一般”这样的一种说法呢, 大家普遍默认, 只要能够挑选出正确的主流框架, 承受住每秒达到1万次请求的情况, 面对千万级别的并发也全然不是难题…

阅读更多 →
Smali 语法基础 2026/9/12 21:31:23

Smali 语法基础

Smali 语法基础 Smali 是 DEX 字节码的汇编语言表示:APK 中的 DEX 文件经 baksmali/apktool 反汇编后得到 .smali 文件,每条 smali 指令与 DEX 字节码一一对应、语义等价。修改 smali 后可以重新汇编成 DEX 并打包回 APK——这也是修改 App 功能&#xf…

阅读更多 →
Python文本分析实战:从基础到项目开发 2026/9/12 21:31:23

Python文本分析实战:从基础到项目开发

1. Python第五次作业:从零基础到实战项目作为一名Python开发者,我经常被问到"学完基础语法后该做什么"。第五次作业往往是一个关键转折点,标志着从语法学习转向实际应用。这次作业通常会要求学生综合运用前四次学到的变量、循环、条…

阅读更多 →
Vant `useRect` 组合式函数完全指南:获取元素尺寸与视口相对位置 2026/9/12 21:28:22

Vant `useRect` 组合式函数完全指南:获取元素尺寸与视口相对位置

Vant useRect 组合式函数完全指南:获取元素尺寸与视口相对位置 【免费下载链接】vant A lightweight, customizable Vue UI library for mobile web apps. 项目地址: https://gitcode.com/GitHub_Trending/va/vant useRect 是 vant/use 提供的一个轻量级组合…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞