socket-详细分析No buffer space available
关键词:socket,tcp三次握手,tcp四次握手,2MSL最大报文生存时间,LVS,负载均衡
新年上班第一天,突然遇到一个socket连接No buffer space available的问题,导致接口大面积调用(webservice,httpclient)失败的问题,重启服务器后又恢复了正常。
问题详情
具体异常栈信息如下:
Caused by: java.net.SocketException: No buffer space available (maximum connections reached?): connect at 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?): connect at 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),频繁的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连接而无法向外提供服务。
解决办法,加强安全防护。
socket-详细分析No buffer space available的更多相关文章
- socket-详细分析No buffer space available(转)
新年上班第一天,突然遇到一个socket连接No buffer space available的问题,导致接口大面积调用(webservice,httpclient)失败的问题,重启服务器后又恢复了正 ...
- socket-详细分析No buffer space available(转载)
文章原文出处:http://www.cnblogs.com/hjwublog/p/5114380.html 今天在公司服务器上部署运行的后台程序出现大面积接口无法调用的问题,查看后台控制台打印如下信息 ...
- Struct Socket详细分析(转)
原文地址:http://anders0913.iteye.com/blog/411986 用户使用socket系统调用编写应用程序时,通过一个数字来表示一个socket,所有的操作都在该数字上进行,这 ...
- java socket / No buffer space available
s https://www.cnblogs.com/yiwangzhibujian/p/7107785.html Socket用在哪呢,主要用在进程间,网络间通信. https://www.cnblo ...
- An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误.未找到或无法访问服务器.请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接. (provider: TCP ...
- 详细分析MySQL事务日志(redo log和undo log)
innodb事务日志包括redo log和undo log.redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作. undo log不是redo log的逆向过程,其实它 ...
- 详细分析MySQL事务日志(redo log和undo log) 表明了为何mysql不会丢数据
innodb事务日志包括redo log和undo log.redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作. undo log不是redo log的逆向过程,其实它 ...
- 1125MySQL Sending data导致查询很慢的问题详细分析
-- 问题1 tablename使用主键索引反而比idx_ref_id慢的原因EXPLAIN SELECT SQL_NO_CACHE COUNT(id) FROM dbname.tbname FORC ...
- java.net.SocketException: No buffer space available
https 访问url在调用量不大的情况下 java.net.SocketException: No buffer space available (maximum connections reach ...
随机推荐
- github生成静态博客
github生成静态博客很简单. 1.确认你知道你github的用户名,我的叫做chenxing12 2.创建一个项目名字叫做:用户名.github.io 我的用户名叫做chenxing12,所以我创 ...
- SQL Server 存储(1/8):理解数据页结构
我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或写入所有数据页.页有不同的类型,像数据页,GA ...
- 【笔记】Asp.Net WebApi对js POST带参数跨域请求的支持方案
先说下需求:在原来的WebApi项目中增加对js跨域的请求支持,请求方式:以POST为主,webapi路由规则根据原项目需求修改如下: public static void Register(Http ...
- C#写爬虫,版本V2.0
这个版本主要是以百度图片为对象,对其进行爬虫操作,实现了最基本的下载功能,但是缺陷非常多,日后还会对其进行改进. 打开百度图片,同时打开开发者工具,我们会发现,百度图片是通过如下的一段ajax来加载图 ...
- 异构(兼容dubbo)SOA系统架构(.net)优化升级
前面一片文章已经提到我司的异构(兼容dubbo)SOA系统架构,解决了不少技术痛点,也还算比较完善,也顺利推广开来. 但作为项目的开发者,自己产品的问题心里是清楚的,离自己满意还是有不小的距离. 在推 ...
- centos安装禅道的步骤
1.下载 XAMPP 套件: https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/stats/timeline 下载的文件是 xam ...
- JFreechart在linux下不显示及中文乱码问题
一.使用JFreeChart建的报表,在window下能正常显示,但是放到linux下就报错,而且有时候会把tomcat挂掉, 原因是jfreechart的在linux系统中需要访问java awt库 ...
- 转载:《TypeScript 中文入门教程》 6、命名空间
版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...
- Scalaz(57)- scalaz-stream: fs2-多线程编程,fs2 concurrency
fs2的多线程编程模式不但提供了无阻碍I/O(java nio)能力,更为并行运算提供了良好的编程工具.在进入并行运算讨论前我们先示范一下fs2 pipe2对象里的一些Stream合并功能.我们先设计 ...
- Asp.net mvc自定义Filter简单使用
自定义Filter的基本思路是继承基类ActionFilterAttribute,并根据实际需要重写OnActionExecuting,OnActionExecuted,OnResultExecuti ...