用nginx做grpc反向代理,nginx到後端server不能維持長連線問題
公司內部容器平臺,接入層用nginx做LB,使用者有grpc協議需求,所以在lb層支援grcp反向代理,nginx從1.13開始支援grpc反向代理,將公司使用的nginx包從1.12升級到1.14.0後,增加grpc反向代理配置。配置完成後,打壓力測試時,發現接入層機器端口占滿而導致服務異常,開始追查問題。
追查方向
深入瞭解grpc協議
- gRPC是一個高效能、通用的開源 RPC 框架,其由 Google 主要面向移動應用開發並基於HTTP/2協議標準而設計,基於ProtoBuf(Protocol Buffers) 序列化協議開發,且支援眾多開發語言。gRPC 提供了一種簡單的方法來精確地定義服務和為 iOS、Android 和後臺支援服務自動生成可靠性很強的客戶端功能庫。客戶端充分利用高階流和連結功能,從而有助於節省頻寬、降低的 TCP 連結次數、節省 CPU 使用、和電池壽命。
從上述描述可以看出grpc基於http2,client到server應該保持長連線,理論上不應該出現端口占滿的問題
抓包
- client到接入層抓包看請求狀態,發現client到接入層確實是長連線狀態。接入層到後端server抓包發現,請求並沒有保持長連線,一個請求處理完之後,連結就斷開了。
查nginx跟長連線相關配置
- nginx長連線相關說明參考以下文件:nginx長連線
- nginx跟grpc長連線相關配置,發現在1.15.6版本引入了"grpc_socket_keepalive"跟grpc直接相關長連線配置
Configures the “TCP keepalive” behavior for outgoing connections to a gRPC server. By default, the operating system’s settings are in effect for the socket. If the directive is set to the value “on”, the SO_KEEPALIVE socket option is turned on for the socket.
參考nginx長連線相關文件做了配置調整之後,發現nginx到server依然是短連線
將nginx升級到nginx1.15.6(升級過程中由於線上的nginx用到了lua模組,碰到了lua模組不適配問題,解決方案見連結 lua模組適配問題 )配置grpc_socket_keepalive on,抓包發現,會有少量處理多個請求的長連線存在,但大部分依然是短連線。
- 開啟nginx debug模式
從debug日誌來看nginx確實嘗試重用連結,但是從實際抓包看,nginx的連結重用的情況非常少,大部分都是請求處理完之後連結斷開,懷疑nginx對grpc反向代理支援的不夠理想。