如果OKHTTP第一次出現SocketTimeoutException,後續即使網路已經恢復正常,請求也始終返回SocketTimeoutException。 ...
研發中心/王鵬 2019年7月
關鍵詞:OKHTTP,安卓,連接復用,開源軟體BUG
一.背景知識:
OKHTTP已是安卓項目中被廣泛使用的網路請求開源庫,它有如下特性:
1.支持HTTP/2,允許所有同一個主機地址的請求共用同一個socket連接;
2.連接池減少請求延時;
3.緩存響應內容,避免一些完全重覆的請求;
4.透明的GZIP壓縮減少響應數據的大小;
其中前三點特性可理解為就是連接復用,但後來發現這裡有坑~
二.問題現象:
據現場端反饋,即使在網路正常的情況下,也會有個別設備會在某個時段內出現支付緩慢,多筆交易連續失敗的情況。
通過業務保障平臺發現訂單查詢介面一直出現SocketTimeOutException。
三.問題原因:
如果OKHTTP第一次出現SocketTimeoutException,後續即使網路已經恢復正常,請求也始終返回SocketTimeoutException,必須等到雙活功能變數名稱切換或者重新連接WiFi,或重新啟動應用程式才能恢復正常。
四.排查過程:
根據以上日誌分析,可發現一個規律:切換(雙活機房)基礎功能變數名稱時,請求便恢復正常,基本符合OKHTTP源碼中不復用之前連接的條件:
所以我初步懷疑這是連接復用的特性導致的:
即問題出現之後,一直在復用錯誤的連接,而功能變數名稱切換之後,不再復用之前的錯誤連接,於是請求恢復正常。
但項目中的連接池復用一直採用的是OKHTTP預設設置的配置,未做其他改動,所以懷疑OKHTTP有BUG。
查看OkHttp GitHub的issues,發現2019年4月26號新增了一條Issues,與我們的問題類似。問題如下:
內容大致意思為:部分設備出現了SocketTimeOut後,後續請求一直返回SocketTimeOut,尤其是在4G網路下比較常見!目前該問題仍未解決,處於開放狀態,BUG依舊存在。
五.解決方法:
在全局 ResponseError 監聽器里,如果發現出現 SocketTimeOut 就清空連接池:
目前此方案的缺點是應用程式出現SocketTimeOut一次,下一次訪問才能成功,當前請求無法修正。
後續會持續關註此issues修複狀態,及時更新。
七.經驗教訓:
1.使用第三方開源庫,一定要熟悉其原理,在使用前一定要通篇瞭解其issues中反饋的各種問題,評估其影響,平常定期不定期關註其Issues更新。p.s.:鄭總的《那些年我們一起犯過的錯》,已給我們打過預防針了。
2.做好邊界測試和壓力測試。
3.一定要重視線上問題,明確根本原因並評估其影響。之前慣性地認為SocketTimeOut就是網路狀況不好導致的,未引起足夠重視。
八.RCA類型:
開源軟體的BUG
-EOF-
歡迎關註公眾號:老兵筆記,講述那些年我們一起犯過的錯