为什么会存在TIME_WAIT socket-详细分析No buffer space available
新年上班第一天,突然遇到一个socket连接No buffer space available的问题,导致接口大面积调用(webservice,httpclient)失败的问题,重启服务器后又恢复了正常。
问题详情
具体异常栈信息如下:
Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connectat org.apache.axis.AxisFault.makeFault(AxisFault.java:101)at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:154)at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)at org.apache.axis.client.Call.invokeEngine(Call.java:2784)at org.apache.axis.client.Call.invoke(Call.java:2767)at org.apache.axis.client.Call.invoke(Call.java:2443)at org.apache.axis.client.Call.invoke(Call.java:2366)at org.apache.axis.client.Call.invoke(Call.java:1812)Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connectat java.net.PlainSocketImpl.socketConnect(Native Method)at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)at java.net.Socket.connect(Socket.java:519)at sun.reflect.GeneratedMethodAccessor24.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)at org.apache.axis.components.net.DefaultSocketFactory.create(DefaultSocketFactory.java:153)at org.apache.axis.components.net.DefaultSocketFactory.create(DefaultSocketFactory.java:120)at org.apache.axis.transport.http.HTTPSender.getSocket(HTTPSender.java:191)at org.apache.axis.transport.http.HTTPSender.writeToSocket(HTTPSender.java:404)at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:138)
查阅了网上的资料,基本可以把问题锁定在:系统并发过大,连接数过多,部分socket连接无法释放关闭,而持续请求又导致无法释放的socket连接不断积压,最终导致No buffer space available。
最快解决办法
最快的解决办法:重启服务器,注意,重启tomcat不起作用。下面将分析最终的解决办法。
问题分析
虽然重启服务器能最快的将socket连接释放,但是问题很容易复现,很明显这不是问题的根本解决方式。还有几个问题需要进行进一步分析:
l 打开cmd输入netstat -an,发现存在大量处于TIME_WAIT状态的TCP连接,也就是之前提到的未释放的socket连接,并且server端口在不断变化,这又是什么现象呢?如下如图
l 系统是否有自动关闭连接的措施,是代码问题还是性能问题?
下面我们来分析解决这几个问题。
TIME_WAIT状态的由来
我们知道,TCP关闭连接需要经过四次握手,为什么是四次握手,而不是像建立连接那样三次握手,看看下面三次握手和四次握手的流程图。
三次握手建立连接示意图
四次握手关闭连接示意图
从上面的三次握手建立连接示意图中可以知道,只要client端和server端都接收到了对方发送的ACK应答之后,双方就可以建立连接,之后就可以进行数据交互了,这个过程需要三步。
而四次握手关闭连接示意图中,TCP协议中,关闭TCP连接的是Server端(当然,关闭都可以由任意一方发起),当Server端发起关闭连接请求时,向Client端发送一个FIN报文,Client端收到FIN报文时,很可能还有数据需要发送,所以并不会立即关闭SOCKET,所以先回复一个ACK报文,告诉Server端,“你发的FIN报文我收到了”。当Client端的所有报文都发送完毕之后,Client端向Server端发送一个FIN报文,此时Client端进入关闭状态,不在发送数据。
Server端收到FIN报文后,就知道可以关闭连接了,但是网络是不可靠的,Client端并不知道Server端要关闭,所以Server端发送ACK后进入TIME_WAIT状态,如果Client端没有收到ACK则Server段可以重新发送。Client端收到ACK后,就知道可以断开连接了。Server端等待了2MSL(Max Segment Lifetime,最大报文生存时间)后依然没有收到回复,则证明Client端已正常断开,此时,Server端也可以断开连接了。2MSL的TIME_WAIT等待时间就是由此而来。
我们知道了TIME_WAIT的由来,TIME_WAIT 状态最大保持时间是2 * MSL,在1-4分钟之间,所以当系统并发过大,Client-Server连接数过多,Server端会在1-4分钟之内积累大量处于TIME_WAIT状态的无法释放的socket连接,导致服务器效率急剧下降,甚至耗完服务器的所有资源,最终导致No buffer space available (maximum connections reached?): connect
问题的发生。
端口变化由来
对于大型的应用,访问量较高,一台Server往往不能满足服务需求,这时就需要多台Server共同对外提供服务。如何充分、最大的利用多台Server的资源处理请求,这时就需要请求调度,将请求合理均匀的分配到各台Server。
LVS (Linux Virtual Server)集群(Cluster)技术就是实现这一需求的方式之一。采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率,将请求均衡地转移到不同的服务器上执行,且调度器自动屏蔽掉服务器的故障,从而将一组服务器构成一个高性能的、高可用的虚拟服务器。
LVS集群采用三层结构,其主要组成部分为:
l 负载均衡调度器(load balancer),它是整个集群对外面的前端机,负责将客户的请求发送到一组服务器上执行,而客户认为服务是来自一个IP地址(我们可称之为虚拟IP地址)上的。
l 服务器池(server pool),是一组真正执行客户请求的服务器,执行的服务有WEB、MAIL、FTP和DNS等。
l 共享存储(shared storage),它为服务器池提供一个共享的存储区,这样很容易使得服务器池拥有相同的内容,提供相同的服务。
其结构如下图所示:
LVS结构示意图
从LVS结构示意图中可以看出,在后端看来Load Balancer到后端Server的IP的数据包的源IP地址都是一样(Load Balancer的IP地址和Server 的IP地址属于同一网段),而客户端认为服务是来自一个IP地址(实际上就是Load Balancer的IP)因为load Balencer会做负载均衡,实际上客户端指不定会和哪个服务器连接的每新连接一次就会建立一个新的会话,如果server1处于TIME_WAIT因为客户端只能看到一个load balencer,此时客户端并不知道有其他服务器的存在,会认为(所有的)服务器都处于TIME_WAIT状态,频繁的TCP连接建立和关闭,使得Load Balancer到后端Server的TCP连接会受到限制,导致在server上留下很多处于TIME_WAIT状态的连接,而且这些状态对应的远程IP地址都是Load Balancer的。Load Balancer的端口最多也就60000多个(2^16=65536,1~1023是保留端口,还有一些其他端口缺省也不会用),每个Load Balancer上的端口一旦进入 Server的TIME_WAIT黑名单,就有240秒不能再用来建立和Server的连接,这样Load Balancer和Server的连接就很有限。所以我们看到了使用netstat -an命令查看网络连接状况时同一个 remote IP会有很多端口。
最终解决办法
从上面的分析来看,导致出现No buffer space available这一问题的原因是多方面的,原因以及解决办法如下:
l 从代码层面上看,webservice或httpclient调用未进行连接释放,导致资源无法回收。
解决办法是在axis2的客户端代码中进行连接关闭,如下:
stub._getServiceClient().cleanupTransport();
stub._getServiceClient().cleanup();
stub.cleanup();
stub = null;
及时的关闭和clean能有效的避免内存溢出的问题,及时回收资源。
或者httpClient中,最终要在finally调用response.close()或者httpPost.releaseConnection() 进行连接释放。
l 从系统层面上看,系统socket连接数设置不合理,socket连接数过小,易达到上限;其次是2MSL设置过长,容易积压TIME_WAIT状态的TCP连接。
解决办法是修改Linux内核参数,
修改系统socket最大连接数,在文件/etc/security/limits.conf最后加入下面两行:
* soft nofile 32768
* hard nofile 32768
或者缩小2MSL的时长、允许重用处于TIME_WAIT状态的TCP连接、快速回收处于 TIME_WAIT状态的TCP连接,修改/etc/sysctl.conf,添加如下几行:
#改系統默认的TIMEOUT时间
net.ipv4.tcp_fin_timeout=2
#启重用,允许将TIME_WAIT sockets重新用于新的TCP连接 默认为0表示关闭
net.ipv4.tcp_tw_reuse=1
#开启TCP连接中TIME_WAIT sockets的快速回收 默认为0 表示关闭
net.ipv4.tcp_tw_recycle=1
对于windows环境,可通过修改注册表进行配置:
\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
添加一个DWORD类型的值TcpTimedWaitDelay,值可以根据实际情况配置。
\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters
添加一个DWORD类型的值MaxUserPort ,值可以根据实际情况配置。
上面这些参数根据实际情况进行配置。
l 从LVS 层面上看,调度算法不合理,导致请求过多分配到某一台服务器上。
解决办法,根据实际情况指定合理的负载均衡解决方案。
l 从安全层面上看,当服务器遭到DDoS(拒绝服务***)时,服务器大量积压TIME_WAIT状态的TCP连接而无法向外提供服务。
出处:http://www.itwenku.net/dev/20160108/1961.html
转载于:https://blog.51cto.com/frankch/1752325
为什么会存在TIME_WAIT socket-详细分析No buffer space available相关推荐
- windows系统socket泄露问题解决--No buffer space available (maximum connections reached?): JVM_Bind
今天在公司服务器上部署的一套后台系统突然不能使用了,上服务器看了一下,控制台打印了如下错误信息: java.net.SocketException: No buffer space available ...
- Android system server之PackageManagerService详细分析
概要 本篇主要分析了系统启动阶段包管理服务的启动流程,其中的几个接口在 apk 安装时也会被调用.包管理服务启动时主要做的工作大致有如下几方面: 1. 建立 java 层的 installer 与 c ...
- 处理大并发之四 libevent demo详细分析(对比epoll)
处理大并发之四 libevent demo详细分析(对比epoll) libevent默认情况下是单线程,每个线程有且仅有一个event_base,对应一个struct event_base结构体,以 ...
- 客户端访问https时应无浏览器(含终端)安全警告信息;_https和http有什么区别(内附详细分析)...
很多站长知道https和http有所不同,但是究竟两者有什么不同浑然不知,针对这种情况,本文Seo星火给大家详细分析一下https和http有什么区别. 一.基本概念: (http服务器-->本 ...
- Linux记录-TCP状态以及(TIME_WAIT/CLOSE_WAIT)分析(转载)
1.TCP握手定理 2.TCP状态 l CLOSED:初始状态,表示TCP连接是"关闭着的"或"未打开的". l LISTEN :表示服务器端的某个SOCK ...
- 处理大并发之四 libevent demo详细分析(对比epoll)
处理大并发之四 libevent demo详细分析(对比epoll) libevent默认情况下是单线程,每个线程有且仅有一个event_base,对应一个struct event_base结构体,以 ...
- 一起来用Websocket(二):Websocket协议详细分析
一起来用Websocket(二):Websocket协议详细分析 前言 本节主要翻译一下websocket的协议.其中,socket通信开发,最重要的就是协议了.通信软件(QQ.MSN).杀毒软件(3 ...
- 详细分析Apple macOS 6LowPAN 漏洞(CVE-2020-9967)
聚焦源代码安全,网罗国内外最新资讯! 安全研究员 Alex Plaskett 在2020年5月向苹果报告了影响MacOS Big Sur 的一个漏洞 (CVE-2020-9967).苹果公司在12月 ...
- gsm模块 java 录音_Android GSM驱动模块详细分析
Android的RIL驱动模块, 在hardware/ril目录下,一共分rild,libril.so以及librefrence_ril.so三个部分,另有一 radiooptions可供自动或手动调 ...
最新文章
- 服务端如何防止订单重复支付!
- python详细安装教程3.7.0-Linux 安装Python3.7.0
- android 隐藏闹钟通知,redis环境搭建
- uml图工具_UML建模工具更新情况(二)
- 【渝粤题库】国家开放大学2021春1121健康教育与健康促进题目
- php5.2 json,php5.2以上版本json_encode兼容性
- 基于netty,hessian的RPC框架
- linux脚本打印变量的值,linux利用read命令获取变量中的值
- 读取json本地js处理输出html,JavaScript 通过浏览器导出和读取本地 JSON 文件
- 虚拟机 Debian 11 安装moodle3.11
- vscode编程常用快捷键
- 3种夸克有多少组合?
- migration php,Lavarel常用语句之Migration
- Linux终端分屏软件tmux工具基本快捷键
- java runtime是什么软件_Java SE Runtime Environment (JRE) 运行Java程序的必备软件
- docker安装过程 和部署2048小游戏
- 2018-8-7 直播课堂笔记
- 转载:那些年他(她)们做过的“蠢事”
- 从业务需求出发,开启IDC高效运维之路
- 社科院与杜兰大学金融管理硕士---授人以鱼不如授人以渔,培养全新金融人才
热门文章
- SPOJ - SUBLEX 【后缀自动机】
- HtmlHelper扩展 及 页面编码化
- 大熊君大话NodeJS之------Net模块
- Xamarin.Android开发音乐播放器
- phpMyAdmin ‘tbl_gis_visualization.php’多个跨站脚本漏洞
- 如何找到需要的rpm包
- KD树(k-d tree)
- [轉]VS2010 UML类图生成代码
- java.lang.NoClassDefFoundError: org/apache/http/ssl/TrustStrategy 错误解决办法
- idea项目application.properties文件注释显示unicode编码