HttpClient有三种超时时间设置,在RequestConfig配置类中定义的,分别为connectionRequestTimeout、connectTimeout和socketTimeout,如下图,然后分开讲解。
RequestConfig三种超时时间属性
一、准备实验代码
1、服务端代码
准备一个controller代码,如下:
服务端代码
2、客户端代码
准备一个测试类作为客户端,如下:
客户端代码
二、三种超时时间各自验证
1、connectTimeout
字面含义就是连接超时时间,查阅了下资料说是客户端和服务端建立连接即三次握手阶段的超时时间。于是通过调整上面客户端的请求代码进行验证。
将请求端口号调成一个错误的端口,目的是让三次握手不成功,然后执行客户端请求,结果如下:
connectTimeout报错
发现报错是connect time out,并且可以通过调整前面客户端代码中的setConnectTimeout(1000)的值去验证超时时间是否生效,我这里进行了验证发现这里的时间调为2000以上时候就不起作用了,好像最大只能2000ms超时似的。
2、socketTimeout
这个查阅了下是在客户端和服务端建立好连接之后,服务端和客户端之间数据包传输的超时时间,而且这个超时时间是单次数据包超时时间,而不是整个数据传输过程的超时时间,同样改下代码进行验证。需要调整下服务端Controller的代码为多次发送数据,并在每次发送后睡眠一会如1000ms,如下:
再改下setSocketTimeout(999),运行客户端代码,结果如下:
可以看到有socket time out报错,接下来我们再将setSocketTimeout(1003)调大一点,观察是否成功,发现调大时间之后,没有报错,可以正常拿到完整的数据,那也就说明了socketTimeout是单个数据包的超时时间,不是整体数据传输的超时时间。
3、connectionRequestTimeout
同样查阅是客户端从连接池中获取连接的超时时间,那这里验证的话我们就需要自己指定线程池大小,让连接池满了,从而导致获取不到连接。
调整客户端代码如下:
运行代码,结果如下:
可以看到已经报错Timeout waiting for connection from pool。
通过以上验证均已理解connectionRequestTimeout、connectTimeout和socketTimeout三个超时时间的意义,下次再遇到线上异常报错就可以直接根据异常类型定位。如果是ConnectTimeout多半就是服务端网络问题、服务端关机、服务端端口问题等。如果遇到SocketTimeout多半就是服务端忙碌,线程数满了,或者服务端性能受限来不及处理请求等等,目前connectionRequestTimeout还基本没见到过这类异常。