文章目录
为什么要设置HTTP timeout?
- 与用户操作相关的接口,如果不设置超时时间,将会出现长时间的无响应,严重影响用户体验。
- 负载很高的系统,因为大量调用耗时长的接口,导致性能急剧下降,从而影响其他正常的业务。
- 某些情况下,HTTP请求可能永远都得不到响应,那么这部分系统资源就一直被占用,直到系统奔溃。
HttpClient超时配置参数的问题
客户端httpclient的关于连接的配置相关的参数和意义如下:
SocketTimeout 是 5s
- 连接建立后,数据传输过程中
数据包之间
间隔的最大时间
ConnectTimeout 是 3s
- 连接建立时间,即
三次握手完成时间
ConnectionRequestTimeout 是默认值
- httpclient使用连接池来管理连接,这个时间就是从
连接池获取连接
的超时时间
响应超时时间异常
在网络不好的时候, 请求超时时间并没有按照我们的设置报超时异常,明明响应超时时间设置了5s,很多请求超时时间都达到了10几秒甚至有的二十几秒,大大超过了我们的预期时间
虽然报文(“abc”)
返回总共用了6秒
,如果SocketTimeout
设置成5秒
,实际程序执行的时候是不会抛出java.net.SocketTimeoutException: Read timed out
异常的。
- 因为SocketTimeout的值表示的是“a”、”b”、”c”这三个报文,
每两个相邻的报文的间隔时间没有能超过SocketTimeout
。
wireshark抓包结果
可能会想实际的报文是不是每经过3秒返回一个报文呢,下面是通过wireshark抓包的结果
1:返回字母a的TCP报文
2:返回字母b的TCP报文
3:返回字母c的TCP报文
根据time列
可以看出TCP数据传输报文之间的间隔就是3秒
。,每个报文后还有一个ACK
的报文,就是tcp客户端的回执报文
- 因此可以得出结论: SocketTimeout时间是我们
两次读取数据之间的最长阻塞时间
,如果我在网络抖动的情况下,我每次2秒之内返回一部分数据,这样我就一直不会超时了
Apache的Httpclient不同版本设置超时时间的方法是不一样的,要特别注意
:
3.x.超时设置实例
/* 从连接池中取连接的超时时间(单位是ms),超时则抛出ConnectionPoolTimeoutException*/
ConnManagerParams.setTimeout(params, 1000);
/*客户端和服务器建立连接超时时间(单位是ms),超时则抛出ConnectionTimeOutException*/
HttpConnectionParams.setConnectionTimeout(params, 2000);
/*(已建立连接)指客户端从服务器读取数据的超时时间(单位是ms),超时则抛出SocketTimeOutException*/
HttpConnectionParams.setSoTimeout(params, 4000);
4.x.超时设置实例
connectionRequestTimout(单位是ms):指从连接池获取连接的timeout超出预设时间(
- 从连接池获取连接的超时时间,如果连接池里连接都被用了,且超过设定时间就会抛出
ConnectionPoolTimeoutException
connetionTimeout(单位是ms):指客户端和服务器建立连接的timeout.
- 就是http请求的三个阶段,一:建立连接;二:数据传送;三,断开连接。如果与服务器(这里指数据库)请求建立连接的时间超过ConnectionTimeOut,就会抛
ConnectionTimeOutException
,即服务器连接超时,没有在规定的时间内建立连接。
socketTimeout(单位是ms):指客户端和服务进行数据交互的时间,是指两者之间如果两个数据包之间的时间大于该时间则认为超时,而不是整个交互的整体时间
,比如如果设置1秒超时,如果每隔0.8秒传输一次数据,传输10次,总共8秒,这样是不超时的。而如果任意两个数据包之间的时间超过了1秒,则超时。 超出后会抛出SocketTimeOutException.
public static void main(String[] args) throws Exception{
//创建httpclient
CloseableHttpClient httpClient = HttpClients.createDefault();
//创建http get
HttpGet httpGet = new HttpGet("http://www.taotao.com/");
//构建超时等配置信息
RequestConfig config = RequestConfig.custom().setConnectTimeout(1000) //连接超时时间
.setConnectionRequestTimeout(1000) //从连接池中取的连接的最长时间
.setSocketTimeout(10 *1000) //数据传输的超时时间
.setStaleConnectionCheckEnabled(true) //提交请求前测试连接是否可用
.build();
//设置请求配置时间
httpGet.setConfig(config);
//接受返回的数据
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
}finally{
if(response!=null){
response.close();
}
httpClient.close();
}
}
结合代码测试
注:下面面Case是使用httpclient版本4.5.2测试所得
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
<type>jar</type>
</dependency>
1.完整测试接口代码
/**
* 超时测试接口
*/
@RestController
@RequestMapping("/test")
@Slf4j
public class TimeoutTestController {
/**
* 1.测试socketOutTimeout,三秒后返回数据
*
* @return
* @throws InterruptedException
*/
@GetMapping("/socket_timeout")
String socketTimeout() throws InterruptedException {
log.info("socket_timeout");
TimeUnit.MILLISECONDS.sleep(3000);
return "/socket_timeout接口调用成功";
}
/**
* 2.测试socketOutTimeout,
* 每隔0.8秒返回数据,循环发送,模拟网络不好的时候,收到的数据断断续续
* @return
* @throws InterruptedException
*/
@GetMapping("/socket_timeout_2")
void socketTimeout2(HttpServletResponse response) throws InterruptedException, IOException {
log.info("socket_timeout_2");
for (int i = 0; i < 10; i++) {
log.info("{}", i);
response.getWriter().println("" + i);
response.flushBuffer();
TimeUnit.MILLISECONDS.sleep(800);
}
}
/**
* 3.测试connectionRequestTimeout用的服务,三秒后返回数据
*
* @param request
* @return
* @throws InterruptedException
*/
@GetMapping("/connection_request_timeout")
String connectionRequestTimeout(HttpServletRequest request) throws InterruptedException {
log.info("{}", request.getRequestURI());
TimeUnit.MILLISECONDS.sleep(3000);
return "/connection_request_timeout调用成功";
}
}
2.完整单元测试代码
/**
* 测试HttpClient超时参数
*/
public class TimeoutTestControllerTest {
String urlPrefix = "http://localhost:8443";
/**
* 1.connectionTimeout测试:IP无法建立连接,连接超时
*
* @throws Exception
*/
@Test
public void connectionTimeout() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://192.168.0.125:8443");
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(1000)
.build();
httpGet.setConfig(requestConfig);
long startTime = System.currentTimeMillis();
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("response:" + EntityUtils.toString(response.getEntity()) + ",请求成功耗时" + (System.currentTimeMillis() - startTime));
} catch (ConnectTimeoutException e) {
System.err.println(e.getMessage() + ",请求失败耗时:" + (System.currentTimeMillis() - startTime));
}
}
/**
* 2.socketTimeout测试,服务端没有指定时间内任何响应,会超时
*
* @throws Exception
*/
@Test
public void socketTimeout() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(urlPrefix + "/test/socket_timeout");//test/socket_timeout 3秒后才会返回数据
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(1000).build();
httpGet.setConfig(requestConfig);
long startTime = System.currentTimeMillis();
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("response:" + EntityUtils.toString(response.getEntity()) + ",请求成功耗时" + (System.currentTimeMillis() - startTime));
} catch (SocketTimeoutException e) {
System.err.println(e.getMessage() + ",请求失败耗时:" + (System.currentTimeMillis() - startTime));
}
}
/**
* 3.socketTimeout测试:服务端隔800ms返回一点数据,不会超时
*
* @throws Exception
*/
@Test
public void socketTimeoutNo() {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(urlPrefix + "/test/socket_timeout_2");
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(1000)
.build();
httpGet.setConfig(requestConfig);
long startTime = System.currentTimeMillis();
try {
httpclient.execute(httpGet);
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("response:" + EntityUtils.toString(response.getEntity()) + ",服务端每隔800ms返回一点数据,不会超时。耗时:" + (System.currentTimeMillis() - startTime));
} catch (Exception e) {
System.err.println("任意两个数据包之间的时间超过了1秒,则超时。耗时:" + (System.currentTimeMillis() - startTime));
}
}
/**
* 4.connectionRequestTimeout测试:指从连接管理器(例如连接池)中拿到连接的超时时间
* <p>
* (多线程连接池)PoolingHttpClientConnectionManager, 可以创建并管理一个连接池,为多个路由或目标主机提供连接
*/
@Test
public void connectionRequestTimeoutWithPoolingConnectionManager() throws InterruptedException {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(2);
final CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).build();
final HttpGet httpGet = new HttpGet(urlPrefix + "/test/connection_request_timeout");//当前接口会休眠3秒在返回,因此需要设大SocketTimeout
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(3500).build();
httpGet.setConfig(requestConfig);
// 如下多线程占满连接池
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
int finalI = i;
executorService.submit(() -> {
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println(finalI + "=>connectionRequestTimeoutTest1:" + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
});
}
// 在连接池占满的情况下,拿不到就会抛异常
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("main=>connectionRequestTimeoutTest2: " + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println("main=>connectionRequestTimeoutTest2=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println("main=>connectionRequestTimeoutTest2=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println("main=>connectionRequestTimeoutTest2=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
//休眠20S
TimeUnit.SECONDS.sleep(20);
}
/**
* 5.connectionRequestTimeout测试,指从连接管理器中拿到连接的超时时间,由于使用基本的连接管理器,连接被占用时,直接无法分配连接
* connectionRequestTimeout并未生效,目前看来该参数只在 “ 多线程连接池 ” 奏效.
* <p>
* (单线程连接池)BasicHttpClientConnectionManager
* 自HttpClient 4.3.3起,BasicHttpClientConnectionManager可用作HTTP连接管理器的最简单实现。它用于创建和管理一次只能由一个线程使用的单个连接。
*/
@Test
public void connectionRequestTimeoutWithBasicConnectionManager() throws Exception {
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager();
final CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).setMaxConnPerRoute(1).build();
final HttpGet httpGet = new HttpGet(urlPrefix + "/test/connection_request_timeout");
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(100000)
.setConnectionRequestTimeout(1000000).setSocketTimeout(1000000).build();
httpGet.setConfig(requestConfig);
// 如下多线程占满连接
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
int finalI = i;
executorService.submit(() -> {
try (CloseableHttpResponse response = httpclient.execute(httpGet);) {
System.out.println(finalI + "=>connectionRequestTimeoutTest1:" + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
});
}
// 在连接池占满的情况下,拿不到就会抛异常
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("main=>connectionRequestTimeoutTest2: " + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println("main=>connectionRequestTimeoutTest2=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println("main=>connectionRequestTimeoutTest2=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println("main=>connectionRequestTimeoutTest2=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
//休眠20S
TimeUnit.SECONDS.sleep(20);
}
}
分析每个单元测试案例
1.建立连接超时测试
/**
* 1.connectionTimeout测试:IP无法建立连接,连接超时
*
* @throws Exception
*/
@Test
public void connectionTimeout() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://192.168.0.125:8443");
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(1000)
.build();
httpGet.setConfig(requestConfig);
long startTime = System.currentTimeMillis();
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("response:" + EntityUtils.toString(response.getEntity()) + ",请求成功耗时" + (System.currentTimeMillis() - startTime));
} catch (ConnectTimeoutException e) {
System.err.println(e.getMessage() + ",请求失败耗时:" + (System.currentTimeMillis() - startTime));
}
}
响应结果:
当前请求的超时配置为:
- 连接池获取连接时间1秒,建立连接时间1秒,数据包响应时间1秒
接口 http://192.168.0.125:8443 并不存在,因此客户端与服务端建立连接时间超出connectTimeout
配置时间后就会抛出ConnectTimeoutException
2.响应超时测试(单个数据包)
/**
* 2.socketTimeout测试,服务端没有指定时间内任何响应,会超时
*
* @throws Exception
*/
@Test
public void socketTimeout() throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(urlPrefix + "/test/socket_timeout");//test/socket_timeout 3秒后才会返回数据
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(1000).build();
httpGet.setConfig(requestConfig);
long startTime = System.currentTimeMillis();
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("response:" + EntityUtils.toString(response.getEntity()) + ",请求成功耗时" + (System.currentTimeMillis() - startTime));
} catch (SocketTimeoutException e) {
System.err.println(e.getClass().getName() + ":" + e.getMessage()+"=》请求失败耗时:" + (System.currentTimeMillis() - startTime));
}
}
响应结果:
当前请求的超时配置为:
- 连接池获取连接时间1秒,建立连接时间1秒,数据包响应时间1秒
接口 /test/socket_timeout 会休眠3秒,因此服务端响应单个数据包超出socketTimeout
配置时间后就会抛出SocketTimeoutException
3.响应超时测试(多个数据包)
网络不好时,服务端可能会分段返回多个数据包时,包与包之前不超过socketTimeout时间,而整体时间超过socketTimeout时间,也不会判断为超时
/**
* 3.socketTimeout测试:服务端隔800ms返回一点数据,不会超时
*
* @throws Exception
*/
@Test
public void socketTimeoutNo() {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(urlPrefix + "/test/socket_timeout_2");
//设置超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(1000)
.build();
httpGet.setConfig(requestConfig);
long startTime = System.currentTimeMillis();
try {
httpclient.execute(httpGet);
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("response:" + EntityUtils.toString(response.getEntity()) + ",服务端每隔800ms返回一点数据,不会超时。耗时:" + (System.currentTimeMillis() - startTime));
} catch (Exception e) {
System.err.println( e.getClass().getName() + ":" + e.getMessage()+"=》任意两个数据包之间的时间超过了1秒,则超时。耗时:" + (System.currentTimeMillis() - startTime));
}
}
响应结果:
当前请求的超时配置为:
- 连接池获取连接时间1秒,建立连接时间1秒,数据包响应时间1秒
接口 /test/socket_timeout_2 每隔0.8秒传输一次数据,传输10次,总共8秒,这样是不超时的。而如果任意两个数据包之间的时间超过了1秒,则超时
,超出后会抛出SocketTimeOutException
本人测试过: 实际上
okHttp
以及HttpURLConnection
的 socketTimeOut 都是 连接建立后,数据传输过程中数据包之间
间隔的最大时间
.
如果说错了请在下方对本文评论
4.多线程连接获取连接超时测试
/**
* 4.connectionRequestTimeout测试:指从连接管理器(例如连接池)中拿到连接的超时时间
* <p>
* (多线程连接池)PoolingHttpClientConnectionManager, 可以创建并管理一个连接池,为多个路由或目标主机提供连接
*/
@Test
public void connectionRequestTimeoutWithPoolingConnectionManager() throws InterruptedException {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(2);
final CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).build();
final HttpGet httpGet = new HttpGet(urlPrefix + "/test/connection_request_timeout");//当前接口会休眠3秒在返回,因此需要设大SocketTimeout
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(1000)
.setConnectTimeout(1000)
.setSocketTimeout(3500).build();
httpGet.setConfig(requestConfig);
// 如下多线程占满连接池
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
int finalI = i;
executorService.submit(() -> {
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println(finalI + "=>connectionRequestTimeoutTest1:" + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
});
}
// 在连接池占满的情况下,拿不到就会抛异常
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("main=>connectionRequestTimeoutTest2: " + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println("main=>connectionRequestTimeoutTest2=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println("main=>connectionRequestTimeoutTest2=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println("main=>connectionRequestTimeoutTest2=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
//休眠20S
TimeUnit.SECONDS.sleep(20);
}
响应结果:
当前请求的超时配置为:
- 连接池获取连接时间1秒,建立连接时间1秒,数据包响应时间3.5秒
接口 /test/connection_request_timeout 会在3秒后返回数据,导致一个连接会被占用3秒后,才能被恢复可用状态,当多个线程同时从PoolingHttpClientConnectionManager 获取连接时,无空闲连接可用且超出等待获取连接池连接时间
,会抛出ConnectionPoolTimeoutException
5.单线程连接获取连接超时测试
/**
* 5.connectionRequestTimeout测试,指从连接管理器中拿到连接的超时时间,由于使用基本的连接管理器,连接被占用时,直接无法分配连接
* connectionRequestTimeout并未生效,目前看来该参数只在 “ 多线程连接池 ” 奏效.
* <p>
* (单线程连接管理)BasicHttpClientConnectionManager
* 自HttpClient 4.3.3起,BasicHttpClientConnectionManager可用作HTTP连接管理器的最简单实现。它用于创建和管理一次只能由一个线程使用的单个连接。
*/
@Test
public void connectionRequestTimeoutWithBasicConnectionManager() throws Exception {
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager();
final CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).setMaxConnPerRoute(1).build();
final HttpGet httpGet = new HttpGet(urlPrefix + "/test/connection_request_timeout");
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(100000)
.setConnectionRequestTimeout(1000000).setSocketTimeout(1000000).build();
httpGet.setConfig(requestConfig);
// 如下多线程占满连接
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
int finalI = i;
executorService.submit(() -> {
try (CloseableHttpResponse response = httpclient.execute(httpGet);) {
System.out.println(finalI + "=>connectionRequestTimeoutTest1:" + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println(finalI + "=>connectionRequestTimeoutTest1=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
});
}
// 在连接池占满的情况下,拿不到就会抛异常
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println("main=>connectionRequestTimeoutTest2: " + EntityUtils.toString(response.getEntity()));
} catch (SocketTimeoutException e) {
System.err.println("main=>connectionRequestTimeoutTest2=SocketTimeoutException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (IOException e) {
System.err.println("main=>connectionRequestTimeoutTest2=IOException=>" + e.getClass().getName() + ":" + e.getMessage());
} catch (Exception e) {
System.err.println("main=>connectionRequestTimeoutTest2=Exception=>" + e.getClass().getName() + ":" + e.getMessage());
}
//休眠20S
TimeUnit.SECONDS.sleep(20);
}
响应结果:
当前请求的超时配置为:
-
连接池获取连接时间1秒,建立连接时间1秒,数据包响应时间1秒
接口 /test/connection_request_timeout 会在3秒后返回数据,导致一个连接会被占用3秒后,才能被恢复可用状态,
BasicHttpClientConnectionManager
是一个简单的连接管理器,它用于创建和管理一次只能由一个线程使用的单个连接。
使用他当获取连接时超过 connectionRequestTimeout并未抛出ConnectionPoolTimeoutException
,因此可以得出connectionRequestTimeout是从 连接池获取连接的超时时间的设置