我正在使用OkHttp 3.5.0执行超文本传输协议-基准测试。我正在向同一个URL发送数千个请求。
我期望OkHttp-client使用ConnectionPool并一遍又一遍地重用它的连接。但是如果我们研究netstat
,我们会看到许多连接处于TIME_WAIT状态:
TCP 127.0.0.1:80 127.0.0.1:51752 TIME_WAIT
TCP 127.0.0.1:80 127.0.0.1:51753 TIME_WAIT
TCP 127.0.0.1:80 127.0.0.1:51754 TIME_WAIT
TCP 127.0.0.1:80 127.0.0.1:51755 TIME_WAIT
TCP 127.0.0.1:80 127.0.0.1:51756 TIME_WAIT
...
在数千个请求之后,我得到了一个SocketException:没有可用的缓冲区空间(达到最大连接数?)
代码预执行请求(Kotlin):
val client = OkHttpClient.Builder()
.connectionPool(ConnectionPool(5, 1, TimeUnit.MINUTES))
.build()
val request = Request.Builder().url("http://192.168.0.50").build()
while (true) {
val response = client.newCall(request).execute()
response.close()
}
而不是
响应。close()
我使用响应。body()。string()
,则不会发生SocketException
,但netstat
仍显示大量等待连接的时间,并且基准性能越来越低。
我哪里做错了?
PS:我尝试过使用ApacheHttpClient及其
PoolighttpClientConnectionManager
,看起来它工作得很好。但我想找出OkHttp的问题所在。
感谢toien和我找到了我的解决方案(对于非标准超文本传输协议服务器)。
public class Http1CodecWrapper implements HttpCodec {
private HttpCodec codec;
public Http1CodecWrapper(HttpCodec codec) {
this.codec = codec;
}
// ...
@Override
public Response.Builder readResponseHeaders(boolean expectContinue) throws IOException {
return codec.readResponseHeaders(expectContinue)
.addHeader("Connection", "keep-alive");
}
}
OkHttpClient httpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
StreamAllocation allocation = realChain.streamAllocation();
HttpCodec codec = new Http1CodecWrapper(realChain.httpStream());
RealConnection connection = (RealConnection) realChain.connection();
return realChain.proceed(request, allocation, codec, connection);
}
})
.build();
我的版本是3.13.0,离3.5.0不远,我也遇到了时间等待问题。
在深入研究源代码之后,我在CallServerInterceptor中找到了。java
第142行:
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
在流量分配方面。java第367行:
public void noNewStreams() {
Socket socket;
Connection releasedConnection;
synchronized (connectionPool) {
releasedConnection = connection;
socket = deallocate(true, false, false); // close connection!
if (connection != null) releasedConnection = null;
}
closeQuietly(socket);
if (releasedConnection != null) {
eventListener.connectionReleased(call, releasedConnection);
}
}
这意味着,如果请求或响应中存在“connection:CLOSE”头,okhttp将关闭连接
虽然问题提交已经很久了,但我希望这个答案能帮助遇到这个问题的人,祝你们好运。
问题内容: 我有一个http客户端,可以创建与主机的多个连接。我想设置它可以设置到特定主机的最大连接数。go的request.Transport中没有此类选项。我的代码看起来像 我希望这会创建1个连接。正如我在for循环中所说的那样。但这一直在创建无限数量的连接。 使用请求库的类似python代码仅创建一个连接。 由于某种原因,go代码没有重用http连接。 编辑:go代码需要关闭主体才能重用连接
在我的应用程序与RabbitMQ服务器失去连接后,我在日志中看到 然后,当我的应用程序重新连接到RabbitMQ服务器时,我在日志中看到 但是,当应用程序重新连接到RabbitMQ服务器时,通道不会重新打开,在RabbitMQ管理控制台中,我可以在“通道”选项卡中看到没有任何通道。 重新连接后,在RabbitMQ服务器日志中: 我使用的是Spring Boot 1.5.3和Spring Boot
问题内容: 我正在尝试使用OkHttp,但是它一直崩溃。有人可以快速浏览一下,看看是否知道发生了什么事。谢谢。 日志猫: 这是我尝试使用的代码示例。它来自在线教程(teamtreehouse.com)Java代码: 问题答案: OkHttp需要Okio,OkHttp可以使用Okio来实现快速I / O和可调整大小的缓冲区。您可以在此处下载Okio(最新的JAR)。 要么 Android gradl
我正在开发一个需要从服务器下载数据的移动应用程序。它工作得很好,但在对服务器进行了一些更改后,来自改装的GET请求停止工作。它成功地发出请求,有时甚至得到成功的响应,但它从不调用onResponse()或onFailure()方法,因此应用程序只能挂起。 基本上有两种情况: 请求正确完成。Okhttp收到响应并打印内容,但它以一条消息结束(“阅读:意外的EOF!”)。之后应用程序停止工作。它不会冻
如果我的理解是正确的,那么为什么不将的==和!=运算符重载为: 那我们就可以省下两个铸件了?
然后用Gson lib将响应转换为我们需要的对象。 这来自Square/OKHTTP文档: 它的请求/响应API是用流畅的构建器和不变性设计的。它同时支持同步阻塞调用和带有回调的异步调用