gpt4 book ai didi

java - HttpClient 无法从服务器获得响应

转载 作者:行者123 更新时间:2023-11-30 11:24:01 33 4
gpt4 key购买 nike

这个问题让我们整个团队堵了半天!

我们使用 apache httpclient 4.3.x 从提供 http api 的存储服务器发布和获取数据。为了提高性能,我们使用了PoolingHttpClientConnectionManager:

public HttpClient createHttpClient() {
Registry registry = RegistryBuilder.create()....build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(50);
connectionManager.setDefaultMaxPerRoute(50);

CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
return httpClient;
}

然后我们在我们的程序中持有一个 httpClient 实例,在每个 http 请求中重用它:

全局httpClient:

HttpClient httpClient = createHttpClient();

发布一些数据:

HttpPost httpPut = new HttpPost("...");
HttpResponse response = httpClient.execute(httpPut);

// Notice we get the response content here!
String content = EntityUtils.toString(response.getEntity());
System.out.println(content);

httpPut.releaseConnection();
response.close();

然后得到:

HttpGet httpGet = new HttpGet("...");

// Blocked at this line !!!!
HttpResponse response = httpClient.execute(httpGet);

String content = EntityUtils.toString(response.getEntity());
System.out.println(content);

httpPut.releaseConnection();
response.close();

请注意这一行://Blocked at this line !!!!

程序在该行阻塞,永远不会转到下一行。在 Debug模式下,我可以看到它已被阻止:

SocketInputStream.socketRead0()

我搜索了很多问题和文档,但没有运气。


我的同事只是通过设置 NoConnectionReuseStrategy.INSTANCE 来修复它:

 HttpClients.custom()
.setConnectionManager(connectionManager)
// Following line fixed the problem, but why?
.setConnectionReuseStrategy(NoConnectionReuseStrategy.INSTANCE)
.build();

现在它没有被阻止,但是为什么?

“重用连接”是什么意思?使用 NoConnectionReuseStrategy 是否存在性能问题?

谢谢大家~

最佳答案

我试图重现阻塞的 http-get(也作为我自己的练习)但即使没有关闭响应我也无法阻止它。我唯一一次成功制作 http-get block 是通过执行 response.getEntity().getContent() 而不从返回的 InputStream 中读取并且没有关闭返回的输入流。对于我的测试,我使用 Tomcat 7.0.47 和两个非常简单的 servlet(一个对 get 响应“OK”,另一个响应 post)作为服务器。客户端启动了 50 个线程,每个线程执行 30 个交替的 http-get 和 http-post 请求(总共 1500 个请求)。客户端没有使用 RegistryBuilder,而是使用默认的(由 PoolingHttpClientConnectionManager 本身创建)。

关于 NoConnectionReuseStrategy:默认情况下(使用 HttpClients.createDefault() 创建的 HttpClient,我使用 org.apache.httpcomponents:httpclient:4.3.1) 一个连接池最多与 1 个服务器建立 2 个连接。例如。即使 5 个线程同时对 1 个服务器执行各种请求,连接池也只打开 2 个连接,将它们重新用于所有请求,并确保在任何给定时间 1 个线程使用 1 个连接。这会对客户端性能产生非常积极的影响,并显着降低服务器上的负载。唯一必须确保的是在 finally block 中调用 response.close()(这确保连接返回到连接池)。通过使用 NoConnectionReuseStrategy,您基本上可以禁用连接池:对于每个请求,都会创建一个新连接。我建议您为类别 org.apache.http.impl.conn.PoolingHttpClientConnectionManager 启用调试日志记录,它非常有用。

关于 httpPut.releaseConnection() 的注意事项:这实际上并没有释放连接,它只是确保您可以在下一个请求中重新使用“httpPut”对象(参见 apidocs ,按照显示的链接)。另请注意,在“httpGet”的代码中,您对“httpPut”而不是“httpGet”调用了 releaseConnection()

关于java - HttpClient 无法从服务器获得响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20880325/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com