Reputation: 916
Now am working on an exception for our uploading image service, the scenario below:
We have a web page, user from all over the world can upload their images to our server, the image normally keep about 3MB. Now we held a promotion, so the images number uploading to our server is extremely huge, which, however caused the server throws the exception as "org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool".
We use apache httpclient as the core uploading middleware, its version is 4.5.*, we correctly handled the response by using the method mentioned in this article. The code like below:
if (returnType != StorageHttpResponse.class && response != null) {
EntityUtils.consumeQuietly(response.getEntity());
httpRequest.abort();
}
Also, the max connection pool for the service is 128 and the max connection time out is 50000 ms. We upload the images by using stream mode, not directly upload the image file.
So here, I correctly handled the response entity by consuming it in finally code block, but I still can't stop the service throw connection pool timeout exception.
Any other stuffs that I need to add to my service? Do I really using redis to make a queue to user's uploading requests and post handling?
Whole code here:
public <T> T excute(Request request, Class<T> returnType) {
Preconditions.checkState(!isShutDown, "JSSHttpClient is destory!");
HttpRequestBase httpRequest = new HttpRequestBuild(this.credential).build(request);
HttpResponse response = null;
try {
response = this.client.execute(httpRequest);
if (errorHandler.hasError(request, response)) {
int statusCode = response.getStatusLine().getStatusCode();
log.warn("Unexpected response," + request + " http code [" + statusCode + "]");
errorHandler.handleError(response);
}
if (returnType != null && returnType != StorageHttpResponse.class) {
return JsonMessageConverter.read(returnType, response);
}
if (returnType == StorageHttpResponse.class) {
return (T) new StorageHttpResponse(response);
}
} catch (IOException e) {
Throwables.propagate(e);
} finally {
if (returnType != StorageHttpResponse.class && response != null) {
EntityUtils.consumeQuietly(response.getEntity());
httpRequest.abort();
}
}
return null;
}
Upvotes: 1
Views: 13662
Reputation: 52
you can set the parameters in either properties or yml file like below.
http:
pool:
size: 100
sockettimeout: 20000
defaultMaxPerRoute: 200
maxPerRoutes:
-
scheme: http
host: localhost
port: 8080
maxPerRoute: 100
-
scheme: https
host: {{URL}}
port: -1
maxPerRoute: 200
Upvotes: 2
Reputation: 916
Finally, we solved this not by using code. Because we all know if the response not consumed directly, the connection of a request will not released. So in our code, we offen consume the response first.
We solved this problem not by using better code but slightly modify some parameters like maxconnectionpoolsize, maxconnectionperroute and maxconnectiontimeout based on our business scenario. Then running it and all seems ok now. Hope this helps you.
Upvotes: 1