我需要为我们对服务(而不是Web服务)发出的Http请求设置时间。我们正在使用Apache HTTP Client。我添加了这两行代码来设置请求和响应服务的超时时间。
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
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;
}
答案 0 :(得分:62)
我猜很多人因为标题而来到这里,因为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客户端时设置此项,但您还需要使用自定义套接字配置构建自定义连接管理器。
configuration example file是了解如何配置Apache HTTP Client的绝佳资源。
答案 1 :(得分:35)
您将看到的例外情况为ConnectTimeoutException
和SocketTimeoutException
。您使用的实际超时值应该是您的应用程序愿意等待的最长时间。关于读取超时的一个重要注意事项是它对应于套接字读取的超时。因此,不是完整响应到达的时间,而是单个套接字读取的时间。因此,如果有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);
}
在上面的代码中做出的一些假设是:1)这是一个带有url参数的函数,2)它在一个带有name变量的类中,3)log是一个log4j实例,而4)pool是一个线程池执行器。请注意,即使您使用线程超时,您还应该在HttpClient上指定连接和套接字超时,以便慢速请求不会占用线程池中的资源。另请注意,我使用线程池,因为通常我在Web服务中使用它,因此线程池在一堆tomcat线程中共享。您的环境可能不同,您可能更愿意为每次调用生成一个新线程。
另外,我通常会看到通过参数的成员函数设置超时,如下所示:
params.setConnectionTimeout(10000);
params.setSoTimeout(10000);
但也许你的语法也可以(不确定)。