HttpClient Timeout

1. Overview

This tutorial will show how to configure a timeout with the Apache HttpClient 4.

If you want to dig deeper and learn other cool things you can do with the HttpClient – head on over to the main HttpClient tutorial.

2. Configure Timeouts via raw String Parameters

The HttpClient comes with a lot of configuration parameters – and all of these can be set in a generic, map-like manner.

There are 3 timeout parameters to configure:


1

2

3

4

5

6

7

8

9

10

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

A quick note is that the last parameter – the connection manager timeout – is commented out when using the 4.3.0 or 4.3.1 versions, because of this JIRA (due in 4.3.2).

3. Configure Timeouts via the API

The more important of these parameters – namely the first two – can also be set via a more type safe API:


1

2

3

4

5

6

7

8

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

The third parameter doesn’t have a custom setter in HttpConnectionParams, and it will still need to be set manually via the setParameter method.

4. Configure Timeouts using the new 4.3. Builder

The fluent, builder API introduced in 4.3 provides the right way to set timeouts at a high level:


1

2

3

4

5

6

7

int timeout = 5;

RequestConfig config = RequestConfig.custom()

  .setConnectTimeout(timeout * 1000)

  .setConnectionRequestTimeout(timeout * 1000)

  .setSocketTimeout(timeout * 1000).build();

CloseableHttpClient client =

  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

That is the recommended way of configuring all three timeouts in a type-safe and readable manner.

5. Timeout Properties Explained

Now, let’s explain what these various types of timeouts mean:

  • the Connection Timeout (http.connection.timeout) – the time to establish the connection with the remote host
  • the Socket Timeout (http.socket.timeout) – the time waiting for data – after the connection was established; maximum time of inactivity between two data packets
  • the Connection Manager Timeout (http.connection-manager.timeout) – the time to wait for a connection from the connection manager/pool

The first two parameters – the connection and socket timeouts – are the most important, but setting a timeout for obtaining a connection is definitely important in high load scenarios, which is why the third parameter shouldn’t be ignored.

6. Using the HttpClient

After being configured, the client can not be used to perform HTTP requests:


1

2

3

4

HttpGet getMethod = new HttpGet("http://host:8080/path");

HttpResponse response = httpClient.execute(getMethod);

System.out.println(

  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

With the previously defined client, the connection to the host will time out in 5 seconds, and if the connection is established but no data is received, the timeout will also be 5 additional seconds.

Note that the connection timeout will result in an org.apache.http.conn.ConnectTimeoutException being thrown, while socket timeout will result in java.net.SocketTimeoutException.

7. Hard Timeout

While setting timeouts on establishing the HTTP connection and not receiving data is very useful, sometimes we need to set a hard timeout for the entire request.

For example, the download of a potentially large file fits into this category – in this case, the connection may be successfully established, data may be consistently coming through, but we still need to ensure that the operation doesn’t go over some specific time threshold.

HttpClient doesn’t have any configuration that allows us to set an overall timeout for a request; it does, however, provide abort functionality for requests, so we can leverage that mechanism to implement a simple timeout mechanism:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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

We’re making use of the java.util.Timer and java.util.TimerTask to set up a simple delayed task which aborts the HTTP GET request after a 5 seconds hard timeout.

8. Timeout and DNS Round Robin – something to be aware of

It is quite common that some larger domains will be using a DNS round robin configuration – essentially having the same domain mapped to multiple IP addresses. This introduces a new challenge for a timeout against such a domain, simply because of the way HttpClient will try to connect to that domain that times out:

  • HttpClient gets the list of IP routes to that domain
  • it tries the first one – that times out (with the timeouts we configure)
  • it tries the second one – that also times out
  • and so on …

So, as you can see – the overall operation will not time out when we expect it to. Instead – it will time out when all the possible routes have timed out, and what it more – this will happen completely transparently for the client (unless you have your log configured at the DEBUG level). Here is a simple example you can run and replicate this issue:


1

2

3

4

5

6

7

8

9

10

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

You will notice the retrying logic with a DEBUG log level:


1

2

3

4

5

6

7

8

9

10

11

12

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

//...

9. Conclusion

This tutorial discussed how to configure the various types of timeouts available for an HttpClient. It also illustrated a simple mechanism for hard timeout of an ongoing HTTP connection.

The implementation of these examples can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

时间: 2024-11-06 03:33:33

HttpClient Timeout的相关文章

httpclient之get/post

终于搞得差不多明白了,总结如下(省略了try catch),参考自这里 1.get: 一坨url带着"编码好"(urlencode需要自己处理)的参数(可以看到)一块发送给服务器:eg: public async Task<string> GetAsync(string uri) { var httpClient = new HttpClient {Timeout = new TimeSpan(0, 0, 0, 17)}; var content = await httpC

Asp.Net Core 轻松学-HttpClient的演进和避坑

前言 ????在 Asp.Net Core 1.0 时代,由于设计上的问题, HttpClient 给开发者带来了无尽的困扰,用 Asp.Net Core 开发团队的话来说就是:我们注意到,HttpClient 被很多开发人员不正确的使用.得益于 .Net Core 不断的版本快速升级:解决方案也一一浮出水面,本文尝试从各个业务场景去剖析 HttpClient 的各种使用方式,从而在开发中正确的使用 HttpClient 进行网络请求. 1.0时代发生的事情 1.1 在 1.0 时代,部署在 L

C# .net 中 Timeout 的处理及遇到的问题

C# 中 Timeout 的处理 前言 最近在项目中要实现一个功能,是关于 Timeout 的,主要是要在要在 TCP 连接建立的时间 和 整个请求完成的时间,在这两个时间层面上,如果超出了设置的时间,就抛出异常,程序中断. 研究了一下项目的代码中,发现在使用HTTP协议,发送请求时,主要用的是微软的 Microsoft.Net.HttpWebRequest 这个类来发起请求和接收请求的.当时我隐约记得这个类怎么有点熟悉呀,好像还有 WebRequst 和 HttpClient 这两个把,还没开

NetCore 阿里大于发送短信

使用阿里大于API发送短信,但阿里没有提供NetCore 的API,自己看了下源码重写了发短信这个部分 public class MessageSender { private readonly string _appKey; private readonly string _appSecret; private readonly string _serverUrl; public MessageSender(string url, string appKey, string appSecret

crm on premise IFD 部署下提供oauth 2.0 集成自定义应用

很多情况下我们的CRM系统会和弟三方应用集成,一般情况我们会开发一个中间站点来提供web api 给弟三方应用. 利用adfs 带的auto2.0可以有一种简单的方式和弟三方应用集成.我们做的只需要类似像和微信.微博.QQ集成弟三登录功能一样实现 ADFS oauth 2.0 弟一步 在ADFS上注册一个client ,生成的 ClientId.RedirectUri (指跳转页面),在ADFS中没有密码这个属性,在请求code的时候 会用这两个属性代替clientid和密码 Add-AdfsC

接口post +json +bean

public ReturnBean<DealBean> getMember(String tagtype, String tag) { try { String requestUrl = getObjectUrl(SynUrl.getMemberByCondition, new String[] { "vendorId", "posCode", "tagtype", "tag", }, new Object[] {

C# 请求Web Api 接口,返回的json数据直接反序列化为实体类

需要的引用的dll类: Newtonsoft.Json.dll.System.Net.Http.dll.System.Net.Http.Formatting.dll Web Api接口为GET形式: public static CstyleCmappListRespDTO GetCstyleCmappList(string cstylename, string cmappgname) { CstyleCmappListRespDTO RespDTO = new CstyleCmappListRe

http请求端口占用异常

解决思路: 1.  ESTABLISHED 过多,使用static解决 static HttpClientHandler StaticHttpClientHandler = new HttpClientHandler { AllowAutoRedirect = true, Proxy = new System.Net.WebProxy(ConfigHelper.FacebookProxyHostUrl) }; static HttpClient StaticHttpClient = new Ht

在后端C#中 call web api

我们要想使用web api, 需要首先在azure 中创建application. (如何创建application可以参考我的另一篇blog 从O365中获取users到D365中 ) Get 我们可以用JObject 和 JArray 来快速获取而不需要DeserializeObject //server-side online oauth2 var sessionResult = (Opportunity)Session["OpportunityData"]; var httpU