前言

前段时间遇到一个问题,由于是初次相识,所以写一篇小笔记记录一下。以免后面再次遇到类似的问题,可以参考提供解决问题的思路。当时是由于一个同事在群里发了一张截图,原来是一个服务挂掉了。当时看到他发的异常信息日志,完全是一脸懵逼,这问题从来没遇到过啊。。。这下难搞了。

问题概述

当时同事发过来的页面异常信息是这样的
偶遇No buffer space available
当时看到这个页面完全没有思绪,没有办法只好连接远程服务器,看到tomcat上也报异常了,没办法只好尝试着去重启tomcat,可是tomcat好像也启动不了。而且报另外一个异常,而我也被这个异常信息带偏了。tomcat上的异常信息是这样的
偶遇No buffer space available
上面的异常信息是显示数据库连接池创建失败。这里想到难道是项目的数据库连接出现问题。检查了数据库是正常的,可以使用,难道是数据源配置出现问题?可是之前部署到tomcat上还是可以的。不应该是数据源配置出现问题,后来想是不是因为换了tomcat部署,而tomcat上可能配置了数据源,可是检查了一下,发现数据源也是正常的,没任何毛病。没办法只好请教了同事,可是同事也没有提出什么好的建议,这下彻底傻眼了。
庆幸的是,我们还有一位最好的老师,那就是度娘。可是网上也说可能是数据源配置问题。可是检查了就是没毛病,这就为难了。当时部门的小伙伴都回去。组长和经理开完会回来,我把我的问题向组长描述了一下,组长说重启一下服务器就ok了。由于当时不早了,所以组长说完就打算回去了,我也就没多问。打算第二天来重启一下试一试。

没什么是重启不能解决的

第二天上班过来,我远程重启了服务器,然后重启了tomcat重新发布了项目,结果居然好了。但是具体是什么原因导致这种情况出现。心中很是疑惑。。。又在网上了查找了一些资料,可是没找到原因。后来我又看了一次同事发给我的异常信息图片,既然tomcat启动报错的原因找不到,说不定可以从最初的异常发生来找原因。我找了一下,网上有提到相关原因,联想到自己的项目,完全吻合。
由于这个项目中,有很多服务接口。而在另外一个项目中有一个功能用httpclient同时调用这些接口,通过httpclient调用时需要建立连接,由于并发或者请求过多导致,由于大量连接处于time-wait,这样就导致了很多服务器的资源被大量消耗。说到这个time-wait状态,这里就要重新复习一下TCP的四次挥手,借用一下《扫盲系列之Http长连接短连接》的图
偶遇No buffer space available
在tcp断开连接的过程中,需要四次挥手,这里的挥手是相对建立连接的三次握手而言。在服务端发送断开连接请求之后(这里需要注意客户端也是可以主动发起断开连接的请求),客户端接收到服务端的断开连接请求,他会回应服务端,他已经收到断开请求,但是客户端不会马上断开连接,因为客户端可能还有数据包没有发送完毕。所以客户端不会马上断开连接,而是等自己这边的数据发送完毕再断开连接,然后再发送一个finish响应。服务端收到客户端的finish响应会再次发送一个ACK来确认客户端是否已经断开连接,由于网络的延迟等其他原因,服务端需要等待一段时间,这段时间就是上图的2MSL,而这段时间的连接都是出于time-wait状态。在一段时间之后连接才彻底断开变为closed状态。而如果请求很多,导致很多连接出于time-wait状态就会导致No buffer space available的产生。后来我在本地简单模拟多次请求,然后通过是netstat -n来查看连接情况,确实看到很多连接出于time-wait状态,截图如下
偶遇No buffer space available

重启只能救场,不能根治

上面的问题,虽然重启服务器能够立马释放socket连接(注意这里不是重启tomcat服务器),但是这种方式只是治标不治本,这种问题后面可能还会出现,对于这种问题,应该从代码和硬件角度来考虑解决。首先代码中对于httpclient建立的连接应该及时关闭,同时还可以修改服务器的注册表,提高socket可用连接数,同时减少time-wait时间,让处于time-wait状态的连接尽快释放。

总结

上面是对于自己遇到的问题的一份小总结,对于这个问题的解决办法,如果有更好的解决思路,还请留言指教!

相关文章: