HttpClient有三種超時(shí)時(shí)間設(shè)置,在RequestConfig配置類中定義的,分別為connectionRequestTimeout、connectTimeout和socketTimeout,如下圖,然后分開講解。

RequestConfig三種超時(shí)時(shí)間屬性
一、準(zhǔn)備實(shí)驗(yàn)代碼
1、服務(wù)端代碼
準(zhǔn)備一個(gè)controller代碼,如下:

服務(wù)端代碼
2、客戶端代碼
準(zhǔn)備一個(gè)測(cè)試類作為客戶端,如下:

客戶端代碼
二、三種超時(shí)時(shí)間各自驗(yàn)證
1、connectTimeout
字面含義就是連接超時(shí)時(shí)間,查閱了下資料說(shuō)是客戶端和服務(wù)端建立連接即三次握手階段的超時(shí)時(shí)間。于是通過(guò)調(diào)整上面客戶端的請(qǐng)求代碼進(jìn)行驗(yàn)證。
將請(qǐng)求端口號(hào)調(diào)成一個(gè)錯(cuò)誤的端口,目的是讓三次握手不成功,然后執(zhí)行客戶端請(qǐng)求,結(jié)果如下:

connectTimeout報(bào)錯(cuò)
發(fā)現(xiàn)報(bào)錯(cuò)是connect time out,并且可以通過(guò)調(diào)整前面客戶端代碼中的setConnectTimeout(1000)的值去驗(yàn)證超時(shí)時(shí)間是否生效,我這里進(jìn)行了驗(yàn)證發(fā)現(xiàn)這里的時(shí)間調(diào)為2000以上時(shí)候就不起作用了,好像最大只能2000ms超時(shí)似的。
2、socketTimeout
這個(gè)查閱了下是在客戶端和服務(wù)端建立好連接之后,服務(wù)端和客戶端之間數(shù)據(jù)包傳輸?shù)某瑫r(shí)時(shí)間,而且這個(gè)超時(shí)時(shí)間是單次數(shù)據(jù)包超時(shí)時(shí)間,而不是整個(gè)數(shù)據(jù)傳輸過(guò)程的超時(shí)時(shí)間,同樣改下代碼進(jìn)行驗(yàn)證。需要調(diào)整下服務(wù)端Controller的代碼為多次發(fā)送數(shù)據(jù),并在每次發(fā)送后睡眠一會(huì)如1000ms,如下:

再改下setSocketTimeout(999),運(yùn)行客戶端代碼,結(jié)果如下:

可以看到有socket time out報(bào)錯(cuò),接下來(lái)我們?cè)賹etSocketTimeout(1003)調(diào)大一點(diǎn),觀察是否成功,發(fā)現(xiàn)調(diào)大時(shí)間之后,沒(méi)有報(bào)錯(cuò),可以正常拿到完整的數(shù)據(jù),那也就說(shuō)明了socketTimeout是單個(gè)數(shù)據(jù)包的超時(shí)時(shí)間,不是整體數(shù)據(jù)傳輸?shù)某瑫r(shí)時(shí)間。
3、connectionRequestTimeout
同樣查閱是客戶端從連接池中獲取連接的超時(shí)時(shí)間,那這里驗(yàn)證的話我們就需要自己指定線程池大小,讓連接池滿了,從而導(dǎo)致獲取不到連接。
調(diào)整客戶端代碼如下:

運(yùn)行代碼,結(jié)果如下:

可以看到已經(jīng)報(bào)錯(cuò)Timeout waiting for connection from pool。
通過(guò)以上驗(yàn)證均已理解connectionRequestTimeout、connectTimeout和socketTimeout三個(gè)超時(shí)時(shí)間的意義,下次再遇到線上異常報(bào)錯(cuò)就可以直接根據(jù)異常類型定位。如果是ConnectTimeout多半就是服務(wù)端網(wǎng)絡(luò)問(wèn)題、服務(wù)端關(guān)機(jī)、服務(wù)端端口問(wèn)題等。如果遇到SocketTimeout多半就是服務(wù)端忙碌,線程數(shù)滿了,或者服務(wù)端性能受限來(lái)不及處理請(qǐng)求等等,目前connectionRequestTimeout還基本沒(méi)見到過(guò)這類異常。