在Apache HttpClient API中,setConnectionTimeout、setSoTimeout和http.connection-manager.timeout有什么区别?

44

这三个(标记为注释)之间的区别是什么:

MultiThreadedHttpConnectionManager connManag =  new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams managParams = connManag.getParams();

managParams.setConnectionTimeout(connectiontimeout); // 1
managParams.setSoTimeout(sotimeout); //2

HttpMethodBase baseMethod = null;

try {
  HttpClient client = new HttpClient(connManag);
  client.getParams().setParameter("http.connection-manager.timeout", poolTimeout); //3

  baseMethod = new GetMethod(…);
  int statusCode = client.executeMethod(…);

  …
}
catch (ConnectTimeoutException cte ){
  //Took too long to connect to remote host
}
catch (SocketTimeoutException ste){
  //Remote host didn’t respond in time
}
catch (Exception se){
  //Some other error occurred
}
finally {
  if (baseMethod != null)
    baseMethod.releaseConnection();
}

1. setConnectionTimeout - 用于确定连接建立的超时时间。

2. setSoTimeout - 用于确定不活动期或两个连续数据包之间的时间差。

那么下面这个是做什么的:

3. "http.connection-manager.timeout"


文档上说了什么?它们是沉默的吗? - Marko Topolnik
2
@Marko 我不理解,所以才在这里发帖。 - Prateek
1
你至少应该提到你已经阅读了它们,并指出特定的方面令你困扰。这样,你的问题看起来不像是在要求我们替你阅读文档。 - Marko Topolnik
4个回答

68

HTTP最底层就是TCP socket。因此当您请求URL并获得响应时,在更低的层面上,客户端Socket被创建,该套接字建立到远程Server Socket的连接,发送一些数据并接收响应。

  • setConnectionTimeout:客户端尝试连接服务器。这表示在连接建立或服务器响应连接请求之前经过的时间。

  • setSoTimeout:建立连接后,客户端套接字在发送请求后等待响应。这是客户端向服务器发送请求后服务器响应之前经过的时间。请注意,这与服务器发送给客户端的HTTP错误408不同。换句话说,它是在连接建立后,在两个连续数据包到达客户端之间的最大空闲时间

  • http.connection-manager.timeoutMultiThreadedHttpConnectionManager使用一组HTTP连接池。为其设置了每个主机的最大和最小值。如果特定主机的所有连接已达到最大值,则针对该主机的新连接请求必须等待,直到任何一个现有连接变为空闲状态。此参数表示在发出连接请求并在HttpConnectionManager返回连接之前经过的时间。


这意味着我们必须关闭套接字或连接中的任一一个。 - Prateek
当你处理像HttpClient这样的API时,你不必直接处理套接字。即使在HttpClient的情况下,也有一种方法(httpclient.getConnectionManager().shutdown();)来关闭执行关闭连接工作的HttpClient - Santosh
但是我不需要关闭连接,因为我正在使用连接池。我应该怎么做才能停止等待请求的响应? - Prateek
但这就是你所要求的(这意味着我们必须关闭套接字或连接之一)。为了不等待响应,您已经使用了HttpConnectionManagerParams.setSoTimeout() - Santosh

38

这个顺序图可能会有所帮助。

apache http api


7
优秀的图表 ;) - Bogdan
@Maria 是哪个顺序图?我在浏览器上看不到。有链接吗? - Gaurav

7
详细的解释可以在Apache HTTP客户端网站的连接管理文档中找到。
CoreConnectionPNames.SO_TIMEOUT='http.socket.timeout': 定义套接字超时时间(SO_TIMEOUT),单位为毫秒,即等待数据的超时时间或者说是两个连续数据包之间的最大不活动期。超时值为零被解释为无限超时。此参数需要一个java.lang.Integer类型的值。如果未设置此参数,则读取操作将不会超时(无限超时)。
CoreConnectionPNames.CONNECTION_TIMEOUT='http.connection.timeout': 确定连接建立的超时时间,单位为毫秒。超时值为零被解释为无限超时。此参数需要一个java.lang.Integer类型的值。如果未设置此参数,则连接操作将不会超时(无限超时)。
连接管理器超时时间(http.connection-manager.timeout)- 等待从连接管理器/池获取连接的时间。
仅供参考。
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);

有另一种方法可以做到

HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, timeout * 1000);
HttpConnectionParams.setSoTimeout(httpParams, timeout * 1000);

2
你如何设置http.connection-manager.timeout?我找不到正确的方法来做这件事。 - devo
2
回复自己的评论,你应该这样做。setConnectionRequestTimeout就是它:RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout) .setSocketTimeout(socketTimeout).build(); - devo
...并将配置设置为 HttpGet 或其他方法。httpGet.setConfig(requestConfig); - WesternGun
仅作为附注:根据Javadoc,在4.5.7中,所有三个参数都具有默认值“-1”,这意味着“未定义(系统默认)”。 - WesternGun

2
简单来说:
连接超时:当应用程序尝试与服务器建立连接但无法建立连接(地址错误或服务器宕机等)时,应用程序等待的时间限制。
套接字超时:当应用程序已连接到服务器但仍在等待响应时,等待的时间限制(例如,可能由于挂起的服务器导致延迟)。
连接管理器超时:当请求在队列中等待其中一个池中的请求被释放时,请求等待的时间限制。换句话说,在HTTP中,我们有一个具有最大大小的连接池。当应用程序负载较重时,池可能已满,并且任何新请求都必须等待池中的另一个请求完成。

值得补充的是,在上面的第3点中,线程将会无限期地等待连接被释放回池中。这是一个非常糟糕的模式,不适用于可靠性和响应性很重要的应用程序。 - asgs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接