HttpClient:如何与服务器只有一个连接?

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

此代码为每个请求创建到 RESTful 服务器的新连接,而不是仅使用现有连接。如何更改代码,以便只有一个连接?

行 "response = oClientCloseable.execute(...)" 不仅完成了任务,还创建了一个连接。

我检查了服务器守护程序日志,只有 activity 从 .execute() 方法生成。

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();

服务器守护程序日志在连接时发出以下内容。

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 似乎是最相关的,因为它谈论消耗(关闭)连接,这与响应有关。该文章也已过时,因为 consumeContent 已被弃用。似乎 response.close() 是正确的方法,但这会关闭连接,新的响应会创建一个新的连接。

看来我需要以某种方式创建一个对 serer 守护程序的响应,然后更改操作(获取、post、放置或删除)。

关于代码应该如何更改的想法?

以下是我使用的其他一些链接:

link 1 link 2 link 3

我通过将开头代码替换为以下内容来实施 Robert Rowntree 的建议(抱歉不确定是否正确引用名称):

// 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();

我还看到了那一堆验证码。

我联系了供应商并与他们分享了使用修改后版本的日志,我的代码很干净。

我的测试样本创建了一个连接(到远程服务器),然后删除了连接并重复了很多次。每次连接创建请求到达时,他们的代码都会转储身份验证消息。

有人指出我在技术上已经知道创建新 RESTful 服务连接的行始终是 "XXXXX connection allowed"。有一个,如果你算上我之后进入基于浏览器的界面以确保我的所有链接都消失的话,还有两个。

很遗憾,我不确定我是否可以使用 Apache 客户端,很遗憾。 Apache 不支持 GET 请求中的消息体。对于头脑简单的人(我,在这种情况下),Apache 不允许:

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

Apache HttpClient --> HttpGet 没有 setEntities 命令。研究表明,作为一个 POST 请求,但服务是这样的,不会改变,所以...

您绝对可以在 Apache HttpClient 中使用查询参数:

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