最近临近产品发版,因为有性能压力测试,开了20个并发请求同一个接口,然后遇到了这样的问题 “java.net.connectException: Cannot assign requested address (connect failed)”。百度了一个看了N篇记录,原因是客户端频繁的连服务器,由于每次连接都在很短的时间内结束,导致很多的TIME_WAIT,以至于用光了可用的端 口号,所以新的连接没办法绑定端口,因此就会跑出异常说 无法分配请求地址。这是一个客户端的问题,与程序服务是没有关系的,而我们目前的程序Http请求也是没有线程池的。
关于服务器TCP请求的TIME_WAIT,linux下可用netstat -a|grep TIME_WAIT 这个命令去查看一下连接数。
同常有比较多条的一个列表,在程序跑的过程中,为了方便看到time_wait的数量是否增多,可以直接用命令netstat -ant|grep -i time_wait |wc -l 查看。
服务器在存在大量短连接的情况下,Linux的TCP栈一般都会生成大量的 TIME_WAIT 状态的socket,有时候这个数量大到惊人的。而这个数量增大会占用系统的内核,而内核可不是无限的。
因此比较直接的解决方式就是修改系统内核相关的参数:
net.ipv4.ip_forward=1 表示开启对于TCP时间戳的支持,若该项设置为为0,则net.ipv4.tcp_tw_reuse设置不起作用,该值系统默认是0
net.ipv4.tcp_syncookies = 1 表示开启对于TCP时间戳的支持,若该项设置为为0,则net.ipv4.tcp_tw_reuse设置不起作用,该值系统默认是0
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_fin_timeout = 30 修改系統默认的TIMEOUT时间,默认是60
修改方式:
编辑 /etc/sysctl.conf 文件,加入参数内容,以上5个参数是我查到的认为有效的结果,然后我的实际情况仅修改了其中三个:
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
编辑完成后执行命令 /sbin/sysctl -p 让参数立即生效。至于气他参数就看具体情况了。我这种修改方式是直接永久保存的,不会受网络服务重启,系统重启等的影响,若要临时修改请自行查询命令。
然后我这边再去跑测试程序,然后再用查看time_wait连接数的命令去查看,得到的结果是这个数量减少了,不会像之前累积的特别多,当然直到并发跑完都没有在出现不法分配连接的异常,只是我这边达到高峰的时候会降低响应效率,这个性能还是待优化的。
我这里的解决方式可能并不完美,但是紧急情况是可以采纳采纳的,关于压力测试当然是我司测试伙伴配合的哈哈。
希望大家多多指教!