前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HttpClient Timeout设置

HttpClient Timeout设置

作者头像
九州暮云
发布2019-08-21 14:28:58
7.2K0
发布2019-08-21 14:28:58
举报
文章被收录于专栏:九州牧云九州牧云

总览

本教程主要讨论Apache HttpClient 4框架的timeout设置。如果想学习HttpClient的其他方面,请参考HttpClient教程

使用String参数配置Timeouts

HttpClient有许多参数配置,这些参数都可以使用一种通用的、类似map风格的方式进行设置。

以下是三个超时参数配置:

代码语言:javascript
复制
DefaultHttpClient httpClient = new DefaultHttpClient();
 
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
// httpParams.setParameter(
//   ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

尤其注意最后一个参数——连接管理器超时,在使用4.3.0 或者 4.3.1版本时应该被注释掉,具体请参考jira说明。

使用API配置Timeout

以下是通过类型安全的API来设置的方式:

代码语言:javascript
复制
DefaultHttpClient httpClient = new DefaultHttpClient();
 
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout

在HttpConnectionParams中没有提供设置第三个参数的setter方法,因此仍然需要我们手动通过调用setParameter方法来设置。

##使用 4.3 Builder API配置Timeout

4.3版本引入了基于fluent、builder操作的API,以下是设置方式:

代码语言:javascript
复制
int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = 
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

这是一种基于类型安全和可读性来配置三个超时参数的推荐方式。

##超时属性解释

现在,我们来看一下这些不同类型超时参数的具体含义:

the Connection Timeout (http.connection.timeout) – 与远程服务器建立连接的时间

the Socket Timeout (http.socket.timeout) – 建立连接之后,等待远程服务器返回数据的时间,也就是两个数据包(请求包和响应包)之间不活动的最大时间。

the Connection Manager Timeout (http.connection-manager.timeout) – 从连接管理器/池中获取一个连接的等待时间。

前两个连接和socket超时的参数,是最重要的,但是获取一个连接的超时设置在高负载情况下也同样重要,这也就是第三个参数不能被忽略的原因所在。

使用 HttpClient

设置完上面的参数之后,HttpClient还不能被用来执行HTTP请求:

代码语言:javascript
复制
HttpGet getMethod = new HttpGet("http://host:8080/path");
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

根据前面的客户端设置,连接到主机的超时时间是5秒,如果建立连接但没有收到数据,超时还将额外增加5秒。

注意这2个异常:

  • 连接超时返回的异常:org.apache.http.conn.ConnectTimeoutException
  • socket超时返回的异常:java.net.SocketTimeoutExceptio

硬超时:Hard Timeout

虽然给HTTP连接建立和等待返回结果设置超时时间十分有用,但是有时我们也需要给整个请求设置一个硬超时时间。

例如,要下载一个可能很大的文件放到当前分类,在这种情况下,也许成功建立了连接,文件数据也许会不断传递给我们,但是我们也需要确保这个操作不会超过给定时间的阈值。

HttpClient没有任何配置,允许我们给一个请求设定一个总的超时时间。然而,可以通过HttpClient为请求提供终止功能,我们可以利用这个机制来实现一个简单的超时策略:

代码语言:javascript
复制
HttpGet getMethod = new HttpGet(
  "http://localhost:8080/spring-security-rest-template/api/bars/1");
 
int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);
 
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

我们利用java.util.Timerjava.util.TimerTask 来创建一个简单的延迟任务,实现在5秒硬超时之后,终止HTTP GET请求。

超时和DNS轮循需要注意的

一些大的域名使用DNS轮循调度配置是很常见的,本质上是一个域名映射到多个IP地址上。给这样的域名设置超时是一个新的挑战,仅仅是因为HttpClient将尝试连接到那个超时的域名:

  • HttpClient 获取域名的IP列表
  • 第一次尝试连接超时(由于我们的超时配置)
  • 第二次尝试连接也超时
  • 等等 …

因此,正如你所看到的,我们期望操作是不超时的。取而代之的是,当所有可能的路由超时的时候,整个操作就会超时。这对客户端来说是透明的(除非你配置了DEBUG级别的日志)。下面是一个简单的例子,您可以运行和重现这个问题:

代码语言:javascript
复制
int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
  .setDefaultRequestConfig(config).build();
 
HttpGet request = new HttpGet("http://www.google.com:81");
response = client.execute(request);

在DEBUG日志中你将注意到以下重试逻辑:

代码语言:javascript
复制
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address
 
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address
 
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...

结论

本教程讨论了如何给HttpClient配置各种不同的可用timeout参数,还举例说明了给一个不间断的HTTP连接建立一个简单的硬超时机制。

可以在GitHub上下载这些例子的代码实现,该项目是基于Maven实现的,因此导入和运行它很容易。

编译自:http://www.baeldung.com/httpclient-timeout

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用String参数配置Timeouts
  • 使用API配置Timeout
  • 使用 HttpClient
  • 硬超时:Hard Timeout
  • 超时和DNS轮循需要注意的
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档