Thanks Alexey for the apply。 I tried it, and sorry that it still doesn't work.
I am using one thread to sending http request for 1000 times every 20
milliseconds. Some response time are as follows:
As you can see, the response time is not stable at all, (there are ocurrences
with 7~10 seconds). If I don't use pool connection manager, then the response
time are very stable, about 200 milliseconds for each request.
Is there code example that issuing HTTP request with pool connection manager
and apply the best practices for the CloseableHttpClient/response release/close
or related things. So that, I can compare it with mine, and hopefully find
whether the problem is.
Thanks.
My testing code snippet:
public void test() {
long allStart = System.currentTimeMillis();
while (i++ < loop) {
long start = System.currentTimeMillis();
HttpUtils.httpInvoke(TEST_URL, null, null); //This the core code that issuing
http request.
long a = System.currentTimeMillis() - start;
String timeSpent = "" + (a >= 1000 ? a + "(>1000)" : a);
writeToFile(timeSpent + "\n", logFile);
Thread.sleep(loopInterval);
}
writeToFile("Total time spent: " + (System.currentTimeMillis() - allStart) +
"\n", logFile);
}
26
30
235
439
851
1667
1040
234
439
851
1671
3310
25
27
26
238
25
234
435
24
235
24
26
27
25
232
27
26
37
29
28
251
472
915
1804
3580
7132
10057
28
26
253
26
25
23
243
24
24
27
26
1025
27
29
24
23
[email protected]
From: Alexey Panchenko
Date: 2015-07-08 11:42
To: HttpClient User Discussion
Subject: Re: Re: httpclient4 is extremely slow than correpsoning code of
HttpClient3
AFAIK there is no need in creating a new HttpClient instance every time, it
should be created once and reused.
On Wed, Jul 8, 2015 at 9:29 AM, [email protected] <[email protected]> wrote:
> One more thing that I noticed is:
>
> When I constructing the CloseableHttpClient, response time gets back to
> normal if I don't pass the PoolingHttpClientConnectionManager object to the
> HttpClientBuilder
>
> HttpClientBuilder httpClientBuilder = HttpClients.custom();
>
> /*comment this code so that no PoolingHttpClientConnectionManager will
> be used!*/
> //httpClientBuilder.setConnectionManager(cm);
>
> //other configurations
> return httpClientBuilder.build();
>
> Seems that there are something related with
> PoolingHttpClientConnectionManager that cause the request's response time
> is abnormally long.
>
> Here is my code about PoolingHttpClientConnectionManager :
>
> cm = new PoolingHttpClientConnectionManager();
> cm.setMaxTotal(1024);
> cm.setDefaultMaxPerRoute(128);
>
>
>
> [email protected]
>
> From: [email protected]
> Date: 2015-07-08 10:25
> To: httpclient-users
> Subject: Re: Re: httpclient4 is extremely slow than correpsoning code of
> HttpClient3
> Thanks Stefan for the reply.
>
> Do you mean that I move the CloseableHttpClient out of the try block like
> following,
>
> public String execute(HttpGet httpGet) {
> String body = "";
> CloseableHttpClient httpclient = this.getHttpclient();
> try{
> CloseableHttpResponse response = httpclient.execute(httpGet);
> int status = response.getStatusLine().getStatusCode();
> ///other codes goes for consuming response
>
> Unfortunately, It still doesn't work for me, and I still see that the
> request time is abnormally long.
>
> One thing I notice, is that when I set the socket time out to be 10
> seconds, there are couple of requests throw exception due to socket time
> out. So I wonder what may cause socket time out issue. With httpclient3, I
> see no such problems, and the longest request time is no more that 2
> seconds.
>
>
>
>
>
>
> [email protected]
> From: Stefan Magnus Landrø
> Date: 2015-07-08 00:33
> To: HttpClient User Discussion
> Subject: Re: httpclient4 is extremely slow than correpsoning code of
> HttpClient3
> >> try{
> >> CloseableHttpClient httpclient =
> Try with resources will close client
> Sendt fra min iPhone
> > Den 7. jul. 2015 kl. 16.59 skrev Todd <[email protected]>:
> >
> > Thanks Stefan for the reply. Could you please point to me which code you
> are referring to?
> >
> >
> >
> > At 2015-07-07 22:49:28, "Stefan Magnus Landrø" <[email protected]>
> wrote:
> >> You shouldn't close http client on every request, only response
> >>
> >> Sendt fra min iPhone
> >>
> >>> Den 7. jul. 2015 kl. 16.05 skrev "[email protected]" <[email protected]>:
> >>>
> >>>
> >>> Can someone kindly help me on this? Thanks a lot!
> >>>
> >>>
> >>>
> >>>
> >>> [email protected]
> >>>
> >>> From: [email protected]
> >>> Date: 2015-07-07 20:51
> >>> To: httpclient-users
> >>> Subject: httpclient4 is extremely slow than correpsoning code of
> HttpClient3
> >>>
> >>> I have following http client code(HttpUtils and HttpClientManager)with
> HttpClient 4.3.6, and a httpclient code in 3.1, and a test case as well. I
> observed that HttpClient 4.3.6 is very much slowly than HttpClient 3.1
> code. In HttpClient 4.3.6 version code, there are a lot
> >>> socket time out error(the socket time is 10 seconds).
> >>>
> >>> I pasted the related classes and code below. It is kind of long code,
> but I still would ask you do me a favor to review the http client
> configuration that may cause the problem. Many Thanks in advance.
> >>>
> >>> Following codes include:
> >>> 1. HttpClient 4.3.6 code to issue HttpGet request
> >>> 2. HttpClient 3.1 code to issue HttpGet request
> >>> 3. Test Case that demontrate the problem.
> >>>
> >>>
> >>> ############################################Http Client 4.3.6 Code
> goes here############################################
> >>>
> ///////////////////////////HttpUtils//////////////////////////////////////////
> >>> import java.util.ArrayList;
> >>> import java.util.List;
> >>> import java.util.Map;
> >>>
> >>> import org.apache.http.Consts;
> >>> import org.apache.http.NameValuePair;
> >>> import org.apache.http.client.config.RequestConfig;
> >>> import org.apache.http.client.entity.UrlEncodedFormEntity;
> >>> import org.apache.http.client.methods.HttpGet;
> >>> import org.apache.http.client.methods.HttpPost;
> >>> import org.apache.http.message.BasicNameValuePair;
> >>> import org.slf4j.Logger;
> >>> import org.slf4j.LoggerFactory;
> >>>
> >>>
> >>>
> >>> public class HttpUtils {
> >>>
> >>> ///This is the util method that will be used to issue http request.
> >>> public static String httpInvoke(String httpUrl, Map<String, Object>
> parameters, RequestConfig config){
> >>> HttpClientManager httpClientConnectionManager =
> HttpClientManager.getHttpClientConnectionManagerInstance();
> >>> HttpGet httpGet = new HttpGet(httpUrl);
> >>> if(config != null ){
> >>> httpGet.setConfig(config);
> >>> }
> >>> String result = httpClientConnectionManager.execute(httpGet);
> >>> return result;
> >>> }
> >>> }
> >>>
> >>>
> //////////////////////////////////HttpClientManager/////////////////////////////////
> >>>
> >>> import java.nio.charset.CodingErrorAction;
> >>> import java.util.ArrayList;
> >>> import java.util.Collection;
> >>>
> >>> import org.apache.commons.httpclient.Header;
> >>> import org.apache.commons.httpclient.HttpStatus;
> >>> import org.apache.commons.lang3.StringUtils;
> >>> import org.apache.http.Consts;
> >>> import org.apache.http.HttpEntity;
> >>> import org.apache.http.HttpHost;
> >>> import org.apache.http.client.config.RequestConfig;
> >>> import org.apache.http.client.entity.GzipDecompressingEntity;
> >>> import org.apache.http.client.methods.CloseableHttpResponse;
> >>> import org.apache.http.client.methods.HttpGet;
> >>> import org.apache.http.client.methods.HttpPost;
> >>> import org.apache.http.config.ConnectionConfig;
> >>> import org.apache.http.config.MessageConstraints;
> >>> import org.apache.http.config.SocketConfig;
> >>> import org.apache.http.impl.client.CloseableHttpClient;
> >>> import org.apache.http.impl.client.HttpClientBuilder;
> >>> import org.apache.http.impl.client.HttpClients;
> >>> import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
> >>> import org.apache.http.message.BasicHeader;
> >>> import org.apache.http.params.CoreProtocolPNames;
> >>> import org.apache.http.util.EntityUtils;
> >>> import org.slf4j.Logger;
> >>> import org.slf4j.LoggerFactory;
> >>>
> >>>
> >>> ///Main class that encapsulate the Http Client
> >>> public class HttpClientManager {
> >>> private static Logger logger =
> LoggerFactory.getLogger(HttpClientManager.class);
> >>>
> >>> private static int defaultConnectionTimeout = 10*1000; //connection
> timeout
> >>> private static int defaultSocketTimeout = 10*1000; //socket time out
> >>> private static int connectionRequestTimeout = 10*1000; //connection
> request timeout
> >>>
> >>> private static int defaultMaxRouteConnections = 128;
> >>> private static int defaultMaxTotalConnections = 1024;
> >>>
> >>> private static int defaultMaxHeaderCount = 200;
> >>> private static int defaultMaxLineLength = 2000;
> >>>
> >>> private static String Charset = "utf-8";
> >>>
> >>> private String proxyHost = null;
> >>> private String proxyPort =null;
> >>>
> >>> private PoolingHttpClientConnectionManager cm;
> >>>
> >>> private final static HttpClientManager httpClientConnectionManager =
> new HttpClientManager();
> >>>
> >>> private HttpClientManager() {
> >>> logger.info("HttpClientManager initial!");
> >>> cm = new PoolingHttpClientConnectionManager();
> >>> cm.setMaxTotal(defaultMaxTotalConnections);
> >>> cm.setDefaultMaxPerRoute(defaultMaxRouteConnections);
> >>> }
> >>>
> >>>
> >>> private CloseableHttpClient getHttpclient(){
> >>> HttpClientBuilder httpClientBuilder = HttpClients.custom();
> >>> httpClientBuilder.setConnectionManager(cm);
> >>>
> >>> RequestConfig.Builder requestConfigBuilder = RequestConfig.custom()
> >>> .setConnectTimeout(defaultConnectionTimeout)
> >>> .setSocketTimeout(defaultSocketTimeout)
> >>> .setConnectionRequestTimeout(connectionRequestTimeout)
> >>> .setExpectContinueEnabled(false)
> >>> .setStaleConnectionCheckEnabled(true);
> >>>
> >>> if(StringUtils.isNotBlank(proxyHost) &&
> StringUtils.isNotBlank(proxyPort)){
> >>> try{
> >>> logger.info("using proxy, proxyHost:{}, proxyPort:{}", proxyHost,
> proxyPort);
> >>> int proxyPortInt = Integer.parseInt(proxyPort);
> >>> requestConfigBuilder.setProxy(new HttpHost(proxyHost, proxyPortInt));
> >>> } catch(Exception e){
> >>> logger.error("parseInt proxyPort:{}", proxyPort, e);
> >>> }
> >>> }
> >>>
> >>> SocketConfig socketConfig =
> SocketConfig.custom().setTcpNoDelay(true).build();
> >>>
> >>> MessageConstraints messageConstraints =
> MessageConstraints.custom().setMaxHeaderCount(defaultMaxHeaderCount).setMaxLineLength(defaultMaxLineLength).build();
> >>>
> >>> ConnectionConfig connectionConfig = ConnectionConfig.custom()
> >>> .setMalformedInputAction(CodingErrorAction.IGNORE)
> >>> .setUnmappableInputAction(CodingErrorAction.IGNORE)
> >>> .setCharset(Consts.UTF_8)
> >>> .setMessageConstraints(messageConstraints).build();
> >>>
> >>> Collection<BasicHeader> collection = new ArrayList<BasicHeader>();
> >>> collection.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows; U;
> Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3"));
> >>> collection.add(new BasicHeader("Accept-Language",
> "zh-cn,zh,en-US,en;q=0.5"));
> >>> collection.add(new BasicHeader("Accept-Charset", Charset));
> >>> collection.add(new BasicHeader("Accept-Encoding", "gzip"));
> >>>
> >>>
> httpClientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
> >>> httpClientBuilder.setDefaultSocketConfig(socketConfig);
> >>> httpClientBuilder.setDefaultConnectionConfig(connectionConfig);
> >>> httpClientBuilder.setDefaultHeaders(collection);
> >>>
> >>> return httpClientBuilder.build();
> >>> }
> >>>
> >>> ///This is the method that will be call the execute the HttpGet request
> >>> public String execute(HttpGet httpGet) {
> >>> String body = "";
> >>> try{
> >>> CloseableHttpClient httpclient = this.getHttpclient();
> >>> CloseableHttpResponse response = httpclient.execute(httpGet);
> >>> int status = response.getStatusLine().getStatusCode();
> >>> try {
> >>> if (status == HttpStatus.SC_OK) {
> >>> HttpEntity entity = response.getEntity();
> >>> if (entity != null) {
> >>> Header header = (Header) entity.getContentEncoding();
> >>> if(header != null && "gzip".equals(header.getValue())){
> >>> body = EntityUtils.toString(new GzipDecompressingEntity(entity),
> Charset);
> >>> } else {
> >>> body = EntityUtils.toString(entity, Charset);
> >>> }
> >>> }
> >>> } else {
> >>> logger.error("[httpClientManager] [fail] [httpGet:{}] [status:{}]",
> httpGet, status);
> >>> }
> >>> } finally {
> >>> response.close();
> >>> }
> >>> } catch(Exception e) {
> >>> logger.error("[module:httpClientManager] [action:execute] [httpGet:{}]
> [error:{}] ", httpGet, e.getMessage(), e);
> >>> }
> >>> return body;
> >>> }
> >>>
> >>>
> >>> ////Singleton object that will be used to access
> httpClientConnectionManager
> >>> public static HttpClientManager
> getHttpClientConnectionManagerInstance(){
> >>> return httpClientConnectionManager;
> >>> }
> >>>
> >>> }
> >>>
> >>>
> >>> ##################################################My HttpClient 1.3
> code goes here###########################################
> >>>
> >>> import org.apache.commons.httpclient.HttpClient;
> >>> import org.apache.commons.httpclient.HttpMethod;
> >>> import org.apache.commons.httpclient.methods.GetMethod;
> >>>
> >>> import java.io.BufferedReader;
> >>> import java.io.IOException;
> >>> import java.io.InputStream;
> >>> import java.io.InputStreamReader;
> >>>
> >>> public class HttpClientUtil {
> >>>
> >>> private static final HttpClientUtil INSTANCE = new HttpClientUtil();
> >>>
> >>> private static final int TIMEOUT = 10 * 1000; //10s
> >>>
> >>> private HttpClientUtil() {
> >>> }
> >>>
> >>> ///Actually, this class is more like a static class than Singleton
> >>> public static HttpClientUtil getInstance() {
> >>> return INSTANCE;
> >>> }
> >>>
> >>> //brand new http client per request
> >>> private HttpClient newHttpClient() {
> >>> HttpClient client = new HttpClient();
> >>>
> client.getHttpConnectionManager().getParams().setConnectionTimeout(TIMEOUT);
> >>> client.getHttpConnectionManager().getParams().setSoTimeout(TIMEOUT);
> >>> return client;
> >>> }
> >>>
> >>> //FIXME The encoding should be provided when convert the response
> binary stream into string
> >>> public static String responseBodyAsString(HttpMethod method) throws
> IOException {
> >>> BufferedReader br = null;
> >>> String lsr = System.getProperty("line.separator");
> >>> try {
> >>> InputStream in = method.getResponseBodyAsStream();
> >>> br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
> >>> StringBuffer sb = new StringBuffer();
> >>> String line;
> >>> while ((line = br.readLine()) != null) {
> >>> sb.append(line).append(lsr);
> >>> }
> >>> return sb.toString();
> >>> } finally {
> >>> if (br != null) {
> >>> br.close();
> >>> }
> >>> }
> >>> }
> >>>
> >>> /////This is the method that will HttpGet to the url
> >>> public String get(String url) throws IOException {
> >>> GetMethod pm = new GetMethod(url);
> >>> pm.setRequestHeader("Connection", "close");
> >>> HttpClient client = newHttpClient();
> >>> try {
> >>> client.executeMethod(pm);
> >>> String response = responseBodyAsString(pm);
> >>> return response;
> >>> } finally {
> >>> pm.releaseConnection();
> >>> }
> >>> }
> >>> }
> >>>
> >>> ##########################################Test
> Case##########################################
> >>> The following code runs in the one thread in the junit test
> >>> while (i++ < 5000) {
> >>> long start = System.currentTimeMillis();
> >>> HttpUtils.httpInvoke(TEST_URL, null, null);
> >>> long a = System.currentTimeMillis() - start;
> >>> String timeSpent = "" + (a >= 1000 ? a + "(>1000)" : a);
> >>> writeToFile(timeSpent + "\n", logFile);
> >>> Thread.sleep(loopInterval);
> >>> }
> >>>
> >>>
> >>>
> >>>
> >>>
> >>> [email protected]
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: [email protected]
> >> For additional commands, e-mail: [email protected]
> >>
>