HttpClient Timeout

1. Ikhtisar

Tutorial ini akan menunjukkan cara mengkonfigurasi waktu tunggu dengan Apache HttpClient 4 .

Jika Anda ingin menggali lebih dalam dan mempelajari hal-hal keren lainnya yang dapat Anda lakukan dengan HttpClient - lanjutkan ke tutorial HttpClient utama .

2. Mengonfigurasi Timeout Sebelum HttpClient 4.3

2.1. Parameter String Mentah

Sebelum versi 4.3 keluar, HttpClient hadir dengan banyak parameter konfigurasi, dan semua ini dapat diatur dengan cara umum seperti peta.

Ada 3 parameter waktu tunggu untuk dikonfigurasi :

DefaultHttpClient httpClient = new DefaultHttpClient(); int timeout = 5; // seconds HttpParams httpParams = httpClient.getParams(); httpParams.setParameter( CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000); httpParams.setParameter( CoreConnectionPNames.SO_TIMEOUT, timeout * 1000); httpParams.setParameter( ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

2.2. API

Yang lebih penting dari parameter ini - yaitu dua yang pertama - juga dapat disetel melalui API yang lebih aman bagi tipe:

DefaultHttpClient httpClient = new DefaultHttpClient(); int timeout = 5; // seconds HttpParams httpParams = httpClient.getParams(); HttpConnectionParams.setConnectionTimeout( httpParams, timeout * 1000); // http.connection.timeout HttpConnectionParams.setSoTimeout( httpParams, timeout * 1000); // http.socket.timeout

Parameter ketiga tidak memiliki penyetel khusus di HttpConnectionParams , dan itu masih perlu disetel secara manual melalui metode setParameter .

3. Konfigurasi Timeout Menggunakan 4.3 Baru. Pembangun

API pembuat yang fasih yang diperkenalkan di 4.3 menyediakan cara yang tepat untuk menyetel waktu tunggu di level tinggi :

int timeout = 5; RequestConfig config = RequestConfig.custom() .setConnectTimeout(timeout * 1000) .setConnectionRequestTimeout(timeout * 1000) .setSocketTimeout(timeout * 1000).build(); CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();

Itu adalah cara yang disarankan untuk mengonfigurasi ketiga batas waktu dengan cara yang aman dan dapat dibaca.

4. Properti Timeout Dijelaskan

Sekarang, mari kita jelaskan apa arti dari berbagai jenis batas waktu ini:

  • yang Connection Timeout ( http.connection.timeout ) - waktu untuk membangun koneksi dengan host remote
  • yang Socket Timeout ( http.socket.timeout ) - waktu menunggu data - setelah membuat sambungan; waktu maksimum tidak aktif antara dua paket data
  • yang Connection Manager Timeout ( http.connection-manager.timeout ) - waktu untuk menunggu koneksi dari koneksi manager / kolam

Dua parameter pertama - koneksi dan batas waktu soket - adalah yang paling penting. Namun, menyetel waktu tunggu untuk mendapatkan koneksi sangatlah penting dalam skenario beban tinggi, itulah sebabnya parameter ketiga tidak boleh diabaikan.

5. Menggunakan HttpClient

Setelah mengonfigurasinya, sekarang kita dapat menggunakan klien untuk melakukan permintaan HTTP:

HttpGet getMethod = new HttpGet("//host:8080/path"); HttpResponse response = httpClient.execute(getMethod); System.out.println( "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Dengan klien yang ditentukan sebelumnya, koneksi ke host akan habis dalam 5 detik. Selain itu, jika koneksi dibuat tetapi tidak ada data yang diterima, batas waktu juga akan menjadi 5 detik tambahan .

Perhatikan bahwa waktu tunggu sambungan akan mengakibatkan org.apache.http.conn.ConnectTimeoutException dilempar, sedangkan waktu tunggu soket akan menghasilkan java.net.SocketTimeoutException .

6. Batas Waktu Sulit

Meskipun mengatur waktu tunggu saat membuat koneksi HTTP dan tidak menerima data sangat berguna, terkadang kami perlu menetapkan waktu tunggu yang sulit untuk seluruh permintaan .

Misalnya, unduhan file yang berpotensi besar masuk ke dalam kategori ini. Dalam hal ini, koneksi mungkin berhasil dibuat, data mungkin terus masuk, tetapi kami masih perlu memastikan bahwa operasi tidak melewati ambang waktu tertentu.

HttpClient tidak memiliki konfigurasi yang memungkinkan kita menyetel batas waktu keseluruhan untuk sebuah permintaan; itu, bagaimanapun, menyediakan fungsionalitas pembatalan untuk permintaan , sehingga kami dapat memanfaatkan mekanisme tersebut untuk mengimplementasikan mekanisme batas waktu yang sederhana:

HttpGet getMethod = new HttpGet( "//localhost:8080/httpclient-simple/api/bars/1"); int hardTimeout = 5; // seconds TimerTask task = new TimerTask() { @Override public void run() { if (getMethod != null) { getMethod.abort(); } } }; new Timer(true).schedule(task, hardTimeout * 1000); HttpResponse response = httpClient.execute(getMethod); System.out.println( "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Kami menggunakan java.util.Timer dan java.util.TimerTask untuk menyiapkan tugas tertunda sederhana yang membatalkan permintaan HTTP GET setelah waktu tunggu 5 detik.

7. Timeout dan DNS Round Robin - Sesuatu yang Harus Diwaspadai

Sangat umum bahwa beberapa domain yang lebih besar akan menggunakan konfigurasi DNS round robin - pada dasarnya memiliki domain yang sama yang dipetakan ke beberapa alamat IP . Ini memperkenalkan tantangan baru untuk waktu tunggu terhadap domain semacam itu, hanya karena cara HttpClient akan mencoba menyambung ke domain itu yang waktu itu habis:

  • HttpClient mendapatkan daftar rute IP ke domain itu
  • itu mencoba yang pertama - waktu itu habis (dengan batas waktu yang kita konfigurasikan)
  • itu mencoba yang kedua - yang juga waktu habis
  • dan seterusnya …

Jadi, seperti yang Anda lihat - keseluruhan operasi tidak akan berhenti seperti yang kami harapkan . Sebaliknya - ini akan waktu habis ketika semua rute yang memungkinkan telah habis waktunya. Terlebih lagi - ini akan terjadi sepenuhnya secara transparan untuk klien (kecuali Anda memiliki log yang dikonfigurasi di tingkat DEBUG).

Berikut contoh sederhana Anda dapat menjalankan dan mereplikasi masalah ini:

int timeout = 3; RequestConfig config = RequestConfig.custom(). setConnectTimeout(timeout * 1000). setConnectionRequestTimeout(timeout * 1000). setSocketTimeout(timeout * 1000).build(); CloseableHttpClient client = HttpClientBuilder.create() .setDefaultRequestConfig(config).build(); HttpGet request = new HttpGet("//www.google.com:81"); response = client.execute(request);

Anda akan melihat logika percobaan ulang dengan tingkat log DEBUG:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81 DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81 DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81 DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address //...

8. Kesimpulan

Tutorial ini membahas cara mengonfigurasi berbagai jenis waktu tunggu yang tersedia untuk HttpClient . Ini juga mengilustrasikan mekanisme sederhana untuk waktu tunggu habis dari koneksi HTTP yang sedang berlangsung.

Penerapan contoh-contoh ini dapat ditemukan di proyek GitHub.