Forwarding Address: http://jinnianshilongnian.iteye.com/blog/2089792
Conclusion:
If the use of HttpClient 3.1 concurrent large items, it is best to upgrade to httpclient4.2.3, to ensure that the concurrent volume can withstand. HttpClient 4.3.3, there are still some bugs, or 4.2.x stable version of it.
Take inventory items for example:
HttpClient a day in the amount of 1500w, the peak of 70,000 a second.
During the previous use, there has been a large number of
Org.apache.http.conn.ConnectionPoolTimeoutException:Timeout waiting for connection from pool
At Org.apache.http.impl.conn.PoolingClientConnectionManager.leaseConnection (Poolingclientconnectionmanager.java : 232)
At Org.apache.http.impl.conn.poolingclientconnectionmanager$1.getconnection (Poolingclientconnectionmanager.java : 199)
At Org.apache.http.impl.client.DefaultRequestDirector.execute (defaultrequestdirector.java:456)
In addition to viewing threads through Jstack, you will find that:
"Pool-21-thread-3" prio=10 tid=0x00007f6b7c002800 nid=0x40ff waiting on condition [0x00007f6b37020000]
Java.lang.Thread.State:TIMED_WAITING (parking)
At Sun.misc.Unsafe.park (Native method)
-Parking to wait for <0x00000000f97918b8> (a java.util.concurrent.locks.abstractqueuedsynchronizer$ Conditionobject)
At Java.util.concurrent.locks.LockSupport.parkUntil (locksupport.java:239)
At Java.util.concurrent.locks.abstractqueuedsynchronizer$conditionobject.awaituntil ( abstractqueuedsynchronizer.java:2072)
At Org.apache.http.pool.PoolEntryFuture.await (poolentryfuture.java:129)
At Org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking (abstractconnpool.java:281)
At org.apache.http.pool.abstractconnpool.access$000 (abstractconnpool.java:62)
At Org.apache.http.pool.abstractconnpool$2.getpoolentry (abstractconnpool.java:176)
At Org.apache.http.pool.abstractconnpool$2.getpoolentry (abstractconnpool.java:172)
At Org.apache.http.pool.PoolEntryFuture.get (poolentryfuture.java:100)
At Org.apache.http.impl.conn.PoolingClientConnectionManager.leaseConnection (Poolingclientconnectionmanager.java : 212)
Problem:
Because the connection pool is used, but the connection is not enough, causing a lot of waiting, and this wait has a snowball effect (and the transaction group recently used Apache common DBCP risk is similar).
Solution
Finally, we have set some reasonable parameter values, so far we have not encountered any problems.
Thinking
In fact, the cause of the problem is that we do not understand some parameters, arbitrarily set its value, do not appear the problem is good, the problem is difficult to troubleshoot to the cause, so I use httpclient must set the parameters and code writing and troubleshooting methods summarized for reference.
Parameter settings
1, HttpClient 4.2.3
Httpparams params = new Basichttpparams ();
Set the connection timeout time
Integer connection_timeout = 2 * 1000; Set Request Timeout 2 seconds based on business adjustment
Integer so_timeout = 2 * 1000; Set wait data timeout time 2 seconds according to business adjustment
Defines the millisecond timeout that is used when retrieving a managedclientconnection instance from Clientconnectionmanager
This parameter expects a value of java.lang.Long type. If this parameter is not set, the default equals Connection_timeout, so be sure to set the
Long conn_manager_timeout = 500L; This value is the time when the connection is not enough to wait for the timeout, be sure to set, and not too large ()
Params.setintparameter (Coreconnectionpnames.connection_timeout, connection_timeout);
Params.setintparameter (Coreconnectionpnames.so_timeout, so_timeout);
Params.setlongparameter (Clientpnames.conn_manager_timeout, conn_manager_timeout);
Test connection availability before submitting a request
Params.setbooleanparameter (Coreconnectionpnames.stale_connection_check, true);
Poolingclientconnectionmanager conmgr = new Poolingclientconnectionmanager ();
Conmgr.setmaxtotal (200); Set the maximum number of connections for the entire connection pool depending on your scenario
is the default maximum connection for a route (this value defaults to 2), and limiting the number of actual use of Defaultmaxperroute is not maxtotal.
Set too small to support large concurrency (connectionpooltimeoutexception:timeout waiting for connection from pool), routing is a subdivision of Maxtotal.
Conmgr.setdefaultmaxperroute (Conmgr.getmaxtotal ());//(There is only one route, so let him equal the maximum)
Set the HTTP client retry number by default, 3 times, and is currently disabled (this defaults if the item is not available)
Httpclient.sethttprequestretryhandler (New Defaulthttprequestretryhandler (0, false));
The difference between maxttotal and Defaultmaxperroute is explained here:
1, Maxttotal is the size of the entire pool;
2. Defaultmaxperroute is a subdivision of Maxtotal based on the host connected to it;
maxttotal=400 defaultmaxperroute=200
And I only connect to the http://sishuok.com when the concurrency to this host is only 200, not 400;
And when I connect to http://sishuok.com and http://qq.com, the concurrency to each host is only 200, which adds up to 400 (but not more than 400), so the setting that works is Defaultmaxperroute.
2, HttpClient 3.1
Httpconnectionmanagerparams params = new Httpconnectionmanagerparams ();
Params.setconnectiontimeout (2000);
Params.setsotimeout (2000);
Maximum number of connections
Params.setmaxtotalconnections (500);
Params.setdefaultmaxconnectionsperhost (500);
Params.setstalecheckingenabled (TRUE);
Connectionmanager.setparams (params);
Httpclientparams httpclientparams = new Httpclientparams ();
Setting the connection timeout for httpclient is not a useful connection timeout set for Connection Manager
Httpclientparams.setconnectionmanagertimeout (5000); Equivalent to the conn_manager_timeout in 4.2.3
HttpClient = new HttpClient (ConnectionManager);
Httpclient.setparams (Httpclientparams);
Set the HTTP client retry number by default, 3 times, and is currently disabled (this defaults if the item is not available)
Httpclientparams.setparameter (Httpmethodparams.retry_handler, New Defaulthttpmethodretryhandler (0, false));
The parameter is similar to not much explanation;
Code writing
1, HttpClient 4.2.3
HttpResponse response = null;
Httpentity entity = NULL;
try {
HttpGet get = new HttpGet ();
String url = "http://hc.apache.org/";
Get.seturi (new URI (URL));
Response = Gethttpclient (). Execute (GET);
//Process Response
catch (Exception e) {
Handling Exceptions
finally {
if (response!= null) {
Entityutils.consume (Response.getentity ()); will automatically release the connection
}
The following methods are also possible, but there are some risks; do not use
InputStream is = Response.getentity (). getcontent ();
Is.close ();
}
2, HttpClient 3.1
Postmethod Postmethod = new Postmethod (Yxurl);
try {
Httpclient.executemethod (Postmethod);
catch (Exception e) {
Handling Exceptions
finally {
if (Postmethod!= null) {//Do not forget to release, as far as possible by this method implementation,
Postmethod.releaseconnection ();
There is a risk, do not use
Postmethod.setparameter ("Connection", "close");
InputStream is = Postmethod.getresponsebodyasstream ();
Is.clsoe () will also close and release the connected
}
}
Risk of existence
1, HttpClient 4.2.3 When the connection is released
if (Managedconn.isopen () &&!managedconn.ismarkedreusable ()) {//If the connection is open and is not reusable (not keepalive) close socket
try {
Managedconn.shutdown ();
catch (IOException Iox) {
if (this.log.isDebugEnabled ()) {
This.log.debug ("I/O exception shutting down released connection", Iox);
}
}
}
Only reusable connections can be kept alive
if (managedconn.ismarkedreusable ()) {
Entry.updateexpiry (keepalive, Tunit!= null Tunit:TimeUnit.MILLISECONDS);
if (this.log.isDebugEnabled ()) {
String s;
if (KeepAlive > 0) {
s = "for" + KeepAlive + "" + Tunit;
} else {
s = "indefinitely";
}
This.log.debug ("Connection" + Format (Entry) + "can be kept alive" + s);
}
}
No risk
2, HttpClient 3.1
1. If you go http1.1 protocol: If the proxy-connection/connection request header is set to close, the socket will be closed, or the two headers will not be equal to closing;
2, if it is keep-alive, will not close;
3, if the protocol is less than or equal to http1.0 protocol is not a problem, call releaseconnection will close the socket;
4, other circumstances will not close;
That is, if you go http1.1 and don't set the relevant parameters, then the socket is not closed, it may cause a lot of time_wait, so if you are taking a short connection it is recommended to set Postmethod.setparameter ("Connection", " Close ").
Additional considerations:
1, use keep-alive must set Content-length head (otherwise also not long connection).
2, in the use of httpclient3.1 (4.2.3), try not to call byte[] Getresponsebody (): Because if the content-length does not set or transmit data greater than 1M, there will be a lot of the following log
Log.warn ("Going to buffer response the body of large or unknown size."
+ "Using Getresponsebodyasstream instead is recommended.");
If it is greater than 1M, the parameter can be set; but-1 is out of the way, don't call byte[] Getresponsebody ()
Httpclientparams.setlongparameter (Httpmethodparams.buffer_warn_trigger_limit, 2L * 1024 * 1024);
3, lock
HttpClient 3.1 uses Synchronized+wait+notifyall, there are two problems, a large amount of synchronized slow and notifyall can cause thread starvation; HttpClient 4.2.3 Use Reentrantlock (default is not fair) + Condition (one per thread).
Here's a test: Http://java.dzone.com/articles/synchronized-vs-lock, in my native (jdk1.6.0_43) test Results The advantage of the detail lock is relatively large
1x synchronized {} with threads took 2.621 seconds
1x Lock.lock ()/unlock () with threads took 1.951 seconds
1x Atomicinteger with threads took 4.113 seconds
1x synchronized {} with threads took 2.621 seconds
1x Lock.lock ()/unlock () with threads took 1.983 seconds
This is why there is still a lot of wait in the inventory project using HttpClient 3.1, and httpclient4.2.3 is not a problem.
If you have any questions, please enlighten me.