拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Envoy gRPC HTTP/1.1 Bridge 过滤器:让不支持 Trailers 的 HTTP/1.1 客户端接入 gRPC 服务

Envoy gRPC HTTP/1.1 Bridge 过滤器让不支持 Trailers 的 HTTP/1.1 客户端接入 gRPC 服务【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoygRPC HTTP/1.1 Bridge 是 Envoy 中一个精简而实用的 HTTP 过滤器它的核心价值在于当你的客户端只支持 HTTP/1.1无法处理响应尾随头 trailers时仍然可以调用标准 gRPC 服务。本文以 grpc_http1_bridge_filter.rst 为主线结合 Envoy 仓库中的 proto 定义与 C 实现源码系统讲解该过滤器的工作原理、请求/响应帧格式、Protobuf 升级支持、查询参数清理以及统计指标并给出可直接落地的配置示例。一、为什么需要 gRPC HTTP/1.1 BridgegRPC 协议在标准实现中依赖 HTTP/2其响应中的调用结果如grpc-status、grpc-message是通过trailers尾随头在消息末尾携带的。HTTP/1.1 协议本身并不原生支持 trailers 语义因此一个仅支持 HTTP/1.1 的客户端通常无法直接与 gRPC 服务端正常交互——它看不到响应结尾的 gRPC 状态信息也就无法判断调用是成功还是失败、失败原因是什么。Envoy 的grpc_http1_bridge过滤器正是为打通这一断层而设计它作为一个透明的中间转换层接收 HTTP/1.1 客户端发来的 gRPC 风格请求将其转发给上游 gRPC 服务再在返回路径上把 gRPC trailers 中的关键信息改写进 HTTP/1.1 响应头从而让不支持 trailers 的客户端也能看懂 gRPC 调用的结果。该过滤器的配置类型 URL 为type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config其 proto 定义见 config.proto对应扩展名称为envoy.filters.http.grpc_http1_bridge。二、过滤器的工作机制从源码实现看过滤器核心类Http1BridgeFilter见 http1_bridge_filter.h 与 http1_bridge_filter.cc在请求解码与响应编码两个方向上分别做了拦截。其整体判定逻辑如下请求侧判定当请求到达时decodeHeaders过滤器检查两件事——当前连接协议是否为 HTTP/1.1protocol Http::Protocol::Http2以及请求的content-type是否为application/grpc。两者同时满足时置位do_bridging_进入桥接模式。响应侧拦截进入桥接模式后encodeHeaders阶段会拦截响应头并缓存StopIterationencodeData阶段缓冲响应体一直等到encodeTrailers阶段拿到 gRPC trailers 为止。状态改写在encodeTrailers中读取grpc-status若该值非零或解析失败则将 HTTP 响应码改写为503 Service Unavailable随后把grpc-status与grpc-message两个 trailer 的值复制到响应头中供客户端读取。补充 Content-Length由于响应被缓冲过滤器还会依据编码缓冲区长度设置content-length响应头让 HTTP/1.1 客户端能更准确地判断响应是否完整对应源码中encodeTrailers内的setContentLength调用。上述必须缓冲完整响应才能看到 grpc-status trailer的特性决定了该方案仅适用于 unary一元gRPC API流式streamingAPI 无法使用此过滤器桥接。请求侧的伪头部约定客户端向 Envoy 发送的 HTTP/1.1 请求需要满足以下伪头部pseudo header约定伪头部 / 头字段取值:methodPOST:pathgRPC-METHOD-NAME例如/helloworld.Greeter/SayHellocontent-typeapplication/grpc请求体则是序列化后的 gRPC 帧其字节布局固定为1 字节的帧标志位值为0表示未压缩4 字节**网络字节序大端**的 proto 消息长度序列化后的 proto 消息本体。该 wire format 即 gRPC over HTTP/2 协议规范中定义的帧结构详见 gRPC 官方文档《gRPC over HTTP/2》HTTP/1.1 桥接复用了同一套帧格式。三、过滤器配置示例以下是一个完整的 Envoy 静态配置片段展示了如何在 HTTP 连接管理器HttpConnectionManager中挂载该过滤器static_resources: listeners: - name: grpc_http1_bridge_listener address: socket_address: address: 0.0.0.0 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: type: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager codec_type: AUTO stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: backend domains: [*] routes: - match: prefix: / route: cluster: grpc_backend http_filters: - name: envoy.filters.http.grpc_http1_bridge typed_config: type: type.googleapis.com/envoy.extensions.filters.http.grpc_http1_bridge.v3.Config upgrade_protobuf_to_grpc: false ignore_query_parameters: true - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: grpc_backend type: STRICT_DNS typed_extension_protocol_options: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: type: type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: http2_protocol_options: {} load_assignment: cluster_name: grpc_backend endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 50051要点说明http_filters列表中该过滤器需位于router过滤器之前上游集群需配置为 HTTP/2 协议如示例中通过HttpProtocolOptions指定http2_protocol_options因为 gRPC 服务端以 HTTP/2 通信typed_config中的两个布尔字段均有默认值false按需开启。配置工厂的注册逻辑位于 config.cc通过LEGACY_REGISTER_FACTORY以envoy.grpc_http1_bridge名称注册Config消息的两个字段upgrade_protobuf_to_grpc字段号 1与ignore_query_parameters字段号 2在构造过滤器实例时被读取并保存为成员状态。四、Protobuf 升级支持upgrade_protobuf_to_grpc某些场景下客户端只能发送普通的application/x-protobuf请求而服务端是标准 gRPC 服务。此时可开启配置项upgrade_protobuf_to_grpc过滤器会自动完成普通 Protobuf 请求 → gRPC 请求的升级在decodeHeaders阶段若检测到请求content-type为application/x-protobuf源码通过Grpc::Common::isProtobufRequestHeaders判定则将content-type改写为application/grpc并置位do_framing_在decodeData阶段请求体被缓冲待流结束时调用Grpc::Common::prependGrpcFrameHeader在消息体前面拼接 gRPC 帧头即上文所述 1 字节标志 4 字节长度再转发给上游 gRPC 服务若客户端携带了content-length头过滤器会将其移除removeContentLength因为实际消息长度已由 gRPC 帧内的长度字段表达原头可能与之冲突反向路径上响应返回给客户端前过滤器会从首个数据块中剥离 gRPC 帧头data.drain(Grpc::GRPC_FRAME_HEADER_SIZE)使客户端收到的响应体只包含纯 Protobuf 编码数据与它发送请求时的格式保持一致。注意当upgrade_protobuf_to_grpc生效时过滤器还会调用downstreamCallbacks()-clearRouteCache()清除路由缓存确保改写 content-type 后仍按正确的路由规则转发。帧头常量与编解码gRPC 帧头的大小与格式由 Envoy 的公共 gRPC 编解码模块Grpc::Common见 source/common/grpc/common.h 与 codec.h统一提供prependGrpcFrameHeader负责在缓冲前拼接帧头GRPC_FRAME_HEADER_SIZE定义帧头长度。这也是升级路径与桥接路径共用同一套 wire format 的基础。五、忽略查询参数ignore_query_parameters部分客户端的请求 URL 中可能携带查询参数例如/helloworld.Greeter/SayHello?foobar。而 gRPC 上游服务端无法处理这类请求通常会返回unknown method之类的错误。为此过滤器提供了ignore_query_parameters配置项开启后在请求解码阶段decodeHeaders会调用ignoreQueryParams方法该方法读取:path值找到第一个?的位置截取?之前的路径部分写回请求头headers.setPath(new_path)从而把查询参数从 URL 中剥离注意该逻辑仅在桥接模式do_bridging_下执行。从测试用例见 http1_bridge_filter_test.cc 中的initialize(bool upgrade_protobuf, bool ignore_query_params)构造方式可以看出这两个配置项在单元测试中分别以布尔参数独立开启、组合验证属于过滤器的两个正交能力维度。六、统计指标过滤器会为所有途经的 gRPC 请求收集统计信息——需要说明的是这里包括正常的 HTTP/2 及以上的 gRPC 请求并非仅限被桥接的 HTTP/1.1 请求。指标命名空间为cluster.route target cluster.grpc.即按请求路由到的目标集群维度隔离。名称类型描述grpc service.grpc method.successCounterservice/method 调用成功的总次数grpc service.grpc method.failureCounterservice/method 调用失败的总次数grpc service.grpc method.totalCounterservice/method 调用的总次数例如请求POST /helloworld.Greeter/SayHello路由到集群grpc_backend则对应指标名为cluster.grpc_backend.grpc.helloworld.Greeter.SayHello.success、.failure与.total。重要提醒gRPC 遥测请使用专用过滤器原文档特别以 attention 形式提醒统计数据的采集应由专用的 gRPC Stats 过滤器envoy.filters.http.grpc_stats承担本过滤器用于 gRPC 遥测统计的能力已被禁用。换言之若你的主要诉求是 gRPC 可观测性成功率、失败率、延迟等应挂载grpc_stats过滤器grpc_http1_bridge的定位是协议桥接而非遥测采集。这也是在实际配置中容易出现的误区。七、局限性与适用边界综合原文档与源码实现使用该过滤器前需要明确以下边界仅支持 unary API由于必须缓冲完整响应以等待grpc-statustrailer流式server-streaming / client-streaming / bidi-streaminggRPC API 无法通过本过滤器桥接面向不支持 trailers 的 HTTP/1.1 客户端若客户端本身支持 HTTP/2 与 trailers如多数现代 gRPC 客户端应直接使用 gRPC over HTTP/2无需此过滤器错误呈现方式有限非零grpc-status会被统一映射为 HTTP 503客户端如需精细区分 gRPC 错误码应读取响应头中被复制的grpc-status/grpc-message字段缓冲代价响应全量缓冲意味着内存占用与首字节延迟的权衡在高并发大响应场景下需评估资源开销遥测已禁用不要依赖本过滤器做 gRPC 统计改用专用grpc_stats过滤器。仓库中针对该过滤器还有集成测试 grpc_http1_bridge_integration_test.cc 与配置解析测试 config_test.cc可进一步阅读以验证桥接、Protobuf 升级、查询参数剥离等行为在真实请求链路上的表现。八、总结gRPC HTTP/1.1 Bridge 过滤器以极小的配置代价解决了老客户端 新协议的兼容难题它把 gRPC 的 trailers 语义翻译成 HTTP/1.1 客户端可理解的响应头把grpc-status非零错误映射为 503并提供upgrade_protobuf_to_grpc与ignore_query_parameters两个实用开关分别处理纯 Protobuf 客户端与带查询参数请求的接入场景。在网关迁移、存量系统对接 gRPC 后端、浏览器/嵌入式客户端等无法升级协议栈的现实场景中它都是值得优先考虑的桥接方案——只需记住它的 unary-only 限制与遥测职责的划分。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门