最近给一个公司做项目的时候,在完成上报的功能 的时候,发现数据量稍微大的时候,会出现这样的问题:
错误描述:
com.microsoft.sqlserver.jdbc.SQLServerException: 通过端口 1433 连接到主机 192.168.0.174 的 TCP/IP 连接失败。错误:“Address already in use: connect。请验证连接属性,并检查 SQL Server 的实例正在主机上运行,且在此端口接受 TCP/IP 连接,还要确保防火墙没有阻止到此端口的 TCP 连接。”。
自己找原因找了一天终于从原因及解决方案,都已经找到,而且自己上网也发现好多同志也是遇到这样的问题,遂把解决方案贴出来,供大家参考。
这个问题我研究的时候发现很奇葩的,数据量稍微大的时候,就会出现这样的问题,而数据量小的时候则是完美运行的,而且在调试的走的比较慢的时候这也是可以运行成功的,究竟问题是出在哪里了呢,注:数据库用的是sqlserver,服务器用的是tomcat,考虑到数据量比较大,连接会比较多,用的是连接池,
问题可能原因:
Java的 Socket.close() 并不能立即释放连接,会造成一段时间内 TIME_WAIT 的状态
操作系统可供使用的连接数有默认限制,很快会被占满
自己在网上也找到了一个解决方案:
解决方案:
1、打开注册表:regedit(开始-运行-输入regedit)
2、HKEY_LOCAL_MACHINESYSTEMCurrentControlSet ServicesTCPIPParameters
3、新建 DWORD值,name:TcpTimedWaitDe,value:30(十进制) –> 设置为30秒,默认是240秒
4、新建 DWORD值,name:MaxUserPort,value:65534(十进制) –> 设置最大连接数65534
5、重启系统
但是找到经理,给经理说,这个方案不可以的,总不能到了客户哪里,你再去给客户的服务器修改注册表吧,这是万万行不通的,所以自己有接着踏上了找问题解决方案的路途中了,
后来找到了微软关于sqlserver的一片官方文档,把相应的关键片段,摘抄如下:
注意,MaxUserPort 和 TcpTimedWaitDelay 设置仅适用于这样的客户端计算机:它频繁打开和关闭到运行 SQL Server 的远程计算机的连接,但未使用连接池。例如,这些设置适用于这样一个 Internet Information Services (IIS) 服务器:它正在服务于大量传入的 HTTP 请求,并频频打开和关闭到运行 SQL Server 的远程计算机的连接,此服务器使用 TCP/IP 协议但禁用了连接池功能。如果启用了连接池,则不必调整 MaxUserPort 和 TcpTimedWaitDelay 设置。
当您使用 TCP/IP 协议打开一个到运行 SQL Server 的计算机的连接时,基础 SQL Server 网络库将打开一个到运行 SQL Server 的计算机的 TCP/IP 套接字。当它打开此套接字时,SQL Server 网络库不启用 SO_REUSEADDR TCP/IP 套接字选项。有关SO_REUSEADDR 套接字设置的更多信息,请参阅 Microsoft Developer Network (MSDN) 中的“Setsockopt”主题。
注意,出于安全原因,SQL Server 网络库特意不启用 SO_REUSEADDR TCP/IP 套接字选项。当 SO_REUSEADDR 启用时,恶意用户会挟制一个到 SQL Server 的客户端端口并使用客户端提供的凭据获得对运行 SQL Server 的计算机的访问权限。默认情况下,由于 SQL Server 网络库不启用 SO_REUSEADDR 套接字选项,因此您每次通过客户端上的 SQL Server 网络库打开和关闭套接字时,套接字都会进入为时四分钟的 TIME_WAIT 状态。如果您在禁用连接池的情况下频频打开和关闭通过 TCP/IP 的 SQL Server 连接,您实际上就是在频频打开和关闭 TCP/IP 套接字。换句话说,每一个 SQL Server 连接都有一个 TCP/IP 套接字。如果在不到四分钟的时间内快速打开和关闭了 4000 个套接字,就会达到客户端匿名端口的默认最大设置,并且在现有 TIME_WAIT 套接字超时前新的套接字连接尝试将不会成功。
在客户端,当您禁用了连接池时,可能必须增加在 Q319502 中讨论的 MaxUserPort 和 TcpTimedWaitDelay 设置。这些值的设置由客户端上发生的 SQL Server 连接的打开和关闭数量来决定。您可以通过使用客户端计算机上的 Netstat 工具来检查有多少客户端端口处于 TIME_WAIT 状态。按如下所示使用 -n 标志运行 Netstat 工具,并数一数到您的 SQL Server IP 地址的客户端套接字中有多少处于 TIME_WAIT 状态。在此示例中,运行 SQL Server 的远程计算机的 IP 地址是 10.10.10.20,客户端计算机的 IP 地址是 10.10.10.10,有三个已建立的连接,有两个处于 TIME_WAIT 状态的连接:
读罢,不禁焕然大悟,这也就是为什么我刚才的解决方案能行得通的原因,原来,问题就出在了,我们配置的连接池上了,但是作为我们开发人员的额本地测试的话,我们首当其冲的是会选择tomcat的,可是由于我们用的连接池支持的是websphere或者weblogic,所以才会在本地出现错误,自己赶紧把服务器换成了websphere,问题就再没有出现过了,
写了这么长,就是希望以后的开发人员能少走弯路,特此分享!