公司内部容器平台,接入层用nginx作LB,用户有grpc协议需求,因此在lb层支持grcp反向代理,nginx从1.13开始支持grpc反向代理,将公司使用的nginx包从1.12升级到1.14.0后,增长grpc反向代理配置。配置完成后,打压力测试时,发现接入层机器端口占满而致使服务异常,开始追查问题。html
从上述描述能够看出grpc基于http2,client到server应该保持长链接,理论上不该该出现端口占满的问题linux
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长链接相关文档作了配置调整以后,发现nginx到server依然是短链接git
将nginx升级到nginx1.15.6(升级过程当中因为线上的nginx用到了lua模块,碰到了lua模块不适配问题,解决方案见连接lua模块适配问题)配置grpc_socket_keepalive on,抓包发现,会有少许处理多个请求的长链接存在,但大部分依然是短链接。github
从debug日志来看nginx确实尝试重用连接,可是从实际抓包看,nginx的连接重用的状况很是少,大部分都是请求处理完以后连接断开,怀疑nginx对grpc反向代理支持的不够理想。后端
回到问题自己,要解决的问题是接入层端口占满,各类调整nginx的长链接配置并不能解决这个问题,就尝试从tcp连接端口回收方面解决,大部分的tcp连接都处于TIME_WAIT状态。框架
TIME_WAIT状态的时间是2倍的MSL(linux里一个MSL为30s,是不可配置的),在TIME_WAIT状态TCP链接实际上已经断掉,可是该端口又不能被新的链接实例使用。这种状况通常都是程序中创建了大量的短链接,而操做系统中对使用端口数量作了限制最大能支持65535个,TIME_WAIT过多很是容易出现链接数占满的异常。对TIME_WATI的优化有两个系统参数可配置:tcp_tw_reuse,tcp_tw_recycle 这两个参数在网上都有详细介绍,这是就不展开来说socket
tcp_tw_reuse参考连接tcp
tcp_tw_recycle(Enable fast recycling TIME-WAIT sockets)参考连接post
测试来看,开启tcp_tw_reuse并无解决端口被占满的问题,因此开启了更激进的tcp_tw_recycle,至此端口占用显著下降,问题解决,因为咱们接入层并非用的NAT,因此这个配置不会影响服务。