【问题标题】:Is keep-alive always sent in requests using httpclient and how to prevent sending it是否始终使用 httpclient 在请求中发送 keep-alive 以及如何防止发送它
【发布时间】:2019-05-22 09:40:10
【问题描述】:

我有一个 Java/Spring 项目,我在其中使用 Oauth2RestTemplate 并使其使用 HttpClient (org.apache.http.client.Httpclient) 而不是默认的 SimpleClient

HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory).build(); 

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
oAuth2RestTemplate.setRequestFactory(requestFactory);

关于这一点,我想知道/了解是否始终为所有请求发送 keep-alive 标头?

如果总是发送,有没有办法禁用发送?我看到一个帖子 - Disable Keep Alive in Apache HttpClient 谈到禁用它,但它提出了关于 httpMethod 的设置。我不确定如何在上述代码设置中访问此 httpMethod。

【问题讨论】:

  • @Andreas 从方法签名中我认为 OP 使用的是 Apache http 客户端,而不是 Java 11 http 客户端。

标签: java spring httpclient keep-alive


【解决方案1】:

使用仅返回 false 的 keepAlive() 方法实现 ConnectionReuseStrategy。请参阅HttpClientBuilder 中的setConnectionReuseStrategy()

您可能还想发送一个值为closeConnection 标头。

https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/ConnectionReuseStrategy.html

例子:

List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader(HttpHeaders.CONNECTION, "close"));
HttpClientBuilder builder = HttpClients.custom().setDefaultHeaders(headers)
  .setConnectionReuseStrategy(
    new ConnectionReuseStrategy() {
      @Override
      public boolean keepAlive(HttpResponse httpResponse, HttpContext httpContext) {
        log.info("**** keepAlive strategy returning false");
        return false;
      }
});
CloseableHttpClient httpClient = builder.build();
HttpGet httpGet = new HttpGet("https://google.com");
CloseableHttpResponse response = httpClient.execute(httpGet);
log.info("Response status: " + response.getStatusLine());
response.close();

一些附加信息:

1. Keep-Alive 标头

当大多数人说keep-alive 标头时,他们通常指的是另一个称为Connection 的标头。这两个标题一起工作:

HTTP/1.1 200 OK
...
Connection: Keep-Alive
Keep-Alive: timeout=5, max=1000
...

Connection 标头暗示应该重新使用连接。 Keep-Alive 标头指定连接应保持打开的最短时间,以及连接可重复使用的最大请求数。

Connection 标头的常见值为 keep-aliveclose。服务器和客户端都可以发送此标头。如果Connection 标头设置为close,则Keep-Alive 标头将被忽略。

2。 HTTP/1.1 和 HTTP/2

使用 HTTP/1.1,默认情况下连接是持久的。 Keep-Alive 标头已被弃用(不再在 HTTP 规范中定义),尽管许多服务器仍然发送它们以实现向后兼容性。

无法处理 HTTP/1.1 持久连接的客户端应设置 Connection 标头,其值为 close

HTTP/2 使用多路复用; ConnectionKeep-Alive 标头都不应该与 HTTP/2 一起使用。

3.代理和缓存的影响

一般来说,持久连接不能通过非透明代理工作。他们会默默地删除任何 ConnectionKeep-Alive 标头。

4.连接处理

由于持久连接现在是 HTTP/1.1 的默认设置,因此我们需要一种机制来控制何时/如何使用它们。对于 Apache http 客户端,ConnectionReuseStrategy 确定连接是否应该是持久的,而ConnectionKeepAliveStrategy 指定连接可重用的最大空闲时间。

【讨论】:

  • 我尝试将其设置为:HttpClients.custom().setSSLSocketFactory(socketFactory).setConnectionReuseStrategy(connectionReuseStrategy).build(); ConnectionReuseStrategy connectionReuseStrategy = new ConnectionReuseStrategy() { @Override public boolean keepAlive(HttpResponse response, HttpContext context) { System.out.println("in connectionReuseStrategy **************");返回假; } };我不确定如何测试这是否真的有效。此外,上面的打印语句没有被打印
  • 嗯,不知道为什么它没有被调用。我刚刚添加了一个示例(上图),每个 execute() 至少调用一次。但是您要具体解决什么问题?在您的原始帖子中,您提到阻止客户端发送 keep-alive 标头,但 http keep-alive header (具体而言)实际上是由服务器(而不是客户端)发送的,实际上已被弃用HTTP/1.1 中的行为——被持久连接取代。
  • 所以,现在,据我所知,keep-live 仅在服务器的响应中发送。重写 keepAlive 方法以返回 false 究竟做了什么?它会阻止在响应中返回保持活动状态吗?或者仍然会返回keep-alive作为响应,尽管看到keep-alive,覆盖只会关闭连接?我正在尝试了解它是如何工作的
  • 我说错了一点,从技术上讲,客户端可以发送 keep-alive 标头。但通常您要发送给 prevent keep-alives 的是一个不同的标头,称为 Connection。我已经用更多信息更新了答案,希望有助于澄清问题。
  • 您设置connectionReusestrategy(覆盖keepAlive以返回false)的答案是否会阻止发送连接Connection: Keep-Alive?尽管使用了 connectionReuseStrategy,我仍然看到它发送了
猜你喜欢
  • 2012-06-09
  • 2017-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
  • 2018-05-04
  • 2016-04-14
相关资源
最近更新 更多