Yêu cầu ứng dụng khách Java HTTP với thời gian chờ xác định


91

Tôi muốn tạo BIT (Thử nghiệm tích hợp sẵn) cho một số máy chủ trong đám mây của tôi. Tôi cần yêu cầu không thành công khi hết thời gian chờ lớn.

Tôi nên làm điều này như thế nào với java?

Thử một cái gì đó như bên dưới dường như không hoạt động.

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

- CHỈNH SỬA: Làm rõ thư viện nào đang được sử dụng -

Tôi đang sử dụng httpclient từ apache, đây là phần pom.xml có liên quan

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

Bạn đang sử dụng thư viện nào cho tất cả các chức năng HTTP?
nojo

Cảm ơn bạn đã bình luận. Tôi đã cập nhật bài đăng của mình.
Maxim Veksler

Câu trả lời:


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
Điều này làm gì? Thời gian chờ của những gì nó đặt ra? Vui lòng xem stackoverflow.com/questions/3000767/…
Maxim Veksler

84
HttpClient của Apache có hai thời gian chờ riêng biệt: thời gian chờ trong bao lâu để thiết lập kết nối TCP và thời gian chờ riêng trong khoảng thời gian chờ một byte dữ liệu tiếp theo. HttpConnectionParams.setConnectionTimeout () là cái trước, HttpConnectionParams.setSoTimeout () là cái sau.
benvolioT

7
Thời gian chờ mặc định là gì? Có phải 0 = vô hạn không?
Tobia

1
http.connection.timeout Số nguyên Thời gian chờ cho đến khi kết nối được thiết lập. Giá trị bằng 0 có nghĩa là thời gian chờ không được sử dụng.
maveroid

26
Đối với độc giả trong tương lai: Cần lưu ý rằng các lớp được tham chiếu ở đây hiện không được dùng nữa (kể từ 2016-07-05), mặc dù đây có thể là một câu trả lời hay khi nó được đăng vào năm 2010. Xem câu trả lời sau: stackoverflow.com/a/ 19153314/192801 cho một cái gì đó hiện tại hơn một chút.
FrustratedWithFormsDesigner

125

Nếu bạn đang sử dụng Http Client phiên bản 4.3 trở lên, bạn nên sử dụng cái này:

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

4
Cảm ơn! Tôi đã dành ít nhất 20 phút để cố gắng tìm ra cách loại bỏ các lệnh không dùng nữa để thực hiện việc này trước khi tìm ra câu trả lời cho bạn.
vextorspace

Quên mất SocketTimeout. Ngoài ra, "default" có nghĩa là nó mặc định cho tất cả những HttpClientgì phương thức HttpClientBuilderfrom create () sẽ cung cấp build()? Hay chỉ những cái đi qua setDefaultRequestConfig(requestConfig)? Tôi có hiểu không?
ADTC

@ADTC Câu hỏi của bạn hơi khó hiểu :). Cấu hình yêu cầu mặc định sẽ được sử dụng cho tất cả các phiên bản HttpPost, HttpGet, ... sử dụng 'chỉ' HttpClient đó. Nếu bạn đã tạo một phiên bản HttpClient khác thì cấu hình yêu cầu này sẽ không được sử dụng với ứng dụng khách đó.
Thunder

35

HttpParams không được chấp nhận trong thư viện Apache HTTPClient mới. Sử dụng mã do Laz cung cấp dẫn đến cảnh báo không dùng nữa.

Tôi khuyên bạn nên sử dụng RequestConfig thay thế trên phiên bản HttpGet hoặc HttpPost của bạn:

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

"using the code above" << SO không phải là một diễn đàn và câu trả lời di chuyển lên / xuống do một số yếu tố, vì vậy chúng tôi không biết bạn đang đề cập đến mã nào. Bạn có thể nói điều gì đó như "sử dụng mã từ câu trả lời của xyz"?
ADTC

4
Btw, câu trả lời gọn gàng. Nhưng khi so sánh với câu trả lời của Thunder, có gì khác biệt giữa việc đặt nó RequestConfigthành mọi HttpPosttrái ngược với việc đặt nó làm mặc định thành HttpClient?
ADTC

2
Vâng, bạn nói đúng, đoạn mã trên đề cập đến "câu trả lời được chấp nhận" sẽ không thay đổi theo thời gian. Tôi sẽ cập nhật câu trả lời của mình bằng cách nào ..
pmartin8

10

Có vẻ như bạn đang sử dụng API HttpClient mà tôi không biết gì về nó, nhưng bạn có thể viết một cái gì đó tương tự như thế này bằng cách sử dụng Java lõi.

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
Điều này sẽ không ảnh hưởng đến thời gian chờ cho Apache HTTP Client.
laz

9
Không bao giờ tuyên bố nó đã làm;)
dbyrne

5
Khái niệm thời gian chờ của HttpURLConnection là không đủ. Nếu máy chủ bắt đầu phản hồi, nhưng sau đó bị treo, thì sẽ không bao giờ đạt đến thời gian chờ. Apache's HttpClient là một lựa chọn tốt hơn vì sự khác biệt này.
benvolioT

7

Tôi thấy rằng thiết lập thời gian ra khỏi các thiết lập trong HttpConnectionParamsHttpConnectionManagerkhông giải quyết trường hợp của chúng tôi. Chúng tôi bị giới hạn sử dụng org.apache.commons.httpclientphiên bản 3.0.1.

Tôi đã sử dụng một java.util.concurrent.ExecutorServiceđể theo dõi HttpClient.executeMethod()cuộc gọi.

Đây là một ví dụ nhỏ, khép kín

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

Phương pháp đã nói với mức tăng cao nhất của Laz không được chấp nhận từ phiên bản 4.3 trở đi. Do đó, sẽ tốt hơn nếu sử dụng Đối tượng Cấu hình Yêu cầu và sau đó xây dựng Máy khách 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 là người dùng để đặt số lượng kết nối mặc định tối đa và số lượng tối đa các kết luận trên mỗi tuyến đường. Tôi đã đặt nó là 306 và 108 tương ứng. Các giá trị mặc định sẽ không đủ cho hầu hết các trường hợp.

Để thiết lập Thời gian chờ: Tôi đã sử dụng đối tượng RequestConfig. Bạn cũng có thể đặt thuộc tính Thời gian chờ yêu cầu kết nối để đặt thời gian chờ kết nối từ trình quản lý Kết nối.


5

Điều này đã được đề cập trong một bình luận của benvoliot ở trên. Nhưng, tôi nghĩ nó xứng đáng là một bài đăng cấp cao nhất vì nó chắc chắn khiến tôi phải vò đầu bứt tai. Tôi đăng bài này trong trường hợp nó giúp đỡ người khác.

Tôi đã viết một ứng dụng khách thử nghiệm đơn giản và CoreConnectionPNames.CONNECTION_TIMEOUTthời gian chờ hoạt động hoàn hảo trong trường hợp đó. Yêu cầu sẽ bị hủy nếu máy chủ không phản hồi.

Tuy nhiên, bên trong mã máy chủ, tôi đang cố gắng kiểm tra, mã giống hệt nhau không bao giờ lỗi thời.

Thay đổi nó thành thời gian chờ hoạt động kết nối socket ( CoreConnectionPNames.SO_TIMEOUT) thay vì kết nối HTTP ( CoreConnectionPNames.CONNECTION_TIMEOUT) đã khắc phục sự cố cho tôi.

Ngoài ra, hãy đọc kỹ tài liệu Apache: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

Lưu ý một chút cho biết

Xin lưu ý rằng tham số này chỉ có thể được áp dụng cho các kết nối được liên kết với một địa chỉ cục bộ cụ thể.

Tôi hy vọng rằng điều đó sẽ cứu ai đó khác tất cả những gì tôi đã trải qua. Điều đó sẽ dạy tôi không đọc tài liệu kỹ lưỡng!


2

Op sau đó cho biết họ đang sử dụng Apache Commons HttpClient 3.0.1

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

1

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

Bạn cũng có thể xác định thời gian nghỉ cần thiết của mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.