[英]Best Practice to Use HttpClient in Multithreaded Environment
For a while, I have been using HttpClient in a multithreaded environment. 有一段时间,我一直在多线程环境中使用HttpClient。 For every thread, when it initiates a connection, it will create a completely new HttpClient instance.
对于每个线程,当它启动连接时,它将创建一个全新的HttpClient实例。
Recently, I have discovered that, by using this approach, it can cause the user to have too many ports being opened, and most of the connections are in TIME_WAIT state. 最近,我发现,通过使用这种方法,它可能导致用户打开太多端口,并且大多数连接处于TIME_WAIT状态。
http://www.opensubscriber.com/message/commons-httpclient-dev@jakarta.apache.org/86045.html http://www.opensubscriber.com/message/commons-httpclient-dev@jakarta.apache.org/86045.html
Hence, instead of each thread doing : 因此,而不是每个线程做:
HttpClient c = new HttpClient();
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
We plan to have : 我们计划:
[METHOD A] [方法A]
// global_c is initialized once through
// HttpClient global_c = new HttpClient(new MultiThreadedHttpConnectionManager());
try {
global_c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
}
In a normal situation, global_c will be accessed by 50++ threads concurrently. 在正常情况下,global_c将同时由50个++线程访问。 I was wondering, will this create any performance issues?
我想知道,这会产生任何性能问题吗? Is MultiThreadedHttpConnectionManager using a lock-free mechanism to implement its thread safe policy?
MultiThreadedHttpConnectionManager是否使用无锁机制来实现其线程安全策略?
If 10 threads are using global_c, will the other 40 threads be locked? 如果10个线程正在使用global_c,那么其他40个线程是否会被锁定?
Or would it be better if, in every thread, I create an instance of an HttpClient, but release the connection manager explicitly? 或者,如果在每个线程中我创建一个HttpClient实例,但是显式释放连接管理器会更好吗?
[METHOD B] [方法B]
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
HttpClient c = new HttpClient(connman);
try {
c.executeMethod(method);
}
catch(...) {
}
finally {
method.releaseConnection();
connman.shutdown();
}
Will connman.shutdown() suffer performance issues? connman.shutdown()会遇到性能问题吗?
May I know which method (A or B) is better, for application using an 50++ threads? 对于使用50 ++线程的应用程序,我可以知道哪种方法(A或B)更好吗?
Definitely Method A because its pooled and thread safe. 绝对是方法A因为它的汇集和线程安全。
If you are using httpclient 4.x, the connection manager is called ThreadSafeClientConnManager . 如果您使用的是httpclient 4.x,则连接管理器称为ThreadSafeClientConnManager 。 See this link for further details (scroll down to "Pooling connection manager").
有关详细信息,请参阅此链接 (向下滚动到“池化连接管理器”)。 For example:
例如:
HttpParams params = new BasicHttpParams();
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, registry);
HttpClient client = new DefaultHttpClient(cm, params);
Method A is recommended by httpclient developer community. 方法A由httpclient开发人员社区推荐。
Please refer http://www.mail-archive.com/httpclient-users@hc.apache.org/msg02455.html for more details. 有关详细信息,请参阅http://www.mail-archive.com/httpclient-users@hc.apache.org/msg02455.html 。
My reading of the docs is that HttpConnection itself is not treated as thread safe, and hence MultiThreadedHttpConnectionManager provides a reusable pool of HttpConnections, you have a single MultiThreadedHttpConnectionManager shared by all threads and initialised exactly once. 我对文档的阅读是HttpConnection本身不被视为线程安全,因此MultiThreadedHttpConnectionManager提供了一个可重用的HttpConnections池,你有一个由所有线程共享的单个MultiThreadedHttpConnectionManager并初始化一次。 So you need a couple of small refinements to option A.
因此,您需要对选项A进行一些小改进。
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManag
Then each thread should be using the sequence for every request, getting a conection from the pool and putting it back on completion of its work - using a finally block may be good. 然后每个线程应该为每个请求使用序列,从池中获取一个连接并在完成其工作时将其放回 - 使用finally块可能是好的。 You should also code for the possibility that the pool has no available connections and process the timeout exception.
您还应该编写池没有可用连接并处理超时异常的可能性。
HttpConnection connection = null
try {
connection = connman.getConnectionWithTimeout(
HostConfiguration hostConfiguration, long timeout)
// work
} catch (/*etc*/) {/*etc*/} finally{
if ( connection != null )
connman.releaseConnection(connection);
}
As you are using a pool of connections you won't actually be closing the connections and so this should not hit the TIME_WAIT problem. 当您使用连接池时,您实际上不会关闭连接,因此不应该遇到TIME_WAIT问题。 This approach does assuume that each thread doesn't hang on to the connection for long.
这种方法确实可以确保每个线程不会长时间挂起连接。 Note that conman itself is left open.
请注意,conman本身是开放的。
I think you will want to use ThreadSafeClientConnManager. 我想你会想要使用ThreadSafeClientConnManager。
You can see how it works here: http://foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html 你可以在这里看到它是如何工作的: http : //foo.jasonhudgins.com/2009/08/http-connection-reuse-in-android.html
Or in the AndroidHttpClient
which uses it internally. 或者在内部使用它的
AndroidHttpClient
中。
With HttpClient 4.5 you can do this: 使用HttpClient 4.5,您可以这样做:
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(new PoolingHttpClientConnectionManager()).build();
Note that this one implements Closeable (for shutting down of the connection manager). 请注意,这个实现了Closeable(用于关闭连接管理器)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.