要让Nginx稳定分发gRPC双向流请求,关键在于启用HTTP/2、配置upstream keepalive、延长grpc_read/send_timeout、禁用reset_timedout_connection,并使用least_conn负载均衡算法。

要让 Nginx 稳定分发 gRPC 双向流式请求(Bidirectional Streaming),关键不是简单转发,而是确保 HTTP/2 连接长期存活、流不被意外中断,并在多个后端间合理调度。gRPC 双向流依赖长连接和多路复用,Nginx 默认配置容易因超时或缓冲限制导致流中断,需针对性调优。
必须启用 HTTP/2 并正确编译 Nginx
Nginx 1.13.10+ 原生支持 gRPC,但前提是编译时启用了 --with-http_ssl_module 和 --with-http_v2_module。仅安装预编译包可能不包含 HTTP/2 支持。验证方式:
- 运行
nginx -V 2>&1 | grep -o http_v2,有输出才表示已启用 - 监听端口必须显式声明
http2,例如listen 80 http2;或listen 443 ssl http2; - 明文 HTTP/2(h2c)在非 TLS 端口上不可与 HTTP/1.1 共存,务必单独使用一个端口
配置 upstream 实现负载均衡
双向流适合用 least_conn 算法,避免新连接扎堆到已有大量活跃流的节点:
- 定义带健康检查的上游组:
upstream oap_cluster {<br> least_conn;<br> server 10.0.1.10:11800 max_fails=3 fail_timeout=30s;<br> server 10.0.1.11:11800 max_fails=3 fail_timeout=30s;<br> keepalive 32;<br>} -
keepalive 32表示每个 worker 进程对每个 upstream server 保持最多 32 个空闲连接,减少握手开销 - 避免使用
ip_hash——gRPC 客户端常复用连接池,固定 IP 易造成后端负载不均
适配双向流的关键 timeout 与 buffer 设置
默认超时值对长周期双向流极不友好,必须延长并禁用不适用的限制:
-
grpc_connect_timeout 10s;(建立连接阶段) -
grpc_send_timeout 300s;(客户端发数据间隔,如心跳间隔为 45s,则至少设为 60s) -
grpc_read_timeout 300s;(服务端响应或流数据到达间隔) -
grpc_buffer_size 128k;(避免大消息体被截断) - 务必关闭
reset_timedout_connection off;,防止 Nginx 主动重置“看似空闲”的流连接
日志与可观测性辅助排障
开启 gRPC 特定日志格式,快速定位流中断原因:
- 定义日志格式:
log_format grpc '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_addr $upstream_http_grpc_status'; - 记录
$upstream_http_grpc-status可识别 gRPC 层错误码(如0正常,14表示“unavailable”) - 配合
error_log /var/log/nginx/error.log warn;关注upstream timed out或connection reset类警告


















