我正在开发一个长期运行的应用程序,该应用程序大量使用来自apache的HttpClient。
在我的第一次测试运行中,该应用程序运行良好,直到它被卡住。它没有停止,它没有抛出任何异常,只是在那里无所事事。
我刚刚做了第二次跑步并停止了时间,并在大约停止后停止了。 24小时不间断运行。此外,我注意到我运行它的笔记本电脑的互联网连接在应用程序卡住的确切时刻终止。我不得不重新启动我的WLAN适配器,以便再次运行网络。
虽然应用程序在连接再次启动后没有返回工作状态。现在,它又被卡住了。
HttpClient中是否有我不知道的超时控制器?为什么我的应用程序在连接断开时不会抛出异常?
使用客户端的部分如下所示;
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());
}
应用程序反复调用httputil.getContentAsString()
所需的网址。
答案 0 :(得分:12)
现在不推荐使用此代码(获取HttpParams等)。更好的方法是:
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);
答案 1 :(得分:7)
自版本4.4起,用户user2393012和Stephen C的答案均已弃用。我不确定是否有其他方法可以做到这一点,但我这样做的方法是使用构建器范例HTTPClientBuilder。
实施例
HttpClients.custom().setConnectionTimeToLive(1, TimeUnit.MINUTES).build()
OP提到的问题非常类似(实际上可能是OP问题),但是由于Apache将默认并发连接设置为每个客户端只有两个连接。对此的解决方案是增加最大连接数或者如果可以的话关闭它们。
增加最大连接数:
HttpClients.custom().setMaxConnPerRoute(100000).build()
要关闭连接,可以使用BasicHttpClientConnectionManager并调用close方法
答案 2 :(得分:6)
您还没有说过您使用的是哪个版本的HttpClient,但假设它是版本4,this blog article解释了该怎么做。
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis);
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis);
答案 3 :(得分:5)
我在另一个帖子(HttpClient hangs on socketRead0 with successfully executed method)
中给出了类似的答案就我而言,我在请求中设置了connectionTimeout和socketTimeout,但是在建立SSL连接期间使用的连接套接字上没有设置。因此,我有时会在SSL握手期间挂起。下面是一些使用v4.4设置所有3个超时的代码(也在v4.5中测试)
Add this in custom class of collection view :
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if (self.focused) {
collectionView.image.adjustsImageWhenAncestorFocused = true
}
else{
collectionView.image.adjustsImageWhenAncestorFocused = false
}
}
答案 4 :(得分:4)
我已经将所有超时设置得很好但是我发现我们在url上进行了http分块但没有发送结果(在chrome中运行正常,但在http客户端中它甚至会在超时设置下永久挂起)。幸运的是,我拥有服务器,只是返回一些垃圾,它不再挂起。这似乎是一个非常独特的错误,http客户端不能很好地处理某种空的分块情况(虽然我可能会离开)....我只是知道它每次挂在同一个网址上的空数据和该网址是http chunking csv下载回我们的http客户端。
答案 5 :(得分:3)
默认情况下,HttpClient不会超时(这会导致更多问题)。您所描述的可能是硬件问题,如果您的网络适配器死亡,HttpClient将挂起。
以下parameters设置为HttpParams,作为DefaultHttpClient的构造函数的一部分,包括
http.socket.timeout :定义套接字超时(SO_TIMEOUT) 毫秒,这是等待数据的超时或放置 不同地,两个连续数据之间的最大周期不活动 包)。超时值为零被解释为无限 超时。此参数需要java.lang.Integer类型的值。如果 此参数未设置,读取操作不会超时(无限 超时)。
这将在连接上设置超时,因此在设置超时后将抛出异常。
答案 6 :(得分:3)
我有同样的问题,因为我没有关闭DefaultHttpClient而卡住了 所以这是错误的:
try{
DefaultHttpClient httpclient = new DefaultHttpClient();
...
} catch (Exception e){
e.PrintStackTrace();
}
这是对的:
try (DefaultHttpClient httpclient = new DefaultHttpClient()){
...
} catch (Exception e){
e.PrintStackTrace();
}
希望它有所帮助。