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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3000214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:26:43  来源:igfitidea点击:

Java HTTP Client Request with defined timeout

javahttptimeoutnetwork-protocols

提问by Maxim Veksler

I would like to make BIT (Built in tests) to a number of server in my cloud. I need the request to fail on large timeout.

我想让 BIT(内置测试)连接到我的云中的多个服务器。我需要请求在大超时时失败。

How should I do this with java?

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

Trying something like the below does not seem to work.

尝试类似下面的方法似乎不起作用。

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

-- EDIT: Clarify what library is being used --

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

I'm using httpclient from apache, here is the relevant pom.xml section

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

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

采纳答案by laz

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

回答by dbyrne

It looks like you are using the HttpClient API, which I know nothing about, but you could write something similar to this using core Java.

看起来您正在使用 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;
}

回答by Kirby

I found that setting the time out settings in HttpConnectionParamsand HttpConnectionManagerdid not solve our case. We're limited to using org.apache.commons.httpclientversion 3.0.1.

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

I ended up using an java.util.concurrent.ExecutorServiceto monitor the HttpClient.executeMethod()call.

我最终使用 anjava.util.concurrent.ExecutorService来监视HttpClient.executeMethod()呼叫。

Here's a small, self-contained example

这是一个独立的小示例

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

回答by Mohammed Irfan Tirupattur

HttpConnectionParams.setSoTimeout(params, 10*60*1000);// for 10 mins i have set the timeout

HttpConnectionParams.setSoTimeout(params, 10*60*1000);// for 10 mins i have set the timeout

You can as well define your required time out.

您也可以定义所需的超时时间。

回答by Dan Haynes

This was already mentioned in a comment by benvoliotabove. But, I think it's worth a top-level post because it sure had me scratching my head. I'm posting this in case it helps someone else out.

这已经在上面benvoliot的评论中提到了。但是,我认为它值得一个顶级帖子,因为它确实让我摸不着头脑。我张贴这个以防它帮助别人。

I wrote a simple test client and the CoreConnectionPNames.CONNECTION_TIMEOUTtimeout works perfectly in that case. The request gets canceled if the server doesn't respond.

我写了一个简单的测试客户端,CoreConnectionPNames.CONNECTION_TIMEOUT在这种情况下超时工作完美。如果服务器没有响应,请求将被取消。

Inside the server code I was actually trying to test however, the identical code never times out.

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

Changing it to time out on the socket connection activity (CoreConnectionPNames.SO_TIMEOUT) rather than the HTTP connection (CoreConnectionPNames.CONNECTION_TIMEOUT) fixed the problem for me.

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

Also, read the Apache docs carefully: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

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

Note the bit that says

请注意说的那一点

Please note this parameter can only be applied to connections that are bound to a particular local address.

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

I hope that saves someone else all the head scratching I went through. That will teach me not to read the documentation thoroughly!

我希望能拯救别人我经历的所有头疼。这将教会我不要彻底阅读文档!

回答by Thunder

If you are using Http Client version 4.3 and above you should be using this:

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

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

回答by pmartin8

HttpParams is deprecated in the new Apache HTTPClient library. Using the code provided by Laz leads to deprecation warnings.

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

I suggest to use RequestConfig instead on your HttpGet or HttpPost instance:

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

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

回答by rtaft

Op later stated they were using Apache Commons HttpClient 3.0.1

Op 后来表示他们使用的是 Apache Commons HttpClient 3.0.1

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

回答by Arun Thundyill Saseendran

The said method with highest up's by Laz is deprecated from version 4.3 onwards. Hence it would be better to user the Request Config Object and then build the HTTP Client

从 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;
        }

The PoolingHttpClientConnectionManager is user to set the max default number of connections and the max number of conncetions per route. I have set it as 306 and 108 respectively. The default values will not be sufficient for most of the cases.

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

For setting Timeout:I have used the RequestConfig object. You can also set the property Connection Request Timeout for setting timeout for waiting for connection from Connection manager.

对于设置超时:我使用了 RequestConfig 对象。您还可以设置属性 Connection Request Timeout 以设置等待连接管理器连接的超时时间。