前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >nginx使用长连接代理grpc流量

nginx使用长连接代理grpc流量

原创
作者头像
我有一只萌妹子
修改2022-10-09 18:42:56
3.3K3
修改2022-10-09 18:42:56
举报
文章被收录于专栏:编程碎碎念编程碎碎念

nginx使用长连接代理grpc流量

TOC

Nginx在1.13.10版本支持了对grpc流量的反向代理,恰好业务有需求,要在sidecar容器中代理grpc流量。因此参考指引文档进行了配置。但是并未如预期般顺利运行,按照示例配置后,nginx与后端的grpc服务并非长连接,导致了一系列问题,在此做个记录,也给有需要的读者做一个参考,对具体过程不感兴趣的可直接跳到最后查看完整配置。

踩坑过程

代码语言:text
复制
http {

    log\_format  main  '$remote\_addr - $remote\_user [$time\_local] "$request" '

                      '$status $body\_bytes\_sent "$http\_referer" '

                      '"$http\_user\_agent"';

    server {

        listen 80 http2;

 

        access\_log logs/access.log main;

 

        location / {

            grpc\_pass grpc://localhost:8500;

        }

    }

}

如上为官方实例中的转发配置,配置并重启nginx后,简单调用时没有遇到问题。但是在后续的压测环境中发现会出现偶发的Stream removed错误(如下图所示)。

image-20221009171824287
image-20221009171824287

分析HTTP2协议得知Stream即http2的一个请求,多个stream复用会同一个TCP连接,由此猜测应该是在压测的过程中,TCP连接发生了中断,因此进入nginx容器内部查看通过netstat查看连接情况,果然发现出现了大量的TIME_WAIT连接(如下图所示)。关于TIME_WAIT的含义,可参考https://draveness.me/whys-the-design-tcp-time-wait/

image-20221009163749322
image-20221009163749322

查询资料后发现发现在nginx的默认配置下,grpc与后端并不会使用连接复用,查阅相关资料后发现是没有配置keepalive相关参数导致的,keepalive用于配置与后端和客户端的连接保持,参数的具体含义参照官方说明或下文的配置注释。

代码语言:text
复制
http {

      # 与客户端的连接配置

    keepalive 2000;  # 允许的空闲连接数

    keepalive\_timeout 75s; # 超时时间,超时后连接关闭

    keepalive\_requests 4294967295; # 单连接处理最大请求次数,超过后连接关闭

      

   # 与后端服务的连接配置

    upstream grpc\_server {

        server localhost:8500 max\_fails=2 ; # placeholder

        keepalive 2000;  # 允许的空闲连接数

        keepalive\_timeout 75s; # 超时时间,超时后连接关闭

        keepalive\_requests 4294967295; # 单连接处理最大请求次数,超过后连接关闭

    }

    server {

          listen 80 http2;



          access\_log logs/access.log main;



          location / {

              grpc\_pass grpc://grpc\_server;

          }

     }

}

按照上述配置配置对应的keepalive参数后,可以看到TCP连接数大大下降,同时TIME_WAIT也大量减少,但是在压测过程中中,发现 Stream removed错误出现的概率有明显下降但仍然存在,同时注意到请求错误出现的时间与出现TIME_WAIT连接的时间高度同步,怀疑还是连接保持相关的问题。

image-20221009163804353
image-20221009163804353

搜索相关资料无果后,想到网关侧的nginx-ingress-gateway并未出现类似问题,于是查看了nginx-ingress中的nginx默认配置 ,在对比连接保持相关的参数后,注意到了 reset_timedout_connection,默认是关闭状态,开启后会跳过TCP的TIME_WAIT的状态,直接释放连接相关资源。结合之前注意到的请求失败的时间与TIME_WAIT出现的尝试加上该配置后,再次压测服务,最终没有再出现类似问题。

问题最终得到了解决,笔者认为这里大致是因为在TIME_WAIT状态下,客户端仍然会有请求发送到nginx,但nginx不会再转发到后端,导致了该问题,如果有对nginx更为熟悉的读者,也希望可以在此解惑。

最终配置

问题得到解决后,可以通过长连接稳定代理grpc流量的nginx配置如下(略去了很多非连接相关配置),供大家参考:

代码语言:text
复制
http {

    log\_format  main  '$remote\_addr - $remote\_user [$time\_local] "$request" '

                      '$status $body\_bytes\_sent "$http\_referer" '

                      '"$http\_user\_agent"';

         # 与客户端的连接配置

    keepalive 2000;  # 允许的空闲连接数

    keepalive\_timeout 75s; # 超时时间,超时后连接关闭

    keepalive\_requests 4294967295; # 单连接处理最大请求次数,超过后连接关闭

    reset\_timedout\_connection on;  # 重置超时连接、跳过time\_wait

  

    upstream grpc\_server {

        server localhost:8500 max\_fails=2 ; # placeholder

        keepalive 2000;  # 允许的空闲连接数

        keepalive\_timeout 75s; # 超时时间,超时后连接关闭

        keepalive\_requests 4294967295; # 单连接处理最大请求次数,超过后连接关闭

    }

  

    server {

        listen 80 http2;

 

        access\_log logs/access.log main;

 

        location / {

            grpc\_pass grpc://grpc\_server;

        }

    }

}

参考资料

  1. https://www.nginx.com/blog/nginx-1-13-10-grpc/
  2. http://nginx.org/en/docs/http/ngx_http_upstream_module.html
  3. http://nginx.org/en/docs/http/ngx_http_core_module.html
  4. https://draveness.me/whys-the-design-tcp-time-wait/
  5. https://web.dev/performance-http2/#streams,-messages,-and-frames

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • nginx使用长连接代理grpc流量
    • 踩坑过程
      • 最终配置
        • 参考资料
        相关产品与服务
        API 网关
        腾讯云 API 网关(API Gateway)是腾讯云推出的一种 API 托管服务,能提供 API 的完整生命周期管理,包括创建、维护、发布、运行、下线等。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档