有关HTTP通信的超时设置
- (1)问题描述
- (2)HttpClient的超时设置
- (3)Qt C++中的HTTP超时设置
- (4)结语
(1)问题描述
企业内部用 OpenStack Swift 搭建了一个私有云存储系统,按理说只要存储空间足够,I/O吞吐应该是杠杠的。
(论证阶段进行验证用的是Java的 HttpClient 组件,一直很流畅)
结果应用系统使用的是Qt C++(5.9)开发的客户端,分片上传大文件时总是出现不稳定(而且才2个线程)。
经过对比测试,初步定位在HTTP通信的超时设置上。
(2)HttpClient的超时设置
相比之下,Java语言的HTTP通信要比Qt C++的要完备、成熟得多。以下是Java客户端的代码:
……
//构建GET方法
HttpGet get = new HttpGet(url);
//0321设置超时
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(toc.getConn() )
.setConnectionRequestTimeout(toc.getConnReq() )
.setSocketTimeout(toc.getSocket() ).build();
get.setConfig(config);
……
//客户端执行
HttpResponse resp = HttpClients.createDefault().execute(get);
//返回状态
int statusCode = resp.getStatusLine().getStatusCode();
……
上述是使用 Apache HttpClient 组件,使用 GET 方法请求指定URL的代码片段。
代码片段中设置了请求超时(RequestConfig 即是),如果不设置超时,则无需定义config变量以及调用setConfig方法即可。
代码中,请求超时包括三个部分:
- 连接超时(ConnectTimeout) — 请求1个连接的超时(单位:ms)
- 连接请求超时(ConnectionRequestTimeout)— 建立1个连接的超时(单位:ms)
- 套接字超时(SocketTimeout) — 等待数据(I/O)的超时(单位:ms)
以上3个超时的定义,也是按照的通信时序。 对于这3个超时的设定,是统一的:
- 正值即设定值;
- 0值表示无限超时;
- -1(默认值)表示系统默认值。
以下是 Apache HttpClient 组件(4.5.12)默认配置相关代码:
Builder() {
super();
this.staleConnectionCheckEnabled = false;
this.redirectsEnabled = true;
this.maxRedirects = 50;
this.relativeRedirectsAllowed = true;
this.authenticationEnabled = true;
this.connectionRequestTimeout = -1;
this.connectTimeout = -1;
this.socketTimeout = -1;
this.contentCompressionEnabled = true;
this.normalizeUri = true;
}
这里的Builder即是RequestConfig.Builder。
(3)Qt C++中的HTTP超时设置
相比之下,Qt C++实现HTTP超时设置就有点五花八门了:不同版本的实现方式不一样。
依据开发文档的检索,Qt从5.15才开始定义了QNetworkRequest::DefaultTransferTimeoutConstant(其值为30000ms)。
在我们5.9的版本中,使用的是计时器(QTimer)来实现的超时管理:即发起请求后开始计时,直到通信完成,或者超时才停止/销毁。所以该超时设置应该是按照上述的套接字超时来设置,一般地,应该设置稍大一些,例如5.15中的30s。
当然,如果没有特别要求,无需额外设置,即使用系统默认值即可。
(4)结语
- 对于不同系统,例如:Java vs Qt C++,对于通信超时的定义可能有所不同,需要区别对待。
- 除非您对超时设置比较熟悉,否则不建议您额外设置,使用系统默认即可。