I am debugging an issue in my android app. I found the root cause is file descriptors went beyond the limit. After further investigation I found that the app has too many sockets open. I use OkHttpClient 2.5 for all of my network communication, thus I am wondering how should I limit my connection pool size. Below is my code snippet:
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
}
}
So I have a few questions regarding this implementation:
- My CLIENT_TIMEOUT is shorter than OkHttp ConnectTimeout. If my
finalFuture.get(CLINT_TIMEOUT, TIMEUNIT)
throws timeout exception, would my finally block in the Parser Function still be executed? I am counting on it to close my connection. - How can limits the size of my ConnectionPool? Is there way I can auto-recycle oldest connections if connection went beyond limit?
finally
blocks are always executed. That's what they're for. – Keaton