穩定性三十六計-超時處理

引子
分佈式系統調用的三態
在傳統的單機系統中,調用一個函數,要麼返回成功,要麼返回失敗。這就是兩態系統(2-state system)。
在分佈式系統中,因爲系統是分佈在不一樣機器上的。還可能有一種狀態叫:超時。成功、失敗和超時是分佈式系統調用的三態。
爲何要超時處理
對於超時這種狀態,長時間等待會影響用戶體驗,併發量大時還可能會由於線程池耗盡而不能響應其餘請求。若是這個服務的調用方也是一個服務,那就有可能產生級聯反應,致使其餘服務不可用,最終產生雪崩效應。
 
超時處理的手段
超時處理的兩個要點:判斷何時超時和超時後怎麼處理。
判斷何時超時在無基礎數據時可經過經驗估算一個相對合理值。在服務上線後可依賴統計進行設置,好比設置99%的請求響應時間爲超時時間。還能夠經過人工智能進行調參來設置。
超時後通常採用快速失敗,若是不是核心服務,可直接超時返回失敗。若是是核心服務,能夠設置相應的重試次數。
 
HTTP請求超時處理
HTTP請求通常會對兩個階段作超時處理:創建鏈接階段、數據通訊階段。在apache的HttpClient實現中,添加了獲取鏈接池階段。
獲取鏈接池階段
由於創建鏈接須要IO、網絡帶寬等開銷,須要池化處理,若是超過了鏈接池的最大值,則須要等待其餘鏈接執行完釋放資源。超時時間通常設置爲1s以內。
創建創建階段
HTTP請求須要「三次握手」,第一次握手客戶端發送一個報文到服務器表示想和服務端創建鏈接。第二次握手是服務端接收到客戶端的請求,返回帶有同步和相應標記的客戶端報文,詢問客戶端是否準備好。第三次握手是客戶端再次響應服務端表示已經準備好。超時時間通常設置爲1s到5s。
數據通訊階段
與目標url創建鏈接後,等待數據報文傳輸的時間。這個階段又叫作socket通訊階段。這個階段可能有兩種類型的事件:讀取和寫入。超時時間通常設1s到5s。
在以上三個階段的任何一個階段發生超時則當即終止等待返回失敗,http請求通常會設置超時後有三次重試。爲了進一步理解,能夠藉助HttpClient的調用代碼來感覺一下其使用
    HttpParams httpParams = new BasicHttpParams();
    // 獲取鏈接的最大等待時間1s,對應獲取鏈接池階段
    ConnManagerParams.setTimeout(httpParams, 1000);
    // 鏈接超時時間5s,對應創建創建階段
    HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
    // socket超時時間5s,對應數據通訊階段
    HttpConnectionParams.setSoTimeout(httpParams, 5000);
最近由於OkHttpClient比HttpClient更簡單易用,使用的人多起來。藉助OkHttpClient的調用代碼來感覺一下其使用
    OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
    // 鏈接超時時間5s,對應創建創建階段
    httpClientBuilder.connectTimeout(config.getConnectionTimeout(), TimeUnit.MILLISECONDS);
    // 讀取超時時間5s,對應數據通訊階段(將socket細分爲讀取和寫入兩種類型)
    httpClientBuilder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
    // 寫入超時時間5s,對應數據通訊階段(將socket細分爲讀取和寫入兩種類型)
    httpClientBuilder.writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
讀取和寫入都是socket階段的一個證據是若是發生超時,曝出的異常是SocketTimeoutException
 
Mysql鏈接超時處理
客戶端和Mysql鏈接也分爲創建鏈接和數據通訊兩個階段。目前mysql經常使用的版本是5.6和5.7。
和超時處理相關的參數彙總以下
 
參數名稱 參數說明 缺省值 最低版本要求
connectTimeout
和數據庫服務器簡歷socket鏈接時的超時
單位:毫秒。0表示永不超時
0 3.0.1
socketTimeout
socket操做(讀寫)超時
單位:毫秒。0表示永不超時
0 3.0.1
autoReconnect 當數據庫鏈接異常中斷時是否自動重連 false 1.1
maxReconnects autoReconnect=true時,重試鏈接的次數 3 1.1
failOverReadOnly 自動重連成功後,鏈接是否設置爲只讀 true 3.0.12
autoReconnectForPools 是否使用針對數據庫鏈接池的重連策略 False 3.1.3
 
總結
慢就是錯 
 

關於做者mysql

一線開發十二年,有日本東京和美國硅谷研發經驗。有百餘項技術發明專利,目前任美團點評技術專家。有本身的技術公衆號「編程一輩子」。若是您在閱讀文章時有什麼疑問或者發現文章的錯誤,歡迎在公衆號裏給我留言。sql

相關文章
相關標籤/搜索