最近项目遇到一个问题,同样的程序,再本地调试跑没问题,但是放到服务器上跑,却会出现各种超时。
查了查日志,发现多数是这样的一个错误
message:发生一个或多个错误。
经过一步步排查发现是HttpClient发送请求时的错误,我本地请求一个接口6分钟能收到结果,但是在服务器上,1个小时后就返回了这么个错误
查阅了很多文档资料。
才知道是httpclient在并发线程时,出现的异常。
httpclient在处理请求连接方面使用了连接池,它内部实际上有两种连接池,一种是全局的ConnectionPool,一种是每主机(per-host)HostConnectionPool。参数maxHostConnections就HostConnectionPool中表示每主机可保持连接的连接数,maxTotalConnections是ConnectionPool中可最多保持的连接数。每主机的配置类是HostConfiguration,HttpClient有个int executeMethod(final HostConfiguration hostConfiguration, final HttpMethod method)方法可以指定使用哪个HostConfiguration,不过多数情况都是不显示指定HostConfiguration,这样httpclient就用了默认的HostConfiguration=null,也就是说所有的请求可以认为指自同一个主机。如果不设置这两个参数,httpclient自然会用默认的配置,也就是MultiThreadedHttpConnectionManager中的:
public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2;
// Per RFC 2616 sec 8.1.4 ? public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
使用httpclient还有两点经验,一个是创建的MultiThreadedHttpConnectionManager 实例最好是全局的,否则会有多个连接池,而HttpClient是线程安全的,可以多个实例。另一个是,在处理请求的最后,也就是finnaly里中,要调用method.releaseConnection();回收连接,否则连接池就可能会爆了。
PoolingClientConnectionManager conMgr = new PoolingClientConnectionManager();
conMgr.setMaxTotal(200); //设置整个连接池最大连接数 根据自己的场景决定
//是路由的默认最大连接(该值默认为2),限制数量实际使用DefaultMaxPerRoute并非MaxTotal。
//设置过小无法支持大并发(ConnectionPoolTimeoutException: Timeout waiting for connection from pool),路由是对maxTotal的细分。
conMgr.setDefaultMaxPerRoute(conMgr.getMaxTotal());//(目前只有一个路由,因此让他等于最大值)
//另外设置http client的重试次数,默认是3次;当前是禁用掉(如果项目量不到,这个默认即可)
httpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
此处解释下MaxtTotal和DefaultMaxPerRoute的区别:
1、MaxtTotal是整个池子的大小;
2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分;比如:
MaxtTotal=400 DefaultMaxPerRoute=200
而我只连接到http://www.baidu.com时,到这个主机的并发最多只有200;而不是400;
但素。
.net 中httpclient是4.5后才出来的,
而.net 的HttpClientHandler.MaxConnectionsPerServer 是4.7.1后才出现的,
所以在.net4.7以前想要适应多线程,需要自己处理了。。。
参考文档:
https://news.cnblogs.com/n/553217/
https://bbs.csdn.net/topics/390257271
https://www.cnblogs.com/gisblogs/p/4201096.html
https://blog.csdn.net/kobejayandy/article/details/16921265
https://blog.csdn.net/fgx_123456/article/details/78206001
这里还有dudu写的一个可以提高httpclient性能的相关测试
http://www.cnblogs.com/dudu/p/csharp-httpclient-attention.html