使用Apache HttpClient如何在请求和响应上设置TIMEOUT

pus*_*hya 37 java apache-commons-httpclient

我需要为我们对服务(而不是Web服务)发出的Http请求设置时间.我们正在使用Apache HTTP Client.我添加了这两行代码来设置请​​求和响应服务的超时时间.

HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
Run Code Online (Sandbox Code Playgroud)

1)目前我已将10秒设置为超时,因为我几乎立即看到来自服务的响应.我应该增加还是减少时间?

2)响应时间超过10秒会发生什么?它会抛出异常,会有什么异常吗?在下面的代码中是否还需要添加任何其他内容来设置超时.

public HashMap<String, Object> getJSONData(String url) throw Exception{
    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpParams params = httpClient.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 10000);
    HttpConnectionParams.setSoTimeout(params, 10000);
    HttpHost proxy = new HttpHost(getProxy(), getProxyPort());
    ConnRouteParams.setDefaultProxy(params, proxy);
    URI uri;
    InputStream data = null;
    try {
        uri = new URI(url);
        HttpGet method = new HttpGet(uri);
        HttpResponse response = httpClient.execute(method);
        data = response.getEntity().getContent();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    Reader r = new InputStreamReader(data);
    HashMap<String, Object> jsonObj = (HashMap<String, Object>) GenericJSONUtil.fromJson(r);
    return jsonObj;
}
Run Code Online (Sandbox Code Playgroud)

sim*_*mao 66

我猜很多人因为标题来到这里,因为HttpConnectionParamsAPI已被弃用.

使用最新版本的Apache HTTP Client,您可以使用请求参数设置这些超时:

HttpPost request = new HttpPost(url);

RequestConfig requestConfig = RequestConfig.custom()
  .setSocketTimeout(TIMEOUT_MILLIS)
  .setConnectTimeout(TIMEOUT_MILLIS)
  .setConnectionRequestTimeout(TIMEOUT_MILLIS)
  .build();

request.setConfig(requestConfig);
Run Code Online (Sandbox Code Playgroud)

或者,您也可以在使用HTTP客户端的构建器API创建HTTP客户端时设置此项,但您还需要使用自定义套接字配置构建自定义连接管理器.

配置示例文件是要找出如何配置Apache HTTP客户端的优秀资源.

  • 上面的链接已损坏。我认为这是正确的(即使非权威)链接https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/test/java/org/apache/hc/client5/http/示例/ClientConfiguration.java (2认同)

Kev*_*vin 36

您将看到的例外情况将是ConnectTimeoutExceptionSocketTimeoutException.您使用的实际超时值应该是您的应用程序愿意等待的最长时间.关于读取超时的一个重要注意事项是它对应于套接字读取的超时.因此,不是完整响应到达的时间,而是单个套接字读取的时间.因此,如果有4个套接字读取,每个读取9秒,则总读取时间为9*4 = 36秒.

如果要指定响应到达的总时间(包括连接和总读取时间),可以将调用包装在一个线程中并使用线程超时.例如,我通常做这样的事情:

Future<T> future = null;
future = pool.submit(new Callable<T>() {
    public T call() {
        return executeImpl(url);
    }   
}); 

try {
    return future.get(10, TimeUnit.SECONDS);
}   
catch (InterruptedException e) {
    log.warn("task interrupted", name);
}   
catch (ExecutionException e) {
    log.error(name + " execution exception", e); 
}   
catch (TimeoutException e) {
    log.debug("future timed out", name);
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码做一些假设:1)这是一个网址参数的函数,2)它是在一个名称变量类,3)日志是一个log4j的实例,以及4)池是一些线程池执行.请注意,即使您使用线程超时,您还应该在HttpClient上指定连接和套接字超时,以便慢速请求不会占用线程池中的资源.另请注意,我使用线程池,因为通常我在Web服务中使用它,因此线程池在一堆tomcat线程中共享.您的环境可能不同,您可能更愿意为每个调用生成一个新线程.

另外,我通常会看到通过params的成员函数设置的超时,如下所示:

params.setConnectionTimeout(10000);
params.setSoTimeout(10000);
Run Code Online (Sandbox Code Playgroud)

但也许你的语法也可以(不确定).

  • 你的意思是:`return future.get(10,TimeUnit.SECONDS)`?或者你真的想等一万秒? (6认同)
  • 不,响应可以是块状的.如果你看一下任何低级套接字代码,你会看到`read()`在while循环中发生,而`read()`的返回值是读取的字节数.不要求整个响应都在单个套接字读取中.我会更新我的答案以包含更多细节. (2认同)