具有定义超时的Java HTTP客户端请求


91

我想对云中的许多服务器进行BIT(内置测试)。我需要大超时失败的请求。

我应该如何用Java做到这一点?

尝试以下操作似乎无效。

public class TestNodeAliveness {
 public static NodeStatus nodeBIT(String elasticIP) throws ClientProtocolException, IOException {
  HttpClient client = new DefaultHttpClient();
  client.getParams().setIntParameter("http.connection.timeout", 1);

  HttpUriRequest request = new HttpGet("http://192.168.20.43");
  HttpResponse response = client.execute(request);

  System.out.println(response.toString());
  return null;
 }


 public static void main(String[] args) throws ClientProtocolException, IOException {
  nodeBIT("");
 }
}

-编辑:澄清正在使用的库-

我正在使用来自Apache的httpclient,这是相关的pom.xml部分

 <dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.0.1</version>
   <type>jar</type>
 </dependency>

您正在使用什么库来实现所有HTTP功能?
nojo

谢谢你的意见。我已经更新了我的帖子。
Maxim Veksler 2010年

Answers:


119
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

...

    // set the connection timeout value to 30 seconds (30000 milliseconds)
    final HttpParams httpParams = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
    client = new DefaultHttpClient(httpParams);

1
这是做什么的?它设置了什么超时?请参阅stackoverflow.com/questions/3000767/...
马克西姆Veksler

84
Apache的HttpClient有两个单独的超时:一个等待建立TCP连接的等待时间的超时,以及一个等待下一个数据字节等待的时间的独立超时。前者为HttpConnectionParams.setConnectionTimeout(),后者为HttpConnectionParams.setSoTimeout()。
benvolioT 2011年

7
默认超时是多少?是0 =无限吗?
Tobia 2014年

1
http.connection.timeout整数建立连接之前的超时。零值表示不使用超时。
maveroid '16

26
致将来的读者:应该注意,此处引用的类现已弃用(截至2016-07-05),尽管在2010年发布时可能是一个很好的答案。请参阅此答案:stackoverflow.com/a/ 19153314/192801需要更多电流。
FrustratedWithFormsDesigner

125

如果您使用的是Http Client 4.3及更高版本,则应使用以下版本:

RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();

4
谢谢!我花了至少20分钟的时间来弄清楚在找到答案之前如何摆脱不推荐使用的命令。
vextorspace 2014年

忘了SocketTimeout。此外,没有“默认”的意思是它的默认所有HttpClientHttpClientBuilder创建从()将通过给出build()的方法?还是只是经过的那些setDefaultRequestConfig(requestConfig)我说得通吗
ADTC

@ADTC您的问题有点令人困惑:)。默认请求配置将用于使用“仅”那个HttpClient的所有HttpPost,HttpGet等实例。如果您创建了另一个HttpClient实例,则此请求配置将不与该客户端一起使用。
雷霆队

35

在新的Apache HTTPClient库中不推荐使用HttpParams。使用Laz提供的代码会导致弃用警告。

我建议在您的HttpGet或HttpPost实例上使用RequestConfig:

final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
httpPost.setConfig(params);

“使用上面的代码” << SO并不是一个论坛,由于多种因素,答案在上/下移动,所以我们不知道您指的是哪个代码。您能否说类似“使用xyz答案中的代码”?
ADTC

4
顺便说一句,简洁的答案。但是,与Thunder的答案相比,将设置RequestConfig为everyHttpPost和将其设置为default分别有什么区别HttpClient
ADTC

2
是的,您是对的,上面的代码指的是“可接受的答案”,该答案不应随时间变化。我无论如何都会更新我的答案..
pmartin8

10

看起来您正在使用HttpClient API,对此我一无所知,但是您可以使用核心Java编写类似的内容。

try {

   HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
   con.setRequestMethod("HEAD");
   con.setConnectTimeout(5000); //set timeout to 5 seconds
   return (con.getResponseCode() == HttpURLConnection.HTTP_OK);

} catch (java.net.SocketTimeoutException e) {
   return false;
} catch (java.io.IOException e) {
   return false;
}

2
这不会影响Apache HTTP Client的超时。
laz 2010年

9
从来没有声称这样做过;)
dbyrne 2010年

5
HttpURLConnection的超时概念不足。如果服务器开始响应,但随后挂起,则永远不会达到超时。由于这种差异,Apache的HttpClient是更好的选择。
benvolioT 2011年

7

我发现,设置超时时间设置中HttpConnectionParamsHttpConnectionManager没有解决我们的情况。我们仅限使用org.apache.commons.httpclient3.0.1版。

我最终使用java.util.concurrent.ExecutorService来监视HttpClient.executeMethod()通话。

这是一个小而独立的示例

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Jeff Kirby
 * @since <pre>Jun 17, 2011</pre>
 */
public class Example {

   private static final String SITE = "http://some.website.com/upload";
   private static final int TIME_OUT_SECS = 5;

   // upload a file and return the response as a string
   public String post(File file) throws IOException, InterruptedException {
      final Part[] multiPart = { new FilePart("file", file.getName(), file) };
      final EntityEnclosingMethod post = new PostMethod(SITE);
      post.setRequestEntity(new MultipartRequestEntity(multiPart, post.getParams()));
      final ExecutorService executor = Executors.newSingleThreadExecutor();
      final List<Future<Integer>> futures = executor.invokeAll(Arrays.asList(new KillableHttpClient(post)), TIME_OUT_SECS, TimeUnit.SECONDS);
      executor.shutdown();
      if(futures.get(0).isCancelled()) {
         throw new IOException(SITE + " has timed out. It has taken more than " + TIME_OUT_SECS + " seconds to respond");
      }
      return post.getResponseBodyAsString();
   }

   private static class KillableHttpClient implements Callable<Integer> {

      private final EntityEnclosingMethod post;

      private KillableHttpClient(EntityEnclosingMethod post) {
         this.post = post;
      }

      public Integer call() throws Exception {
         return new HttpClient().executeMethod(post);
      }
   }
}

7

从版本4.3开始不推荐使用Laz提出的最高方法。因此,最好使用请求配置对象,然后构建HTTP客户端

    private CloseableHttpClient createHttpClient()
        {
        CloseableHttpClient httpClient;
        CommonHelperFunctions helperFunctions = new CommonHelperFunctions();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(306);
        cm.setDefaultMaxPerRoute(108);
        RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(15000)
            .setSocketTimeout(15000).build();
        httpClient = HttpClients.custom()
            .setConnectionManager(cm)
            .setDefaultRequestConfig(requestConfig).build();
        return httpClient;
        }

PoolingHttpClientConnectionManager是用户设置每个路由的最大默认连接数和最大连接数。我分别将其设置为306和108。在大多数情况下,默认值将不足。

设置超时: 我使用了RequestConfig对象。您还可以设置属性“连接请求超时”,以设置等待来自连接管理器的连接的超时。


5

沃利奥特在评论中已经提到了这一点上面。但是,我认为这是值得的顶级职位,因为它肯定让我挠头。我发布此信息是为了防止其他人使用。

我编写了一个简单的测试客户端,CoreConnectionPNames.CONNECTION_TIMEOUT在这种情况下,超时非常有效。如果服务器不响应,则请求将被取消。

在我实际上尝试测试的服务器代码内部,相同的代码永远不会超时。

将其更改为套接字连接活动(CoreConnectionPNames.SO_TIMEOUT)而不是HTTP连接(CoreConnectionPNames.CONNECTION_TIMEOUT)超时对我来说解决了这个问题。

另外,请仔细阅读Apache文档:http : //hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

请注意,

请注意,此参数只能应用于绑定到特定本地地址的连接。

我希望这可以省去别人所有我经历过的脑袋抓伤。那会教我不要彻底阅读文档!


2

Op后来表示他们正在使用Apache Commons HttpClient 3.0.1

 HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        client.getHttpConnectionManager().getParams().setSoTimeout(5000);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.