Http请求:Address already in use : connect
一、异常场景
性能测试发送大量http请求时,出现了java.net.BindException: Address already in use: connect异常【注:发送http请求使用的是短连接】
二、原因分析
http网络通信一般用的是TCP进行传输
TCP使用四元组(源地址,源端口,目的地址,目的端口)来标识一个TCP套接字。
高并发场景下客户端会占用大量的端口,如果这些端口没有释放就会出现端口不够用的情况,抛出java.net.BindException: Address already in use: connect异常。
源端口不够用
windows电脑端口总共有65535个,其中
① 0~1023(共1024个)为公认端口,紧密的绑定在一些特定服务上,如21端口就是FTP服务,80端口就是HTTP服务;
② 1024~49151(共48127个)为注册端口,松散的绑定于一些服务,如8080端口常常用于绑定tomcat服务;
③ 49152~65535(共16384个)为动态或私有端口;
49152~65535端口可用于TCP通信,注册端口中的部分端口,也会用于TCP通信,所以一台电脑可用的通信端口数量会稍微比16384多一点,但是也不会多太多,大概是16400+ 个
正常的TCP客户端连接在关闭后,会进入一个TIME_WAIT的状态,持续的时间一般在1~4分钟,对于连接数不高的场景,1~4分钟其实并不长,对系统也会有什么影响,但如果短时间内容进行大量的短连接,则可能出现这样一种情况:客户端所在的操作系统的scoket端口被用尽,系统无法再发起新的连接。
查看TIME_WAIT连接的命令:
windows系统命令:
在cmd下执行如下命令
netstat -ano |findstr 端口 |find /i "TIME_WAIT"
加上 /c 可统计TIME_WAIT连接个数
netstat -ano |findstr 端口 |find /i /c "TIME_WAIT"
linux系统命令
netstat -an |grep -i "端口" | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
三、解决方案
一、对系统进行调优
修改系统注册表
1、打开注册表:regedit
2、进入
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters
3、新建 DWORD值,name:TcpTimedWaitDe,value:10(十进制) –> 设置为10秒,默认是240秒 【如果有这一项则修改,没有则新建】
4、新建 DWORD值,name:MaxUserPort,value:65534(十进制) –> 设置系统当前端口可用范围为65534 【如果有这一项则修改,没有则新建】
5、重启系统使注册表新增配置生效
二、使用长连接
短连接最大的优点是方便,但短连接最大的缺点是将占用大量的系统资源,例如:本地端口、socket句柄。我们可以通过使用长连接来避免这个问题。