【问题标题】:Httpclient throws Timeout waiting for connection from pool exceptionHttpclient 抛出 Timeout waiting for connection from pool 异常
【发布时间】:2017-11-06 05:06:07
【问题描述】:

现在正在处理我们上传图片服务的异常,如下场景:

我们有一个网页,来自世界各地的用户可以将他们的图片上传到我们的服务器,图片通常保持在 3MB 左右。现在我们举办了促销活动,上传到我们服务器的图片数量非常庞大,导致服务器抛出异常“org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool”。

我们使用apache httpclient作为核心上传中间件,它的版本是4.5.*,我们使用in this article提到的方法正确处理了响应。 如下代码:

 if (returnType != StorageHttpResponse.class && response != null) {
        EntityUtils.consumeQuietly(response.getEntity());
        httpRequest.abort();
    }

此外,该服务的最大连接池为 128,最大连接超时为 50000 毫秒。我们使用流模式上传图片,而不是直接上传图片文件。

所以在这里,我通过在 finally 代码块中使用它来正确处理响应实体,但我仍然无法停止服务抛出连接池超时异常。

我需要添加到我的服务中的任何其他内容吗?我真的使用 redis 对用户的上传请求和帖子处理进行排队吗?

完整代码在这里:

 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;
}

【问题讨论】:

  • 我建议在 IOException 捕获块中添加httpRequest.releaseConnection()

标签: httpclient


【解决方案1】:

您可以在属性或 yml 文件中设置参数,如下所示。

http: 水池: 尺寸:100 套接字超时:20000 默认MaxPerRoute:200 最大路由: - 方案:http 主机:本地主机 端口:8080 最大路由:100 - 方案:https 主机:{{URL}} 端口:-1 maxPerRoute: 200

【讨论】:

    【解决方案2】:

    最后,我们不是通过代码解决了这个问题。因为我们都知道,如果不直接消费响应,请求的连接是不会释放的。所以在我们的代码中,我们首先消费了响应。

    我们不是通过使用更好的代码来解决这个问题,而是根据我们的业务场景稍微修改了一些参数,例如 maxconnectionpoolsize、maxconnectionperroute 和 maxconnectiontimeout。然后运行它,现在一切似乎都很好。希望对您有所帮助。

    【讨论】:

    • 你好 Charlie - 你在哪里设置了这些参数?一些配置文件?面对 1000 个 Web 服务请求时,我面临着完全相同的问题
    • @Yogendra 对不起,哥们,刚刚离开那个团队大约两年,关于细节的记忆消失了。
    猜你喜欢
    • 2011-01-16
    • 2019-07-13
    • 1970-01-01
    • 2019-06-14
    • 2018-10-01
    • 2022-12-15
    • 2022-10-14
    • 1970-01-01
    • 2019-01-06
    相关资源
    最近更新 更多