【发布时间】:2019-07-08 19:24:22
【问题描述】:
我正在调试我的 Android 应用程序中的一个问题。我发现根本原因是文件描述符超出了限制。经过进一步调查,我发现该应用程序打开了太多套接字。我使用 OkHttpClient 2.5 进行所有网络通信,因此我想知道我应该如何限制我的连接池大小。下面是我的代码sn-p:
OkHttpClient okHttpClient = new OkHttpClient().setConnectTimeout(TIMEOUT);
ConnectionPool connectionPool = new ConnectionPool(MAX_IDLE_CONNECTIONS,
KEEP_ALIVE_DURATION_MS);
okHttpClient.set(connectionPool);
@RequireArgsConstructor
public HttpEngineCallable implements Callable<IHttpResponse>
{
private final String url;
public IHttpResponse call () throws Exception
{
try
{
Request request = Request.Builder().url(url).build();
Call call = okHttpClient.newCall(request);
Response rawResponse = call.execute();
return new OkHttpResponse(rawResponse);
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
private final Function<IHttpResponse, T> httpResponseParser = new Function<IHttpResponse, T>()
{
@Nullable
@Override
public T apply(@Nullable IHttpResponse httpResponse)
{
if(httpResponse == null)
{
return null;
}
InputStream stream = httpResponse.getBody();
JsonParser parser = null;
T result = null;
try
{
parser = jsonFactory.createParser(stream);
result = strategy.parseData(parser);
}
catch (Exception e)
{
log.error("Unable to convert {} with {}.", stream, strategy, e);
}
finally
{
IOUtils.closeQuietly(parser);
IOUtils.closeQuietly(stream);
}
return result;
}
};
Future<T> future = executorService.submit(new HttpEngineCallable(url));
Future<V> finalFuture = Futures.transform(future, httpResponseParser, executorService);
T result = timeoutExecutorService.submit(new Runnable()
{
try
{
T result = finalFuture.get(CLIENT_TIMEOUT, TIMEUNIT)
if (result == null)
{
notify onFailure listeners
}
else
{
notify onSuccess Listeners
}
}
catch(Exception ex)
{
notify onFailure listeners
}
}
所以我对这个实现有几个问题:
- 我的 CLIENT_TIMEOUT 比 OkHttp ConnectTimeout 短。如果我的
finalFuture.get(CLINT_TIMEOUT, TIMEUNIT)抛出超时异常,我在解析器函数中的 finally 块是否仍会被执行?我指望它关闭我的连接。 - 如何限制我的 ConnectionPool 的大小?如果连接超出限制,我是否可以自动回收最旧的连接?
【问题讨论】:
-
Re (1),
finally块总是被执行。这就是他们的目的。 -
@EJP 确切地说,我担心以下两种情况 1.) finalFuture.get() 超时时间较短。由于这个 get() 强制执行 httpResponseParser.apply(),所以这部分执行从未发生过。 2.) HttpEngineCallable.call() 发生异常。我不确定执行路径是否仍会到达 httpResponseParser.apply() 部分。你知道在上述两种情况下,执行路径是否仍然会到达包含 finally 块的 httpResponseParser.apply() 部分?
标签: java android future okhttp