简体   繁体   中英

HttpClient: How to have only one connection to the server?

This code creates a new connection to the RESTful server for each request rather than just use the existing connection. How do I change the code, so that there is only one connection?

The line "response = oClientCloseable.execute(...)" not only does the task, but creates a connection.

I checked the server daemon log and the only activity generates from the .execute() method.

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

...

String pathPost = "http://someurl";
String pathDelete = "http://someurl2";
String xmlPost = "myxml";
HttpResponse response = null;
BufferedReader rd = null;
String line = null;

CloseableHttpClient oClientCloseable = HttpClientBuilder.create().setDefaultRequestConfig(defaultRequestConfig).build();

for (int iLoop = 0; iLoop < 25; iLoop++)
{
    HttpPost hPost = new HttpPost(pathPost);
    hPost.setHeader("Content-Type", "application/xml");
    StringEntity se = new StringEntity(xmlPost);
    hPost.setEntity(se);
    line = "";
    try
    {
        response = oClientCloseable.execute(hPost);
        rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        while ((line = rd.readLine()) != null)
        {
            System.out.println(line);
        }
    }
    catch (ClientProtocolException e)
    {
        e.printStackTrace();
    }
    catch (ConnectionPoolTimeoutException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    finally
    {
        HttpClientUtils.closeQuietly(response);
    }

    HttpDelete hDelete = new HttpDelete(pathDelete);
    hDelete.setHeader("Content-Type", "application/xml");
    try
    {
        response = oClientCloseable.execute(hDelete);
    }
    catch (ClientProtocolException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    finally
    {
        HttpClientUtils.closeQuietly(response);
    }
}

oClientCloseable.close();

The server daemon log emits the following for whatever it is worth, when connecting.

HTTP connection from [192.168.20.86]...ALLOWED
POST [/linx] SIZE 248
LINK-18446744073709551615: 2 SEND-BMQs, 2 RECV-BMQs
THREAD-LINK_CONNECT-000, TID: 7F0F1B7FE700 READY
NODE connecting to [192.168.30.20]:9099...
LINK-0-CONTROL-NODE-0 connected to 192.168.30.20(192.168.30.20 IPv4 address: 192.168.30.20):9099
Auth accepted, protocol compatible
NODE connecting to [192.168.30.20]:9099...

This article seems the most relevant, as it talks about consuming (closing) connections, which ties in the response. That article is also out of date, as consumeContent is deprecated. It seems that response.close() is the proper way, but that closes the connection and a new response creates a new connection.

It seems that I need to somehow create one response to the serer daemon and then change action (get, post, put, or delete).

Thoughts on how the code should change?

Here are some other links that I used:

link 1 link 2 link 3

I implemented the suggestion of Robert Rowntree (sorry not sure to properly reference name) by replacing the beginning code with:

// Increase max total connection to 200 and increase default max connection per route to 20. 
// Configure total max or per route limits for persistent connections
// that can be kept in the pool or leased by the connection manager.
PoolingHttpClientConnectionManager oConnectionMgr = new PoolingHttpClientConnectionManager();
oConnectionMgr.setMaxTotal(200);
oConnectionMgr.setDefaultMaxPerRoute(20);
oConnectionMgr.setMaxPerRoute(new HttpRoute(new HttpHost("192.168.20.120", 8080)), 20);

RequestConfig defaultRequestConfig = RequestConfig.custom()
        .setSocketTimeout(5000)
        .setConnectTimeout(5000)
        .setConnectionRequestTimeout(5000)
        .setStaleConnectionCheckEnabled(true)
        .build();

//HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(defaultRequestConfig).build();
CloseableHttpClient oClientCloseable = HttpClientBuilder.create()
        .setConnectionManager(oConnectionMgr)
        .setDefaultRequestConfig(defaultRequestConfig)
        .build();

I still saw the bunch of authenticates.

I contacted the vendor and shared with them the log using the modified version and my code was clean.

My test sample created a connection (to a remote server) followed by deleting the connection and repeating however many times. Their code dumps the authenticate message each time a connection creation request arrives.

I was pointed to what technically I already knew that the line that creates a new RESTful connection to the service is always "XXXXX connection allowed". There was one of those, two if you count my going to the browser based interface afterwards to make sure that all my links were gone.

Sadly, I am not sure that I can use the Apache client, so sad. Apache does not support message bodies inside a GET request. To the simple minded here (me, in this case), Apache does not allow:

GET http://www.example.com/whatevermethod:myport?arg1=data1&arg2=data2

Apache HttpClient --> HttpGet does not have a setEntities command. Research showed that as a POST request, but the service is the way that it is and will not change, so...

You can definitely use query parameters in Apache HttpClient:

URIBuilder builder = new URIBuilder("http://www.example.com/whatevermehtod");
builder.addParameter("arg1", "data1");
URI uri = builder.build();
HttpGet get = new HttpGet(uri);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM