我在 REST API 调用某些 Web 服务期间使用 Apache HTTP 客户端进行连接池。
奇怪的是,尽管我使用了 HTTP 连接池,但性能却没有任何提升。
我正在使用 Apache HTTP Client 连接到我的 Web 服务,代码如下 documentation :
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
HttpHost host = new HttpHost("abc.com", 80);
cm.setMaxPerRoute(new HttpRoute(host), 50);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
我正在使用 Spring 的
RestTemplate
来使用 Spring 的 HttpClient
来包装 Apache 的 HttpComponentsClientHttpRequestFactory
实现。
但是即使我不使用连接池,即。使用Spring的
SimpleClientHttpRequestFactory
,我没有获得任何性能优势。
我的连接仍然需要相同的时间才能完成。
我所做的是否是实现 HTTP 连接池的正确方法?我是不是做错了什么?
如果我需要任何进一步的信息,请告诉我。
注意 HTTP 客户端池的工作方式,它可能会在短时间内提高性能。看看下面的分析:
来自 PoolingHttpClientConnectionManager javadocs
4.4 版本中更改了对过时连接的处理。以前,代码会默认检查每个连接,然后再重新使用它。现在,代码仅在自上次使用连接以来经过的时间超过已设置的超时时检查连接。默认超时设置为2000ms
从池性能的角度来看,这意味着只要管理器在默认情况下 2 秒内认为该路由处于“活动”状态,到特定路由的连接就会被重用。
2 秒后,与该路由的不活动连接将被视为过时并被丢弃,从而在下次请求该路由时产生连接初始化惩罚。
换句话说,池在第一个连接之后的 2 秒内提高了连接的性能。重型航线受益最大。
作为一个简单的测试,将池大小设置为一个较小的值,例如最大 5。在 Linux 上发送 5 个请求并检查已建立的到该路由的连接数
watch "ss -ant dst <your route IP>"
watch "netstat -ant | grep <your route IP>"
您应该看到 5 个连接。等待 10 或 20 秒并向同一路由发送 2 个请求,您应该看到这 5 个连接关闭,并创建了 2 个新连接。
也可以通过调试日志记录来观察这一点。 这里有一篇很好的文章可供参考。
Apache 官方文档关于 http 日志记录。
我相信您正确设置了
HttpClient
和池管理器。
我的实现有一个细微的差别,我没有使用
HttpClients.custom()
,而是使用 HttpClientBuilder.create()
,但随后具有与您相同的方法调用。根据另一个 Stack Overflow answer,这应该不会产生影响。
我之前在 Spring 应用程序中使用过此配置,并获得了很好的好处。我想知道响应是否发生得足够快,以至于您没有看到很大的好处?我唯一能想到的另一件事是
RestTemplate
是否可能未正确配置。
您的配置似乎是正确的。您可以使用多线程来利用系统资源来提高性能。
HttpGet get = new HttpGet("http://www.codersjargon.com");
PoolingHttpClientConnectionManager connManager
= new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom().
setConnectionManager(connManager).build();
MultiHttpClientConnThread thread1 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread2 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread3 = new MultiHttpClientConnThread(client, get);
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();