Tanımlanmış zaman aşımına sahip Java HTTP İstemci İsteği


92

Bulutumdaki bir dizi sunucuya BIT (Yerleşik testler) yapmak istiyorum. Büyük zaman aşımı nedeniyle başarısız olma isteğine ihtiyacım var.

Bunu java ile nasıl yapmalıyım?

Aşağıdakine benzer bir şey denemek işe yaramıyor.

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

- DÜZENLEME: Hangi kitaplığın kullanıldığını netleştirin -

Apache'den httpclient kullanıyorum, işte ilgili pom.xml bölümü

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

Tüm HTTP işlevselliği için hangi kitaplığı kullanıyorsunuz?
nojo

Yorum için teşekkürler. Yazımı güncelledim.
Maxim Veksler

Yanıtlar:


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);


84
Apache'nin HttpClient iki ayrı zaman aşımına sahiptir: bir TCP bağlantısı kurmak için ne kadar bekleneceği için bir zaman aşımı ve sonraki bir veri baytı için ne kadar bekleneceği için ayrı bir zaman aşımı. HttpConnectionParams.setConnectionTimeout () birincisidir, HttpConnectionParams.setSoTimeout () ikincisidir.
benvolioT

7
Varsayılan zaman aşımı nedir? 0 = sonsuz mu?
Tobia

1
http.connection.timeout Tam Sayı Bir bağlantı kurulana kadar geçen zaman aşımı. Sıfır değeri, zaman aşımının kullanılmadığı anlamına gelir.
maveroid

26
Gelecekteki okuyucular için: Burada atıfta bulunulan sınıfların artık kullanımdan kaldırıldığına dikkat edilmelidir (2016-07-05 itibariyle), ancak bu muhtemelen 2010'da yayınlandığında iyi bir cevaptı. Şu yanıta bakın: stackoverflow.com/a/ 19153314/192801 biraz daha güncel bir şey için.
FrustratedWithFormsDesigner

125

Http Client sürüm 4.3 ve üstünü kullanıyorsanız, bunu kullanmalısınız:

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

4
Teşekkürler! Cevabınızı bulmadan önce bunu yapmak için en azından 20 dakika, kullanımdan kaldırılmış komutlardan nasıl kurtulacağımı bulmaya çalıştım.
vextorspace

Unuttum SocketTimeout. Ayrıca, "varsayılan" , create () öğesinin yöntem aracılığıyla vereceği her HttpClientşey için varsayılan olduğu anlamına mı gelir? Yoksa sadece geçenler mi? Mantıklı mıyım? HttpClientBuilderbuild()setDefaultRequestConfig(requestConfig)
ADTC

@ADTC Sorunuz biraz kafa karıştırıcı :). Varsayılan istek yapılandırması, 'yalnızca' bu HttpClient kullanan tüm HttpPost, HttpGet, ... örnekleri için kullanılacaktır. Başka bir HttpClient örneği oluşturduysanız, bu istek yapılandırması o istemciyle kullanılmayacaktır.
Thunder

35

HttpParams, yeni Apache HTTPClient kitaplığında kullanımdan kaldırılmıştır. Laz tarafından sağlanan kodun kullanılması, kullanımdan kaldırma uyarılarına yol açar.

Bunun yerine, HttpGet veya HttpPost örneğinizde RequestConfig kullanmanızı öneririm:

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

"yukarıdaki kodu kullanmak" << SO bir forum değildir ve yanıtlar çeşitli faktörlerden dolayı yukarı / aşağı hareket eder, bu nedenle hangi kodu kastettiğinizi bilmiyoruz. "Xyz'in cevabındaki kodu kullanarak" gibi bir şey söyleyebilir misiniz?
ADTC

4
Btw, temiz cevap. Ancak Thunder'ın cevabıyla karşılaştırıldığında, onu varsayılan olarak ayarlamakla RequestConfigher birini içine ayarlamak arasındaki fark nedir? HttpPostHttpClient
ADTC

2
Evet, haklısınız, yukarıdaki kod zamanla değişmemesi gereken "kabul edilen yanıtı" ifade ediyor. Cevabımı yine de güncelleyeceğim ..
pmartin8

10

Hakkında hiçbir şey bilmediğim HttpClient API kullanıyormuşsunuz gibi görünüyor, ancak çekirdek Java kullanarak buna benzer bir şeyler yazabilirsiniz.

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
Bu, Apache HTTP İstemcisi için zaman aşımını etkilemeyecektir.
laz

9
Asla yaptığını iddia etmedi;)
dbyrne

5
HttpURLConnection'ın zaman aşımı kavramı yetersiz. Sunucu yanıt vermeye başlar ancak daha sonra takılırsa, zaman aşımına asla ulaşılmaz. Apache'nin HttpClient'i bu farklılık nedeniyle daha iyi bir seçimdir.
benvolioT

7

Ben ayarlara dışarı zaman ayarı bulundu HttpConnectionParamsve HttpConnectionManagerdavamızı çözemedi. org.apache.commons.httpclient3.0.1 sürümünü kullanmakla sınırlıyız .

Aramayı java.util.concurrent.ExecutorServiceizlemek için bir kullandım HttpClient.executeMethod().

İşte küçük, bağımsız bir örnek

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 tarafından söz konusu en yüksek değerlere sahip yöntem 4.3 sürümünden itibaren kullanımdan kaldırılmıştır. Bu nedenle, İstek Yapılandırma Nesnesini kullanmak ve ardından HTTP İstemcisini oluşturmak daha iyi olacaktır.

    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, kullanıcının yol başına maksimum varsayılan bağlantı sayısını ve maksimum bağlantı sayısını ayarlamasını sağlar. Sırasıyla 306 ve 108 olarak ayarladım. Çoğu durumda varsayılan değerler yeterli olmayacaktır.

Zaman Aşımını ayarlamak için: RequestConfig nesnesini kullandım. Bağlantı yöneticisinden bağlantı beklemek için zaman aşımını ayarlamak için Bağlantı İsteği Zaman Aşımı özelliğini de ayarlayabilirsiniz.


5

Bundan yukarıda benvoliot tarafından yapılan bir yorumda bahsedilmişti. Ancak, üst düzey bir gönderiye değer olduğunu düşünüyorum çünkü kesinlikle kafamı kaşımamı sağladı. Başkasına yardım etmesi ihtimaline karşı bunu gönderiyorum.

Basit bir test istemcisi yazdım ve CoreConnectionPNames.CONNECTION_TIMEOUTbu durumda zaman aşımı mükemmel çalışıyor. Sunucu yanıt vermezse istek iptal edilir.

Sunucu kodunun içinde aslında test etmeye çalışıyordum, ancak aynı kod asla zaman aşımına uğramadı.

CoreConnectionPNames.SO_TIMEOUTHTTP bağlantısı ( CoreConnectionPNames.CONNECTION_TIMEOUT) yerine soket bağlantı etkinliğinde ( ) zaman aşımına uğraması sorunu benim için çözdü.

Ayrıca, Apache belgelerini dikkatlice okuyun: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

Yazan kısma dikkat edin

Lütfen bu parametrenin yalnızca belirli bir yerel adrese bağlı bağlantılara uygulanabileceğini unutmayın.

Umarım bu, yaşadığım tüm kafa kaşınmalarından başka birini kurtarır. Bu bana belgeleri iyice okumamamı öğretecek!


2

Op daha sonra Apache Commons HttpClient 3.0.1 kullandıklarını belirtti

 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

İstediğiniz zaman aşımını da tanımlayabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.