场景:数据中心往各个业务平台分发所需的数据
所用的同步方式:spring-httpinvoker
异常信息:
Caused by: org.apache.commons.httpclient.ConnectionPoolTimeoutException: Timeout waiting for connection
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.doGetConnection(MultiThreadedHttpConnectionManager.java:497)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager.getConnectionWithTimeout(MultiThreadedHttpConnectionManager.java:416)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:153)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor.executePostMethod(CommonsHttpInvokerRequestExecutor.java:196)
at org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor.doExecuteRequest(CommonsHttpInvokerRequestExecutor.java:130)
at org.springframework.remoting.httpinvoker.AbstractHttpInvokerRequestExecutor.executeRequest(AbstractHttpInvokerRequestExecutor.java:136)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:192)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.executeRequest(HttpInvokerClientInterceptor.java:174)
at org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor.invoke(HttpInvokerClientInterceptor.java:142)
--------------------------------------------------------------------------------
对问题进行了排查,主要引入两篇文章供参考学习:
http://jer-gavin.iteye.com/blog/1490505
http://blog.csdn.net/ppby2002/article/details/6003150
问题原因大致明了:
MultiThreadedHttpConnectionManager 设置的链接数默认只有2个,程序中设置的等待连接超时时间为10秒,而同步程序允许的并发同步线程数设置最多为20个。
另外网络原因:同步程序部署在福建运营商机房,业务平台部署在杭州。网络存在跨运营商
调整方案
CommonsHttpInvokerRequestExecutor executor = new CommonsHttpInvokerRequestExecutor();
executor.getHttpClient().getParams().setConnectionManagerTimeout(connectionTimeout);
executor.getHttpClient().getParams().setSoTimeout(socketTimeout);
System.out.println(executor.getHttpClient().getHttpConnectionManager().getParams()
.getDefaultMaxConnectionsPerHost());
System.out.println(executor.getHttpClient().getHttpConnectionManager().getParams()
.getMaxTotalConnections());
修改 connectionTimeout 为30秒
调高 DefaultMaxConnectionsPerHost 为10
调高 MaxTotalConnections 为50
外网更新后 等待连接超时的异常基本上没有了,效果很明显。
socketTimeout目前设置的是30秒 后发现现在响应超时的日志频繁,确定下来应该是业务平台接收数据返回响应过程太久,需业务平台优化属后话了。
在此做下记录,httpinvoker实际上内部也是采用了线程池的概念,缓存了多个httpClient 实现并发处理远程调用。