metersphere / jmeter 报错解决 java.net.NoRouteToHostException

metersphere 3个测试节点池,会有10%的请求出现 java.net.NoRouteToHostException 异常,主要原因是端口资源不足。

具体报错 jmeter java.net.NoRouteToHostException: Cannot assign requested address (Address not available)

JMeter HEAP 参数为 -Xms16g -Xmx16g -XX:MaxMetaspaceSize=1g

原因分析

由于客户端连接端口用尽,无法建立socket连接所致,虽然socket正常关闭,但是端口不是立即释放,而是处于 TIME_WAIT 状态,默认等待60s后释放。

解决办法

net.ipv4.tcp_timestamps=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.ip_local_port_range=10000 65000
net.ipv4.tcp_fin_timeout=20

修改 /etc/sysctl.conf 以后执行 sysctl -p 生效。

常见问题

sysctl: cannot stat /proc/sys/net/ipv4/tcp_tw_recycle: No such file or directory

net.ipv4.tcp_tw_reuse = 0  表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭

net.ipv4.tcp_tw_recycle = 0  表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭

net.ipv4.tcp_fin_timeout = 60  表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间(可改为30,一般来说FIN-WAIT-2的连接也极少)

好像上面3个内核调整参数,都是很多 Linux 运维工程师的标配了,怎么我一升级内核就不行了? 自己狠下心来好好去的看了 kernel 的文档,Linux 从4.12内核版本开始移除了 tcp_tw_recycle 这个参数。 好嘛,小弟我手贱贱,升级到了4.14现在没有这个参数,只能硬着头皮去掉。

但是这个参数对 linux 系统回收大量 tcp timeout wait 有帮助,tcp_tw_recycle通常会和tcp_tw_reuse参数一起使用,用于解决服务器TIME_WAIT状态连接过多的问题。 但是 kernel 为什么又要取消掉呢? 

简单来说就是,Linux会丢弃所有来自远端的timestramp时间戳小于上次记录的时间戳(由同一个远端发送的)的任何数据包。也就是说要使用该选项,则必须保证数据包的时间戳是单调递增的。同时从4.10内核开始,官方修改了时间戳的生成机制,所以导致 tcp_tw_recycle 和新时间戳机制工作在一起不那么友好,同时 tcp_tw_recycle 帮助也不那么的大。

此处的时间戳并不是我们通常意义上面的绝对时间,而是一个相对时间。很多情况下,我们是没法保证时间戳单调递增的,比如业务服务器之前部署了NAT,LVS等情况。相信很多小伙伴上班的公司大概率实用实用各种公有云,而各种公有云的 LVS 网关都是 FullNAT 。所以可能导致在高并发的情况下,莫名其妙的 TCP 建联不是那么顺畅或者丢连接。

发表评论