Nginx 1.13.10+ 启用 grpc_pass 必须同时编译 --with-http_v2_module 和 --with-http_ssl_module,否则指令不可用;配置需用 listen 443 ssl http2;,upstream 配 keepalive 且 grpc_pass 指向 upstream 名,禁用 grpc_buffering。

直接上结论:Nginx 1.13.10+ 编译时必须启用 --with-http_v2_module 和 --with-http_ssl_module,否则 grpc_pass 指令根本不可用,配置会报错或静默失效。
nginx -t 报 unknown directive "grpc_pass"
这是最常遇到的拦路虎。不是配置写错了,而是 Nginx 根本没编译进 gRPC 支持模块。
- 运行
nginx -V查看编译参数,确认输出中包含--with-http_v2_module(HTTP/2 是 gRPC 底层必需)和--with-http_ssl_module(即使走明文 h2c,多数客户端也要求 TLS 终止) - Ubuntu/Debian 官方源的 nginx 包通常不含
http_v2_module,必须源码编译;CentOS Stream 9+ 的nginx-all-modules包才默认启用 - 若用包管理器安装,优先选官方 nginx.org 的 repo(提供预编译含 v2 模块的版本),避免用系统默认源
listen 80 http2; 不生效,curl 或 grpcurl 返回 426 Upgrade Required
HTTP/2 在明文(h2c)下仅支持升级协商,而 Nginx 的 http2 参数仅对 ssl 监听生效——这是硬性限制,不是 bug。
- 生产环境必须用
listen 443 ssl http2;,搭配有效证书(自签名需客户端显式信任) -
listen 80 http2;实际被忽略,Nginx 仍按 HTTP/1.1 处理,导致 gRPC 客户端无法完成协议升级 - 测试阶段若坚持用明文,可改用
listen 8000 http2;+ 客户端强制 h2c(如 Go 的grpc.WithTransportCredentials(insecure.NewCredentials())),但 Nginx 配置里仍要写http2 on;(注意:不是listen ... http2)
压测出现 Stream removed 或 connection reset by peer
本质是 TCP 连接未复用,短连接风暴触发内核 TIME_WAIT 耗尽,而非 gRPC 协议层错误。
- 必须为 upstream 显式配置
keepalive:在upstream块里加keepalive 2000;(空闲连接池大小),否则每次请求都新建 TCP 连接 -
grpc_pass后端地址必须指向upstream名(如grpc_pass grpc://grpc_backend;),不能直写grpc://127.0.0.1:50051,否则 keepalive 不生效 - 检查后端 gRPC Server 是否启用了 HTTP/2(Go 默认开启;Java Netty 需显式设置
usePlaintext()或配置 TLS);若后端只监听 HTTP/1.1,Nginx 无法降级,直接断连
client_max_body_size 和 grpc_buffering 的取舍
gRPC 流式响应可能远超默认 1MB 限制,但盲目调大 buffer 反而引发粘包或延迟。
-
client_max_body_size必须设足够大(如1000m),否则大 payload 请求直接 413 -
grpc_buffering off;是关键:gRPC 二进制帧需透传,禁用 Nginx 内部缓冲,避免流式响应被截断或合并 -
grpc_buffer_size(如16k)仅控制单次读取缓冲区大小,不影响流式语义,可保留默认值
最容易被忽略的是:Nginx 的 upstream keepalive 和 grpc_pass 必须成对出现,缺一不可;另外所有超时指令(grpc_read_timeout 等)必须显式设长,因为流式调用可能持续数小时,而默认 60 秒会直接 kill 连接。











