2012-03-29 27 views
20

Tôi đang phát triển một ứng dụng chạy dài sử dụng rất nhiều HttpClient từ apache.HttpClient bị kẹt mà không có bất kỳ ngoại lệ

Khi chạy thử nghiệm đầu tiên, ứng dụng hoạt động hoàn hảo cho đến khi nó bị kẹt. Nó không dừng lại, nó không ném bất kỳ ngoại lệ nào, nó chỉ ngồi đó chẳng làm gì cả.

Tôi đã chạy lần thứ hai ngay bây giờ và đã dừng thời gian và dừng lại sau khoảng. 24 giờ chạy contant. Ngoài ra tôi nhận thấy rằng kết nối internet của máy tính xách tay của tôi mà tôi đã chạy nó đã bị chấm dứt tại thời điểm chính xác ứng dụng đã bị mắc kẹt. Tôi phải khởi động lại bộ điều hợp WLAN để mạng hoạt động trở lại.

Ứng dụng này không hoạt động trở lại sau khi kết nối lại hoạt động trở lại. Và bây giờ, nó lại bị kẹt lại.

Có bộ điều khiển hết thời gian chờ nào mà tôi không biết trong HttpClient không? Tại sao ứng dụng của tôi không ngoại lệ khi kết nối bị ngắt?

Phần sử dụng ứng dụng khách như sau;

public HttpUtil(ConfigUtil config) { 
    this.config = config; 

    client = new DefaultHttpClient(); 
    client.getParams().setParameter(HttpProtocolParams.USER_AGENT, this.config.getProperty("httputil.userAgent")); 
} 

public String getContentAsString(String url) throws ParseException, ClientProtocolException, IOException { 
    return EntityUtils.toString(
      client.execute(
        new HttpGet(url)).getEntity()); 
} 

Ứng dụng nhiều lần gọi httputil.getContentAsString() trên URL cần.

+0

Có thể thực thể của bạn là một chuỗi rỗng. – kasavbere

+0

Sau đó, phương pháp của tôi vẫn sẽ trả lại chuỗi rỗng, phải không? Hoặc ném một ngoại lệ ít nhất? –

+1

Tôi có cùng một vấn đề. httpEntity.consumeContent() lưu tôi. http://stackoverflow.com/questions/9505358/android-httpclient-hangs-on-second-request-to-the-server-connection-timed-out – JamesC

Trả lời

8

Mã này hiện không còn được dùng nữa (hãy tải HttpParams, v.v.).Một cách tốt hơn là:

RequestConfig defaultRequestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BEST_MATCH).setExpectContinueEnabled(true).setStaleConnectionCheckEnabled(true).setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)).setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build(); 

HttpGet httpGet = new HttpGet(url);  
RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig).setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000).build(); 
httpGet.setConfig(requestConfig); 
6

Bạn chưa biết bạn đang sử dụng phiên bản HttpClient nào, nhưng giả sử rằng phiên bản 4 là, this blog article sẽ giải thích việc cần làm.

DefaultHttpClient httpClient = new DefaultHttpClient(); 
HttpParams params = httpClient.getParams(); 
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis); 
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis); 
+2

Tôi tin rằng điều này hiện không được chấp nhận –

3

Theo mặc định, HttpClient không hết thời gian chờ (gây ra nhiều sự cố hơn giúp ích). Những gì bạn mô tả có thể là một vấn đề phần cứng, nếu bộ điều hợp mạng của bạn chết, HttpClient sẽ treo.

Sau đây là các thiết lập để parametersHttpParams như một phần của các nhà xây dựng để DefaultHttpClient bao gồm

http.socket.timeout: xác định thời gian chờ ổ cắm (SO_TIMEOUT) trong mili giây, đó là thời gian chờ đợi cho cho dữ liệu hoặc, đặt khác nhau, khoảng thời gian không hoạt động tối đa giữa hai dữ liệu liên tiếp gói). Giá trị thời gian chờ bằng 0 được hiểu là thời gian chờ vô hạn . Tham số này mong đợi một giá trị của kiểu java.lang.Integer. Nếu thông số này không được đặt, hoạt động đọc sẽ không hết thời gian chờ (vô hạn thời gian chờ).

Điều đó sẽ đặt thời gian chờ trên kết nối, do đó, sau khi hết thời gian chờ, một ngoại lệ sẽ được ném.

3

Tôi có tất cả các thiết lập timeouts tốt nhưng tôi phát hiện ra rằng chúng tôi có trên url mà http chunking nhưng không gửi kết quả (hoạt động tốt trong chrome, nhưng trong http khách hàng nó treo mãi mãi ngay cả với các thiết lập thời gian chờ). May mắn là tôi sở hữu máy chủ và chỉ trả lại một số rác và nó không còn bị treo nữa. Điều này có vẻ giống như một lỗi rất độc đáo trong ứng dụng khách http đó không xử lý một số trường hợp chunking trống (mặc dù tôi có thể tắt) .... Tôi chỉ biết nó treo mọi lúc trên cùng một url với dữ liệu trống và url đó là http chunking csv tải xuống lại cho ứng dụng khách http của chúng tôi.

6

Kể từ phiên bản 4.4, cả hai câu trả lời của người dùng user2393012 và Stephen C đều không được chấp nhận. Tôi không chắc chắn nếu có một cách khác để làm điều đó, nhưng cách tôi làm điều đó là bằng cách sử dụng một mô hình xây dựng, HTTPClientBuilder.

Ví dụ:

HttpClients.custom().setConnectionTimeToLive(1, TimeUnit.MINUTES).build() 

Một rất giống nhau (nó thực sự có thể là vấn đề OP của) vấn đề với những gì OP cũng đề cập xảy ra nhưng là do Apache thiết lập các kết nối đồng thời mặc định chỉ có hai kết nối cho mỗi khách hàng. Giải pháp cho điều này là tăng các kết nối tối đa hoặc đóng chúng nếu bạn có thể.

Để tăng kết nối tối đa:

HttpClients.custom().setMaxConnPerRoute(100000).build() 

Để đóng kết nối, bạn có thể sử dụng một BasicHttpClientConnectionManager và gọi vào phương pháp chặt chẽ cho

3

tôi đã cùng một vấn đề, nó bị mắc kẹt vì tôi đã không đóng DefaultHttpClient.
Vì vậy, đây là sai:

try{ 
    DefaultHttpClient httpclient = new DefaultHttpClient(); 
    ... 
} catch (Exception e){ 
    e.PrintStackTrace(); 
} 

Và đây là đúng:

try (DefaultHttpClient httpclient = new DefaultHttpClient()){ 
    ... 
} catch (Exception e){ 
    e.PrintStackTrace(); 
} 

Hy vọng nó sẽ giúp một ai đó.

4

tôi đã đưa ra một câu trả lời tương tự trong một thread (HttpClient hangs on socketRead0 with successfully executed method)

Trong trường hợp của tôi, tôi đã thiết lập các ConnectionTimeout và socketTimeout theo yêu cầu, nhưng không phải trên các ổ cắm kết nối được sử dụng trong việc thiết lập kết nối SSL. Kết quả là, đôi khi tôi sẽ treo trong khi bắt tay SSL. Dưới đây là một số mã đặt tất cả 3 thời gian chờ bằng cách sử dụng v4.4 (cũng được thử nghiệm trong v4.5)

// Configure the socket timeout for the connection, incl. ssl tunneling 
connManager = new PoolingHttpClientConnectionManager(); 
connManager.setMaxTotal(200); 
connManager.setDefaultMaxPerRoute(100); 

SocketConfig sc = SocketConfig.custom() 
    .setSoTimeout(soTimeoutMs) 
    .build(); 

connManager.setDefaultSocketConfig(sc); 

HttpClient client = HttpClients.custom() 
      .setConnectionManager(connManager) 
      .setConnectionManagerShared(true) 
      .build(); 

// configure the timeouts (socket and connection) for the request 
RequestConfig.Builder config = = RequestConfig.copy(RequestConfig.DEFAULT); 
config.setConnectionRequestTimeout(connectionTimeoutMs); 
config.setSocketTimeout(socketTimeoutMs); 

HttpRequestBase req = new HttpGet(uri); 
req.setConfig(config.build()); 

client.execute(req); 
Các vấn đề liên quan