Permintaan Klien HTTP Java dengan batas waktu yang ditentukan


92

Saya ingin membuat BIT (Tes bawaan) ke sejumlah server di cloud saya. Saya perlu permintaan gagal pada waktu tunggu yang lama.

Bagaimana saya harus melakukan ini dengan java?

Mencoba sesuatu seperti di bawah ini sepertinya tidak berhasil.

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: Memperjelas perpustakaan apa yang sedang digunakan -

Saya menggunakan httpclient dari apache, berikut adalah bagian pom.xml yang relevan

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

Perpustakaan apa yang Anda gunakan untuk semua fungsionalitas HTTP?
nojo

Terima kasih atas komentarnya Saya telah memperbarui posting saya.
Maxim Veksler

Jawaban:


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
Apa fungsinya? Batas waktu dari apa yang disetel? Silakan lihat stackoverflow.com/questions/3000767/…
Maxim Veksler

84
HttpClient Apache memiliki dua waktu tunggu terpisah: waktu tunggu untuk berapa lama menunggu untuk membuat koneksi TCP, dan waktu tunggu terpisah untuk berapa lama menunggu byte data berikutnya. HttpConnectionParams.setConnectionTimeout () adalah yang pertama, HttpConnectionParams.setSoTimeout () adalah yang terakhir.
benvolioT

7
Apa waktu tunggu default? Apakah 0 = tak terbatas?
Tobia

1
http.connection.timeout Integer Timeout hingga koneksi dibuat. Nilai nol berarti batas waktu tidak digunakan.
maveroid

26
Untuk pembaca selanjutnya: Perlu dicatat bahwa kelas yang direferensikan di sini sekarang tidak digunakan lagi (per 2016-07-05), meskipun ini mungkin jawaban yang bagus ketika diposting pada tahun 2010. Lihat jawaban ini: stackoverflow.com/a/ 19153314/192801 untuk sesuatu yang sedikit lebih terkini.
FrustratedWithFormsDesigner

125

Jika Anda menggunakan Http Client versi 4.3 dan di atasnya, Anda harus menggunakan ini:

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

4
Terima kasih! Saya menghabiskan setidaknya 20 menit mencoba mencari cara untuk menghilangkan perintah yang tidak berlaku lagi untuk melakukan ini sebelum menemukan jawaban Anda.
vextorspace

Lupa SocketTimeout. Juga, apakah "default" berarti itu default untuk semua HttpClientyang HttpClientBuilderdari create () akan berikan melalui build()metode? Atau hanya yang lewat setDefaultRequestConfig(requestConfig)? Apakah saya masuk akal?
ADTC

@ADTC Pertanyaan Anda agak membingungkan :). Konfigurasi permintaan default akan digunakan untuk semua instance HttpPost, HttpGet, ... yang menggunakan 'hanya' HttpClient itu. Jika Anda membuat instance HttpClient lain maka konfigurasi permintaan ini tidak akan digunakan dengan klien itu.
Guntur

35

HttpParams tidak digunakan lagi di perpustakaan Apache HTTPClient baru. Menggunakan kode yang disediakan oleh Laz mengarah ke peringatan deprecation.

Saya menyarankan untuk menggunakan RequestConfig sebagai gantinya pada HttpGet atau contoh HttpPost Anda:

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

"menggunakan kode di atas" << SO bukan forum dan jawaban naik / turun karena beberapa faktor, jadi kami tidak tahu kode mana yang Anda maksud. Bisakah Anda mengatakan sesuatu seperti "menggunakan kode dari jawaban xyz"?
ADTC

4
Btw, jawaban yang rapi. Tetapi jika dibandingkan dengan jawaban Thunder, apa perbedaan antara menyetel RequestConfigke setiap HttpPostdan bukan menyetelnya sebagai default ke HttpClient?
ADTC

2
Ya, Anda benar, kode di atas mengacu pada "jawaban yang diterima" yang seharusnya tidak berubah seiring waktu. Saya akan memperbarui jawaban saya juga ..
pmartin8

10

Sepertinya Anda menggunakan HttpClient API, yang saya tidak tahu apa-apa, tetapi Anda bisa menulis sesuatu yang mirip dengan ini menggunakan inti 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
Ini tidak akan mempengaruhi waktu tunggu untuk Apache HTTP Client.
laz

9
Tidak pernah mengklaim itu;)
dbyrne

5
Gagasan HttpURLConnection tentang waktu tunggu tidak cukup. Jika server mulai merespons, tetapi kemudian hang, batas waktu tidak pernah tercapai. HttpClient Apache adalah pilihan yang lebih baik karena perbedaan ini.
benvolioT

7

Saya menemukan bahwa mengatur pengaturan waktu keluar HttpConnectionParamsdan HttpConnectionManagertidak menyelesaikan kasus kami. Kami terbatas untuk menggunakan org.apache.commons.httpclientversi 3.0.1.

Saya akhirnya menggunakan java.util.concurrent.ExecutorServiceuntuk memantau HttpClient.executeMethod()panggilan.

Berikut adalah contoh kecil yang berdiri sendiri

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

Metode tersebut dengan up tertinggi oleh Laz tidak digunakan lagi mulai versi 4.3 dan seterusnya. Oleh karena itu, akan lebih baik untuk menggunakan Objek Konfigurasi Permintaan dan kemudian membangun Klien 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 adalah pengguna yang mengatur jumlah koneksi default maksimum dan jumlah koneksi maksimum per rute. Saya telah menetapkannya masing-masing sebagai 306 dan 108. Nilai default tidak akan cukup untuk sebagian besar kasus.

Untuk mengatur Timeout: Saya telah menggunakan objek RequestConfig. Anda juga dapat mengatur properti Connection Request Timeout untuk mengatur waktu tunggu untuk menunggu koneksi dari Connection manager.


5

Ini sudah disebutkan dalam komentar oleh benvoliot atas. Tapi, saya pikir itu layak untuk posting tingkat atas karena itu pasti membuat saya menggaruk-garuk kepala. Saya memposting ini kalau-kalau itu membantu orang lain.

Saya menulis klien uji sederhana dan CoreConnectionPNames.CONNECTION_TIMEOUTbatas waktu berfungsi dengan sempurna dalam kasus itu. Permintaan dibatalkan jika server tidak merespons.

Di dalam kode server yang sebenarnya saya coba uji, kode identik tidak pernah habis.

Mengubahnya ke waktu habis pada aktivitas koneksi soket ( CoreConnectionPNames.SO_TIMEOUT) daripada koneksi HTTP ( CoreConnectionPNames.CONNECTION_TIMEOUT) memperbaiki masalah bagi saya.

Juga, baca dokumen Apache dengan seksama: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

Perhatikan bagian yang mengatakan

Harap dicatat parameter ini hanya dapat diterapkan ke koneksi yang terikat ke alamat lokal tertentu.

Saya berharap itu menyelamatkan orang lain dari semua garukan kepala yang saya alami. Itu akan mengajari saya untuk tidak membaca dokumentasi secara menyeluruh!


2

Op kemudian menyatakan bahwa mereka menggunakan 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

Anda juga dapat menentukan waktu istirahat yang Anda inginkan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.