必须用 grpc_pass 而非 proxy_pass;http/2 需显式启用,h2c 与 h2 配置逻辑不同;长连接失效主因是 upstream 与 client 端 keepalive 未配对;nginx -v 必须显示 --with-http_v2_module 和 --with-http_ssl_module。

必须用 grpc_pass,不能用 proxy_pass;HTTP/2 必须显式启用,明文(h2c)和 TLS(h2)配置逻辑完全不同;长连接不生效的根因几乎全是 keepalive 没配对。
nginx -V 要看到 --with-http_v2_module 和 --with-http_ssl_module
gRPC 依赖 HTTP/2,而 Nginx 默认不编译该模块。Ubuntu/Debian 的 apt 包通常已内置,但 CentOS/RHEL 的 EPEL 源需确认:
- 运行
nginx -V 2>&1 | grep -o http_v2,有输出才表示支持 - 若无,需源码编译并加
--with-http_v2_module --with-http_ssl_module -
http_v2和ssl模块缺一不可:即使走明文 h2c,Nginx 也要求ssl模块参与协议协商(这是常见盲区)
listen 指令必须带 http2 参数,且端口不能复用 HTTP/1.1
Nginx 不允许同一监听端口同时处理 HTTP/1.1 和 HTTP/2 请求。错误配置会导致 426 Upgrade Required 或静默失败:
- 明文 gRPC(开发测试):
listen 80 http2;—— 但注意:客户端必须显式发起 h2c 升级,多数语言 SDK 默认不支持,容易卡住 - TLS gRPC(生产必需):
listen 443 ssl http2;—— 这是唯一稳定路径 - 不要写
listen 443 http2 ssl;(顺序错会报错),必须是ssl http2
grpc_pass 后端地址协议决定加密行为,不能混用
grpc_pass 的 URL 前缀直接控制 Nginx 与后端的通信方式,和前端是否 TLS 无关:
-
grpc_pass grpc://127.0.0.1:50051;→ Nginx 到后端走明文 HTTP/2(SSL offloading 场景) -
grpc_pass grpcs://127.0.0.1:50051;→ Nginx 到后端也走 TLS,此时必须配grpc_ssl_certificate等指令 - 误用
proxy_pass http://...会导致 502,因为 gRPC 二进制帧被当普通 HTTP 解析,header 和 body 都错乱
keepalive 必须在 upstream 和 client 两端同时配,否则长连接失效
压测中出现大量 TIME_WAIT、Stream removed 错误,90% 是因为只配了客户端 keepalive,没配 upstream 的连接池:
- 客户端侧(server 块内):
keepalive_timeout 75s;控制空闲连接保持时间 - 后端侧(upstream 块内):
keepalive 2000;定义空闲连接池大小,keepalive_timeout 75s;必须与客户端侧一致,否则连接提前断开 - 漏掉 upstream 的
keepalive,Nginx 每次请求都新建 TCP 连接到后端,完全失去 HTTP/2 多路复用价值
最易被忽略的是:upstream 中的 keepalive 数值不是“最大连接数”,而是“空闲连接保留在池中的数量”;如果压测并发远超该值,仍会频繁建连。线上建议设为预期峰值并发的 1.5 倍以上。











