HttpClient4.3 连接池

红太狼 2022-05-27 05:35 282阅读 0赞

连接池管理器一般使用PoolingHttpClientConnectionManager,它管理着连接池,可以同时为很多线程提供http连接请求。Connections are pooled on a per route basis.当请求一个新的连接时,如果连接池有有可用的持久连接,连接管理器就会使用其中的一个,而不是再创建一个新的连接。PoolingHttpClientConnectionManager维护的连接数在每个路由基础和总数上都有限制。默认,每个路由基础上的连接不超过2个,总连接数不能超过20。在实际应用中,这个限制可能会太小了,尤其是当服务器也使用Http协议时。

多线程请求执行

当使用了请求连接池管理器(比如PoolingClientConnectionManager)后,HttpClient就可以同时执行多个线程的请求了。PoolingClientConnectionManager会根据它的配置来分配请求连接。如果连接池中的所有连接都被占用了,那么后续的请求就会被阻塞,直到有连接被释放回连接池中。为了防止永远阻塞的情况发生,我们可以把http.conn-manager.timeout的值设置成一个整数。如果在超时时间内,没有可用连接,就会抛出ConnectionPoolTimeoutException异常。

HttpClient的实例是线程安全的,可以被多个线程共享访问,但是仍旧推荐每个线程都要有自己专用实例的HttpContext。

官方示例

  1. PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
  2. // 将最大连接数增加到200
  3. cm.setMaxTotal(200);
  4. // 将每个路由基础的连接增加到20
  5. cm.setDefaultMaxPerRoute(20);
  6. //将目标主机的最大连接数增加到50
  7. HttpHost localhost = new HttpHost("www.yeetrack.com", 80);
  8. cm.setMaxPerRoute(new HttpRoute(localhost), 50);
  9. CloseableHttpClient httpClient = HttpClients.custom()
  10. .setConnectionManager(cm)
  11. .build();

在自己项目中也用到了连接池管理器,处理了普通的http请求与忽略https证书。这货很灵活,代码仅供参考,毕竟只是为了方便项目。

  1. import java.security.GeneralSecurityException;
  2. import java.security.cert.CertificateException;
  3. import java.security.cert.X509Certificate;
  4. import java.util.concurrent.TimeUnit;
  5. import javax.net.ssl.SSLContext;
  6. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
  7. import org.apache.http.impl.client.CloseableHttpClient;
  8. import org.apache.http.impl.client.HttpClients;
  9. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
  10. import org.apache.http.ssl.SSLContextBuilder;
  11. import org.apache.http.ssl.TrustStrategy;
  12. /**
  13. * HttpClient连接池<br/>
  14. * Author:杨杰超<br/>
  15. * Date:2018年3月12日 下午3:08:19 <br/>
  16. * Copyright (c) 2018, yangjiechao@dingtalk.com All Rights Reserved.<br/>
  17. *
  18. */
  19. public class GlobalHttpClientConnectionManager {
  20. // 设置访问协议
  21. private PoolingHttpClientConnectionManager connMrg = null;
  22. // 超时参数
  23. private long timeToLive = 10;
  24. // 超时参数单位
  25. private TimeUnit tunit = TimeUnit.SECONDS;
  26. // 设置整个连接池最大连接数
  27. private int maxTotal = 256;
  28. // 单个路由最大连接数
  29. private int defaultMaxPerRoute = 64;
  30. /**
  31. * 初始化
  32. */
  33. public GlobalHttpClientConnectionManager() {
  34. connMrg = new PoolingHttpClientConnectionManager(timeToLive, tunit);
  35. connMrg.setMaxTotal(maxTotal);
  36. connMrg.setDefaultMaxPerRoute(defaultMaxPerRoute);
  37. }
  38. /**
  39. * 初始化
  40. *
  41. * @param timeToLive
  42. * 超时参数
  43. * @param tunit
  44. * 超时单位
  45. * @param maxTotal
  46. * 连接池最大连接数
  47. * @param defaultMaxPerRoute
  48. * 主机对MaxTotal的一个细分,比如:MaxtTotal=256
  49. * DefaultMaxPerRoute=64,而我只连接到http://www.baidu.com时,
  50. * 到这个主机的并发最多只有64而不是128
  51. */
  52. public GlobalHttpClientConnectionManager(long timeToLive, TimeUnit tunit, int maxTotal, int defaultMaxPerRoute) {
  53. this.timeToLive = timeToLive;
  54. this.tunit = tunit;
  55. this.maxTotal = maxTotal;
  56. this.defaultMaxPerRoute = defaultMaxPerRoute;
  57. }
  58. public PoolingHttpClientConnectionManager getManager() {
  59. return connMrg;
  60. }
  61. public CloseableHttpClient getHttpClient() {
  62. return HttpClients.custom().setConnectionManager(connMrg).build();
  63. }
  64. /**
  65. * 获取忽略证书的HttpClient
  66. *
  67. * @return
  68. */
  69. public CloseableHttpClient getHttpsClient() {
  70. return getHttpsClient(createSSLConnSocketFactory());
  71. }
  72. public CloseableHttpClient getHttpsClient(SSLConnectionSocketFactory sslSocketFactory) {
  73. return HttpClients.custom().setSSLSocketFactory(sslSocketFactory).setConnectionManager(connMrg).build();
  74. }
  75. /**
  76. * 创建SSL安全连接
  77. *
  78. * @return
  79. */
  80. private SSLConnectionSocketFactory createSSLConnSocketFactory() {
  81. SSLConnectionSocketFactory sslsf = null;
  82. try {
  83. SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
  84. public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  85. // 信任所有
  86. return true;
  87. }
  88. }).build();
  89. sslsf = new SSLConnectionSocketFactory(sslContext);
  90. } catch (GeneralSecurityException e) {
  91. e.printStackTrace();
  92. }
  93. return sslsf;
  94. }
  95. }

然而我们在使用的时候,需求是需要连接多个不同的服务器,所以需要多个PoolingHttpClientConnectionManager。然后再上一份代码~

  1. import java.util.Map;
  2. import java.util.concurrent.ConcurrentHashMap;
  3. import java.util.concurrent.TimeUnit;
  4. import org.apache.http.impl.client.CloseableHttpClient;
  5. /**
  6. * HttpClient连接池工厂<br/>
  7. * Author:杨杰超<br/>
  8. * Date:2018年3月12日 下午3:16:18 <br/>
  9. * Copyright (c) 2018, yangjiechao@dingtalk.com All Rights Reserved.<br/>
  10. *
  11. */
  12. public class GlobalHttpClientConnectionManagerFactory {
  13. // 超时参数
  14. public static final long timeToLive = 10;
  15. // 超时参数单位
  16. public static final TimeUnit tunit = TimeUnit.SECONDS;
  17. // 设置整个连接池最大连接数
  18. public static final int maxTotal = 256;
  19. // 单个路由最大连接数
  20. public static final int defaultMaxPerRoute = 256;
  21. public static Map<String, GlobalHttpClientConnectionManager> cache = new ConcurrentHashMap<>();
  22. public static GlobalHttpClientConnectionManager getGlobalHttpClientConnectionManager(String key) {
  23. return getGlobalHttpClientConnectionManager(key, timeToLive, tunit, maxTotal, defaultMaxPerRoute);
  24. }
  25. public static GlobalHttpClientConnectionManager getGlobalHttpClientConnectionManager(String key, long timeToLive,
  26. TimeUnit tunit, int maxTotal, int defaultMaxPerRoute) {
  27. GlobalHttpClientConnectionManager manager = cache.get(key);
  28. if (null == manager) {
  29. synchronized (cache) {
  30. manager = cache.get(key);
  31. if (null == manager) {
  32. manager = new GlobalHttpClientConnectionManager(timeToLive, tunit, maxTotal, defaultMaxPerRoute);
  33. cache.put(key, manager);
  34. }
  35. }
  36. }
  37. return manager;
  38. }
  39. public static CloseableHttpClient getCloseableHttpClient(String key) {
  40. return getCloseableHttpClient(key, timeToLive, tunit, maxTotal, defaultMaxPerRoute);
  41. }
  42. public static CloseableHttpClient getCloseableHttpClient(String key, long timeToLive, TimeUnit tunit, int maxTotal,
  43. int defaultMaxPerRoute) {
  44. return getGlobalHttpClientConnectionManager(key, timeToLive, tunit, maxTotal, defaultMaxPerRoute)
  45. .getHttpClient();
  46. }
  47. }

这货版本更新变化得太多了,加上jsoup做抓取真不错~

发表评论

表情:
评论列表 (有 0 条评论,282人围观)

还没有评论,来说两句吧...

相关阅读

    相关 HTTPClient 连接

      向Dirud集群写入数据时,采用HTTPClient向集群提交数据,由于数据量大,需要以多线程方式开启多个线程,单个的HTTPClient会出现连接超时,效率低的情况。高