为什么OkHttp不重新使用它的连接? [英] Why OkHttp doesn't reuse its connections?
本文介绍了为什么OkHttp不重新使用它的连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在使用OkHttp 3.5.0执行http基准测试。我正在向同一URL发送数千个请求。
我期望OkHttp客户端使用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: No buffer space available (maximum connections reached?)
准备请求的代码(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()
}
如果我使用response.close()
而不是response.body().string()
,则SocketException
不会发生,但netstat
仍然显示大量的time_wait连接,基准性能越来越低。
我做错了什么?
PS:我尝试过使用ApacheHttpClient及其PoolingHttpClientConnectionManager
,它看起来工作得很好。但我想找出OkHttp出了什么问题。
推荐答案
我的版本是3.13.0,距离3.5.0不远,也遇到了TIME_WAIT
问题。
深入源代码后,我在CallServerInterceptor.java
第142行找到:
if ("close".equalsIgnoreCase(response.request().header("Connection"))
|| "close".equalsIgnoreCase(response.header("Connection"))) {
streamAllocation.noNewStreams();
}
和StreamAllocation.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将关闭连接
虽然问题提交已经很久了,但我希望这个答案能帮助遇到这个问题的人,祝你好运。
这篇关于为什么OkHttp不重新使用它的连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文