nginx 支持 grpc 的前提是版本 ≥ 1.13.10、编译启用 --with-http_v2_module 和 --with-http_ssl_module,运行时必须用 grpc_pass 代理、监听 https + http/2 端口,且后端需支持明文 h2c 或 tls;漏任一环节将导致 unavailable 或 426 错误。

直接说结论:Nginx 支持 gRPC 的前提是版本 ≥ 1.13.10、编译时启用 --with-http_v2_module 和 --with-http_ssl_module,运行时必须用 grpc_pass 代理、监听 HTTPS + HTTP/2 端口,且后端需支持明文 HTTP/2(H2C)或 TLS(gRPCs)。漏掉任一环节,调用大概率返回 UNAVAILABLE 或 426 Upgrade Required。
确认 Nginx 具备 gRPC 代理能力
很多问题不是配置写错,而是 Nginx 根本没编译进必要模块。先验证:
- 执行
nginx -V 2>&1 | grep -o http_v2,必须输出http_v2;若无,说明未启用 HTTP/2 模块,grpc_pass指令根本不可用 -
nginx -V 2>&1 | grep -o http_ssl同样必须有输出,否则 TLS 终止失败,客户端连不上 - 生产环境建议用
nginx:alpine(v1.25+)官方镜像,它默认含 v2 模块;源码编译时务必加全参数:./configure --with-http_v2_module --with-http_ssl_module --with-stream - 别信“装了就行”——
nginx -t通过不代表能跑 gRPC,必须用真实客户端(如grpcurl)测试流式调用
server 块必须严格匹配 gRPC 协议栈
gRPC 不是 HTTP,不能套用普通反向代理模板。关键点在监听和协议终止:
-
listen 443 ssl http2;—— 缺http2就降级成 HTTP/1.1,gRPC 调用直接失败 -
ssl_certificate和ssl_certificate_key必须指向有效证书;测试可用自签名,但客户端要加-insecure - 必须用
grpc_pass grpc://grpc_backend;,不是proxy_pass;后者会走 HTTP/1.1,触发502 Bad Gateway -
grpc_buffering off;—— 不关缓冲,流式响应(如日志 tail、实时监控)会被截断或延迟
upstream 需适配 gRPC 长连接特性
gRPC 客户端复用 TCP 连接,Nginx upstream 若不调优,会频繁建连断连,吞吐骤降:
-
keepalive 32;—— 每个 worker 缓存最多 32 个空闲连接到后端,避免反复握手 - 后端地址必须是明文 H2C(如
10.0.2.10:8080),不能是仅支持 TLS 的 gRPC 端口;若后端也启 TLS,改用grpcs://并配grpc_ssl_certificate -
max_fails=3 fail_timeout=30s;是被动健康检查基础,但 gRPC 更推荐主动探活(如 /health 端点 +health_check指令,Nginx Plus 支持,开源版需额外脚本) -
client_max_body_size 1000000000;—— 默认 1MB,大文件上传或长响应容易被截断,建议设为 1G
Ingress 场景下只需注解,但 TLS 不可省
Kubernetes 中用 Nginx Ingress 暴露 gRPC 服务,配置极简,但隐性依赖强:
- 必须加注解:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC",否则流量按 HTTP 处理 - TLS Secret 必须存在且正确引用(
secretName: nginx-ingress-tls),HTTP/2 在 Ingress 层强制依赖 TLS - 域名
host必须与证书 SAN 匹配,否则客户端证书校验失败;测试时可用grpcurl -insecure绕过,但生产环境必须配对 - Ingress controller 版本需 ≥ 1.0(对应 Nginx v1.21+),旧版注解不生效或静默忽略
最常被忽略的其实是后端服务本身——Nginx 配得再准,如果 gRPC Server 没启用 HTTP/2(比如 Go 的 grpc.Server 默认支持,但 Java 的 Netty 需显式配置 ALPN),整个链路依然不通。调试时优先查 error.log 里有没有 upstream rejected request with error 或 no live upstreams,比反复改配置更高效。











