如何解决高并发,连接等待超时的异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解决高并发,连接等待超时的异常相关的知识,希望对你有一定的参考价值。

如果你的并发确实超过 20 个,那么加大并发 active 是必须的,除非你接受列长时间的等待(这个是刚需)
如果你只是 21 个线程,但不是并发超过20个需求(也就是线程激活,但不一定在处理需求,可能是等待),那么你应该在每个线程的需求处理完成之后及时关闭连接(也就是让连接回到连接池,让其他线程可以用)
参考技术A MaxActive:可用连接实例的最大数目,为负数的时候没有限制。
MaxIdle:空闲连接实例的最大数目,为负值时没有限制。
MaxWait:等待获取链接的超时时间。
也就是说当连接池中没有active/idle的连接时,会等待maxWait时间,如果等待超时还没有可用连接,则抛出Could not get a resource from the pool异常。所以为避免这样的错误,
我们应该根据程序实际情况合理设置这三个参数的值。
同时在我们获取一个连接的程序方法中也应该合理的处理这个异常,当没有连接可用时,等待一段时间再获取也许是个比较好的选择。

JBoss配置解决高并发连接异常问题(转)

 

这两天一个项目在做压力测试的时候,发现只要并发数超过250个,连续测试两轮就会有连接异常出现,测试轮数越多出现越频繁,异常日志如下:

 

[plain] view plain copy
 
 技术分享技术分享
  1. Caused by: com.caucho.hessian.client.HessianConnectionException: 500: java.io.IOException: Error writing to server  
  2.     at com.caucho.hessian.client.HessianURLConnection.sendRequest(HessianURLConnection.java:142)  
  3.     at com.caucho.hessian.client.HessianProxy.sendRequest(HessianProxy.java:283)  
  4.     at com.caucho.hessian.client.HessianProxy.invoke(HessianProxy.java:170)  
  5.     at $Proxy168.sendOpenAcctInfo(Unknown Source)  
  6.     at sun.reflect.GeneratedMethodAccessor750.invoke(Unknown Source)  
  7.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
  8.     at java.lang.reflect.Method.invoke(Method.java:597)  
  9.     at org.springframework.remoting.caucho.HessianClientInterceptor.invoke(HessianClientInterceptor.java:219)  
  10.     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)  
  11.     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)  
  12.     at $Proxy169.sendOpenAcctInfo(Unknown Source)  
  13.     at com.shine.web.bean.OpenAcctBeanImpl.sendOpenAcctInfo(OpenAcctBeanImpl.java:62)  
  14.     ... 32 more  
  15. Caused by: java.io.IOException: Error writing to server  
  16.     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)  
  17.     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)  
  18.     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)  
  19.     at java.lang.reflect.Constructor.newInstance(Constructor.java:513)  
  20.     at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1345)  
  21.     at java.security.AccessController.doPrivileged(Native Method)  
  22.     at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1339)  
  23.     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:993)  
  24.     at com.caucho.hessian.client.HessianURLConnection.sendRequest(HessianURLConnection.java:122)  
  25.     ... 43 more  
  26. Caused by: java.io.IOException: Error writing to server  
  27.     at sun.net.www.protocol.http.HttpURLConnection.writeRequests(HttpURLConnection.java:453)  
  28.     at sun.net.www.protocol.http.HttpURLConnection.writeRequests(HttpURLConnection.java:465)  
  29.     at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1047)  
  30.     at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:373)  
  31.     at com.caucho.hessian.client.HessianURLConnection.sendRequest(HessianURLConnection.java:109)  
  32.     ... 43 more  


一开始使用Error writing to server去网络上查找原因,发现基本都无关。

 

后来搜索hessian和spring兼容问题,发现spring2.5.6和hessian4.0.7不兼容。将hessian版本号降低到3.1.3,情况有好转,但测试10轮之后,异常又出现了。

通过内存监控,先排除虚拟机内存问题。虚拟机内存配置为-Xms1024m -Xmx1024m,监控下来发现实际占用内存不到一半。

然后通过netstat -na监控操作系统端口占用情况,发现端口占用高峰不到500个,这个原因也排除了。(测试服务器已经修改注册表将TIME_WAIT时间降低到30秒,所以基本不会出现端口占用问题)。

通过CPU监控,确认并发高峰时,CPU占用也不到50%。

种种迹象表明,这些都不是造成连接断开的原因,那到底瓶颈出现在哪里呢?

于是我们将目光转向JBoss的配置。

首先确认数据库的连接池配置,最大连接数设置为50,从前几轮都可以正常运行来看,数据库连接应该够用;

然后确认JBoss的线程池配置,发现默认配置如下:

 

[html] view plain copy
 
 技术分享技术分享
  1. <mbean code="org.jboss.util.threadpool.BasicThreadPool"  
  2.    name="jboss.system:service=ThreadPool">  
  3.    <attribute name="Name">JBoss System Threads</attribute>  
  4.    <attribute name="ThreadGroupName">System Threads</attribute>  
  5.    <!-- How long a thread will live without any tasks in MS -->  
  6.    <attribute name="KeepAliveTime">60000</attribute>  
  7.    <!-- The max number of threads in the pool -->  
  8.    <attribute name="MaximumPoolSize">10</attribute>  
  9.    <!-- The max number of tasks before the queue is full -->  
  10.    <attribute name="MaximumQueueSize">1000</attribute>  
  11.    <!-- The behavior of the pool when a task is added and the queue is full.  
  12.    abort - a RuntimeException is thrown  
  13.    run - the calling thread executes the task  
  14.    wait - the calling thread blocks until the queue has room  
  15.    discard - the task is silently discarded without being run  
  16.    discardOldest - check to see if a task is about to complete and enque  
  17.       the new task if possible, else run the task in the calling thread  
  18.    -->  
  19.    <attribute name="BlockingMode">run</attribute>  
  20. </mbean>  


搜索了一下相关配置的说明,在进行高并发的时候,建议修改MaximumPoolSize的大小为并发数的125%。

 

由于我们测试的不是持续的并发,因此将线程池大小修改成200先测试了一下,发现并发数在300的时候可以正常运行,又将并发数修改到500,持续测试了6个小时,均没有发现异常。

现在比较好奇的是,为什么250个并发的时候就能一直不出错,超过250个并发,就会频繁出错,这个值和MaximumPoolSize的参数到底有什么联系呢?

http://blog.csdn.net/nicholas_lin/article/details/20639481

 http://wenku.baidu.com/link?url=eUQiTt73bQN_XBHVNpAhDnSMYfLdfqQXK1AF5Pp2dhTgBrO4nHaws7rEm8WZY5WVIiOEUaX5UQuuQTNCM9DrsNMjetboto1NnikLSEtzH6S

以上是关于如何解决高并发,连接等待超时的异常的主要内容,如果未能解决你的问题,请参考以下文章

JBoss配置解决高并发连接异常问题(转)

高并发下载tomcat下的文件时,发生java.net.SocketException: Connection reset解决方案

java高并发,如何解决,啥方式解决,高并发

【golang】高并发下TCP常见问题解决方案

高并发的MySQL数据查询时,会不会选择数据库连接池?

如何解决访问Apache 80端口出现超时的问题