java Apache HTTPClient 不会建立超过 2 个连接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7683574/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:58:03  来源:igfitidea点击:

Apache HTTPClient does not make more than 2 connections

javahttpconnectionapache-httpclient-4.x

提问by shyam

I've been trying to implement connection pooling for my application using Apache HTTPClient (v4.1). The problem is that the client always makes only two connections when run, though there are enough threads running parallel. I have been trying to modify the code for a while now, but nothing has helped yet.
I'm using ThreadSafeClientConnManagerfor connection pooling and set the MaxTotaland DefaulMaxPerRouteto values I want.
Is there anything that comes to your mind first that I might want to check?

Here's that code segment that I use to create the client.

我一直在尝试使用 Apache HTTPClient (v4.1) 为我的应用程序实现连接池。问题是客户端在运行时总是只建立两个连接,尽管有足够的线程并行运行。我一直在尝试修改代码一段时间,但没有任何帮助。
我使用ThreadSafeClientConnManager连接池,并设置MaxTotalDefaulMaxPerRoute我想要的值。
您首先想到的有什么我可能想检查的吗?

这是我用来创建客户端的代码段。

DefaultHttpClient createClient() {
    HttpParams params = new BasicHttpParams();
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

    params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(60000));
    params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(60000));
    params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);

    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("https", sf, 6443));
    registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));

    ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, registry);
    cm.setMaxTotal(2 * maxConnections);
    cm.setDefaultMaxPerRoute(maxConnections);

    HttpHost localhost = new HttpHost("localhost");
    cm.setMaxForRoute(new HttpRoute(localhost), maxConnections);

    HttpHost sdpTargetHost = new HttpHost("webserviceIP", webservicePort, "https");
    cm.setMaxForRoute(new HttpRoute(sdpTargetHost, null, true), maxConnections);

    return new DefaultHttpClient(cm, params);
}

The client returned by this function is used in Runnablesmanaged by a ThreadPoolExecutor. The Runnables use the client, and has these lines:

这个函数返回的客户端使用Runnables由管理ThreadPoolExecutor。Runnables 使用客户端,并具有以下几行:

HttpResponse response = httpClient.execute(httpPost, context);
HttpEntity entity = response.getEntity();
....
EntityUtils.consume(entity);

From what I know, the EntityUtils.consume(entity)will notify the connection manager that the connection is no longer used, and thus will release the connection to be used by other threads. So I'm guessing the connection management is alright.

I guess I've provided enough info, please tell me if I'm to add anything more.

Thanks

据我所知,EntityUtils.consume(entity)将通知连接管理器不再使用该连接,从而将释放该连接以供其他线程使用。所以我猜连接管理没问题。

我想我已经提供了足够的信息,请告诉我是否要添加更多信息。

谢谢

回答by shyam

OK. I've found the solution, thanks to olegfor pointing out the logging, and to google and all the forums.
All I had to do was define the class with only the connection manager, and then set HttpParams using HttpClient.setParams(). So the code will look something like this:

行。我找到了解决方案,感谢oleg指出日志记录,以及谷歌和所有论坛。
我所要做的就是仅使用连接管理器定义类,然后使用 HttpClient.setParams() 设置 HttpParams。所以代码看起来像这样:

DefaultHttpClient createClient() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("https", sf, 6443));

    ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(registry);
    cm.setMaxTotal(maxConnections);
    cm.setDefaultMaxPerRoute(maxConnections);

    HttpHost targetHost = new HttpHost("webserviceIP", webservicePort, "https");
    cm.setMaxForRoute(new HttpRoute(targetHost, null, true), maxConnections);

    return new DefaultHttpClient(cm);
}

And right before using the client,

在使用客户端之前,

DefaultHttpClient httpClient = createClient();
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, new Integer(60000));
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, new Integer(60000));
params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
httpClient.setParams(params);

There apparently is no difference in the code logically, but this fixed my problem. I presume this probably is some sorta bug in the HttpClient 4.1 API.

代码逻辑上显然没有区别,但这解决了我的问题。我认为这可能是 HttpClient 4.1 API 中的某种错误。

回答by Maxim

I was not able to set this option in cm

我无法以厘米为单位设置此选项

cm.setDefaultMaxPerRoute(maxConnections);

It was necessary to do so:

有必要这样做:

ConnPerRoute perRoute = new ConnPerRouteBean(100);
ConnManagerParams.setMaxConnectionsPerRoute(params, perRoute);
ConnManagerParams.setMaxTotalConnections(params, 100);
ConnManagerParams.setTimeout(params, 15000);