คำขอไคลเอ็นต์ Java HTTP พร้อมการหมดเวลาที่กำหนด


92

ฉันต้องการทำการทดสอบ 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("");
 }
}

- แก้ไข: ชี้แจงว่าใช้ไลบรารีใด -

ฉันใช้ httpclient จาก apache นี่คือส่วน pom.xml ที่เกี่ยวข้อง

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

คุณใช้ไลบรารีใดสำหรับฟังก์ชัน HTTP ทั้งหมด
nojo

ขอบคุณสำหรับความคิดเห็น ฉันอัปเดตโพสต์ของฉันแล้ว
Maxim Veksler

คำตอบ:


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/…
Maxim Veksler

84
HttpClient ของ Apache มีการหมดเวลาแยกกันสองแบบ: การหมดเวลาสำหรับระยะเวลาในการรอเพื่อสร้างการเชื่อมต่อ TCP และการหมดเวลาแยกต่างหากสำหรับระยะเวลาในการรอข้อมูลไบต์ที่ตามมา HttpConnectionParams.setConnectionTimeout () เดิมคือ HttpConnectionParams.setSoTimeout () เป็นแบบหลัง
benvolioT

7
การหมดเวลาเริ่มต้นคืออะไร? มันเป็น 0 = ไม่มีที่สิ้นสุด?
Tobia

1
http.connection.timeout Integer การหมดเวลาจนกว่าจะสร้างการเชื่อมต่อ ค่าเป็นศูนย์หมายถึงไม่มีการใช้การหมดเวลา
maveroid

26
ถึงผู้อ่านในอนาคต: ควรสังเกตว่าชั้นเรียนที่อ้างถึงในที่นี้ได้เลิกใช้แล้ว (ณ วันที่ 2016-07-05) แม้ว่านี่อาจเป็นคำตอบที่ดีเมื่อโพสต์ในปี 2010 ดูคำตอบนี้: stackoverflow.com/a/ 19153314/192801สำหรับบางสิ่งที่เป็นปัจจุบันมากขึ้น
FrustratedWithFormsDesigner

126

หากคุณใช้ Http Client เวอร์ชัน 4.3 ขึ้นไปคุณควรใช้สิ่งนี้:

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

4
ขอบคุณ! ฉันใช้เวลาอย่างน้อย 20 นาทีในการพยายามหาวิธีกำจัดคำสั่งที่เลิกใช้แล้วเพื่อทำสิ่งนี้ก่อนที่จะพบคำตอบของคุณ
vextorspace

ลืมSocketTimeout. นอกจากนี้ "ค่าเริ่มต้น" หมายความว่าเป็นค่าเริ่มต้นสำหรับทุกสิ่งHttpClientที่HttpClientBuilderfrom create () จะให้ผ่านbuild()method หรือไม่? หรือแค่คนที่ผ่านsetDefaultRequestConfig(requestConfig)? ฉันมีเหตุผลไหม?
ADTC

@ADTC คำถามของคุณค่อนข้างสับสน :) การกำหนดค่าคำขอเริ่มต้นจะถูกใช้สำหรับอินสแตนซ์ HttpPost, HttpGet, ... ทั้งหมดโดยใช้ 'only' ที่ HttpClient หากคุณสร้างอินสแตนซ์ HttpClient อื่นการกำหนดค่าคำขอนี้จะไม่ถูกใช้กับไคลเอนต์นั้น
ธันเดอร์

35

HttpParams เลิกใช้งานแล้วในไลบรารี Apache HTTPClient ใหม่ การใช้รหัสที่ Laz ให้ไว้นำไปสู่คำเตือนการเลิกใช้งาน

ฉันแนะนำให้ใช้ RequestConfig แทนในอินสแตนซ์ HttpGet หรือ HttpPost ของคุณ:

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

"ใช้โค้ดด้านบน" << SO ไม่ใช่ฟอรัมและคำตอบจะเลื่อนขึ้น / ลงเนื่องจากปัจจัยหลายประการดังนั้นเราจึงไม่รู้ว่าคุณกำลังอ้างถึงรหัสใด คุณช่วยพูดว่า "ใช้รหัสจากคำตอบของ xyz" ได้ไหม
ADTC

4
Btw คำตอบที่เรียบร้อย แต่เมื่อเทียบกับคำตอบทันเดอร์, สิ่งที่แตกต่างระหว่างการตั้งค่าที่RequestConfigเข้ามาทุกHttpPostเมื่อเทียบกับการตั้งค่าเป็นค่าเริ่มต้นเข้ามา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

9
ไม่เคยอ้างเลย;)
dbyrne

5
แนวคิดเรื่องการหมดเวลาของ HttpURLConnection ไม่เพียงพอ หากเซิร์ฟเวอร์เริ่มตอบสนอง แต่แฮงค์จะไม่มีการหมดเวลา HttpClient ของ Apache เป็นตัวเลือกที่ดีกว่าเนื่องจากความแตกต่างนี้
benvolioT

7

ฉันพบว่าการตั้งค่าการหมดเวลาในHttpConnectionParamsและHttpConnectionManagerไม่สามารถแก้ปัญหาของเราได้ เรา จำกัด ให้ใช้org.apache.commons.httpclientเวอร์ชัน 3.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

วิธีการดังกล่าวที่มีค่าสูงสุดโดย 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 ตามลำดับ ค่าเริ่มต้นจะไม่เพียงพอสำหรับกรณีส่วนใหญ่

สำหรับการตั้งค่า Timeout: ฉันใช้วัตถุ RequestConfig คุณยังสามารถตั้งค่าคุณสมบัติ Connection Request Timeout สำหรับการตั้งค่าการหมดเวลาสำหรับการรอการเชื่อมต่อจาก Connection manager


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

สังเกตบิตที่ระบุว่า

โปรดทราบว่าพารามิเตอร์นี้สามารถใช้ได้กับการเชื่อมต่อที่ผูกไว้กับที่อยู่ในเครื่องเท่านั้น

ฉันหวังว่าจะช่วยคนอื่นได้ทั้งหมดที่ฉันเกาหัว ที่จะสอนให้ฉันอ่านเอกสารไม่ละเอียด!


2

Op ระบุในภายหลังว่าพวกเขาใช้ Apache Commons HttpClient 3.0.1

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.