博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HttpClient Timeout设置
阅读量:6858 次
发布时间:2019-06-26

本文共 4562 字,大约阅读时间需要 15 分钟。

  hot3.png

总览

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

使用String参数配置Timeouts

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

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

DefaultHttpClient httpClient = new DefaultHttpClient(); int timeout = 5; // secondsHttpParams 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版本时应该被注释掉,具体请参考说明。

使用API配置Timeout

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

DefaultHttpClient httpClient = new DefaultHttpClient(); int timeout = 5; // secondsHttpParams httpParams = httpClient.getParams();HttpConnectionParams.setConnectionTimeout(  httpParams, timeout * 1000); // http.connection.timeoutHttpConnectionParams.setSoTimeout(  httpParams, timeout * 1000); // http.socket.timeout

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

##使用 4.3 Builder API配置Timeout

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

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请求:

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为请求提供终止功能,我们可以利用这个机制来实现一个简单的超时策略:

HttpGet getMethod = new HttpGet(  "http://localhost:8080/spring-security-rest-template/api/bars/1"); int hardTimeout = 5; // secondsTimerTask 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级别的日志)。下面是一个简单的例子,您可以运行和重现这个问题:

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日志中你将注意到以下重试逻辑:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81DEBUG 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:81DEBUG 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:81DEBUG 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连接建立一个简单的硬超时机制。

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

编译自:

转载于:https://my.oschina.net/dabird/blog/842433

你可能感兴趣的文章
【Scala】Scala之Control Structures
查看>>
三星手机拍照,从图库选择照片旋转问题完美解决
查看>>
算法笔记_173:历届试题 斐波那契(Java)
查看>>
菜鸟版JAVA设计模式—外观模式
查看>>
EasyUI----动态拼接EasyUI控件
查看>>
PHP session 跨子域问题总结 ini_set('session.cookie_domain', ".domain.com")
查看>>
Office WPS如何在页眉页脚添加一条横线
查看>>
站在 Android 开发的角度,聊聊 Airbnb 的 Lottie!!!
查看>>
数组去重Demo引出的思考
查看>>
javascript怎么禁用浏览器后退按钮
查看>>
AtomicLong可以被原子地读取和写入的底层long值的操作
查看>>
Android studio 将 Module 打包成 Jar 包
查看>>
coffee script
查看>>
正则表达式大全
查看>>
SVN switch 用法详解
查看>>
Javascript文件下载顺序问题
查看>>
程序员第一定律:关于技能与收入
查看>>
网络通讯合并数据发送的重要性和实现原理
查看>>
Jquery getJSON 实现跨域请求 --- callback
查看>>
<转载>构造函数与拷贝构造函数
查看>>