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

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

HttpConnectionParams.setConnectionTimeout(params, 10000); HttpConnectionParams.setSoTimeout(params, 10000); 

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

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

 public HashMap 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 jsonObj = (HashMap) GenericJSONUtil.fromJson(r); return jsonObj; } 

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

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

 Future future = null; future = pool.submit(new Callable() { 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); } 

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

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

 params.setConnectionTimeout(10000); params.setSoTimeout(10000); 

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

我猜很多人因为标题而来到这里,因为不推荐使用HttpConnectionParams API。

使用最新版本的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); 

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

配置示例文件是了解如何配置Apache HTTP Client的绝佳资源。