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

时间:2010-06-08 18:36:32

标签: java http timeout network-protocols

我想在我的云中为多个服务器制作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>

9 个答案:

答案 0 :(得分:114)

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 :(得分:106)

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

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

答案 2 :(得分:29)

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

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

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

答案 3 :(得分: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;
}

答案 4 :(得分:7)

我发现在HttpConnectionParamsHttpConnectionManager设置超时设置并没有解决我们的问题。我们仅限于使用org.apache.commons.httpclient版本3.0.1。

我最终使用java.util.concurrent.ExecutorService来监控HttpClient.executeMethod()来电。

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

答案 5 :(得分:6)

Laz最高级别的上述方法已从4.3版开始弃用。因此,最好使用Request Config Object然后构建HTTP Client

    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对象。您还可以设置属性Connection Request Timeout,以设置从Connection Manager等待连接的超时。

答案 6 :(得分:5)

上面benvoliot的评论中已经提到过这一点。但是,我认为它值得一个顶级职位,因为它确实让我摸不着头脑。我发布这个是为了帮助其他人。

我编写了一个简单的测试客户端,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

注意说

的位
  

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

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

答案 7 :(得分:2)

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

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

答案 8 :(得分:1)

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

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