DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Nginx gRPC 报 too large http2 frame,检查 Fabio 的监听协议

gRPC 请求返回502和 too large http2 frame,核对 Nginx 下一跳与 Fabio 的监听端口、协议及RPC路由。

gRPC 客户端经过 Nginx 返回 502,错误日志同时出现 upstream sent too large http2 frame,上游地址是 grpc://127.0.0.1:9999。如果这个端口实际属于 Fabio,先确认 Fabio 在该端口接收的是 gRPC,还是普通 HTTP。客户端到 Nginx 已经使用 HTTP/2,不能证明 Nginx 到下一跳也用了正确协议。

这里处理的是 Nginx 经 Fabio 转发 gRPC 的场景。Fabio 没有显式指定 proto 时,监听协议按配置采用 HTTP 或 HTTPS;单独建立一个普通 HTTP 监听,不会因为后面挂着 gRPC 服务就自动变成 gRPC 代理。这个错误也可能有其他原因,必须先对照实际连接端口和响应协议。

从日志中的下一跳查起

找到对应请求的新日志,核对 upstream 的主机、端口和 scheme。不要把公开 443 端口、Fabio 的代理端口和应用容器端口混在一起。Nginx、Fabio 若处于不同容器,127.0.0.1 指向 Nginx 自己的网络命名空间,还要先确认它确实能到达该监听。

Nginx 的 grpc_pass grpc://... 用于不带 TLS 的 gRPC 上游,grpcs://... 用于带 TLS 的上游,两者都要求下一跳提供相应协议。把一端配置为 gRPC、另一端仍返回 HTTP/1 响应时,应修正监听和转发关系,不能先靠放大缓冲区解释为真正的超大 HTTP/2 帧。

普通 REST 接口返回 200,也只能证明普通 HTTP 路径可用。排查应针对失败的 RPC 路径、Fabio 实际监听配置和对应日志,不要用首页能打开代替 gRPC 验证。

明确 gRPC 监听,并让 Nginx 使用同一个端口

Fabio 的 fabio.properties 可以显式配置 gRPC 监听。以下以本机回环 8888 为例,仅适用于 Nginx 能在同一网络环境访问它的部署:

proxy.addr = 127.0.0.1:8888;proto=grpc

已有多监听配置时,应按现有格式合入所需监听,不要覆盖普通 HTTP、HTTPS 或其他业务端口。另一个容器需要访问 Fabio 时,应选用受网络和访问规则约束的可达地址,而不是直接扩大到所有公网接口。

Nginx 对应的代理位置必须同步指向这个监听。例如合入原有 server 的片段:

location / {
    grpc_pass grpc://127.0.0.1:8888;
}

这是端口和协议配对示例,不包含完整站点配置。保留原有入口 TLS、认证和 RPC 路由;如果原 location 中还有必要的 gRPC 请求头和超时设置,也要保持。只新增 8888 监听,却让 Nginx 继续请求旧的 9999,仍会访问原来的协议。

实际下一跳要求 TLS 时,应沿用 grpcs 监听及其证书配置,不要为了消除报错把受保护的链路改成明文。grpc_ssl_* 与普通 HTTP 代理的 proxy_ssl_* 是不同模块的指令,也不能把后者直接复制给 gRPC 上游。

监听正确后,再确认 Fabio 知道 RPC 去哪里

Fabio 的 gRPC 代理还需要服务注册或路由信息。采用 Consul 注册时,服务应广告实际 RPC 服务或方法,例如 urlprefix-/my.service/Method proto=grpc;其中的服务名与方法名必须替换为应用的真实值。

建立监听不等于自动发现所有容器。继续核对注册地址、端口、健康检查和协议,以及 Fabio 到应用的链路。不要把这里的示例包名和方法名当成固定规则,也不要为了路由成功放开原有访问控制。

修改前保存 Nginx 和 Fabio 配置。用实际实例的配置检查方式确认语法和端口条件,再按部署原有方式加载;Nginx 的检查应针对同一配置文件、二进制和网络环境。加载后调用原来失败的只读或受控 RPC,确认请求到达目标应用,RPC 状态、响应和 trailer 符合预期,不再新增同一上游协议错误。

如果帧错误消失后出现服务找不到、授权失败或应用状态错误,应处理新的具体分支。需要撤回时恢复两侧配套的监听与代理配置,避免 Nginx 的目标端口与 Fabio 的实际监听再次错位。