官术网_书友最值得收藏!

2.2.3 偽異步I/O弊端分析

要對偽異步I/O的弊端進行深入分析,首先我們看兩個Java同步I/O的API說明,隨后我們結合代碼進行詳細分析。

代碼清單2-6 Java輸入流InputStream

請注意加粗斜體字部分的API說明,當對Socket的輸入流進行讀取操作的時候,它會一直阻塞下去,直到發生如下三種事件。

◎ 有數據可讀;

◎ 可用數據已經讀取完畢;

◎ 發生空指針或者I/O異常。

這意味著當對方發送請求或者應答消息比較緩慢、或者網絡傳輸較慢時,讀取輸入流一方的通信線程將被長時間阻塞,如果對方要60s才能夠將數據發送完成,讀取一方的I/O線程也將會被同步阻塞60s,在此期間,其他接入消息只能在消息隊列中排隊。

下面我們接著對輸出流進行分析,還是看JDK I/O類庫輸出流的API文檔,然后結合文檔說明進行故障分析。

代碼清單2-7 Java輸入流OutputStream

當調用OutputStream的write方法寫輸出流的時候,它將會被阻塞,直到所有要發送的字節全部寫入完畢,或者發生異常。學習過TCP/IP相關知識的人都知道,當消息的接收方處理緩慢的時候,將不能及時地從TCP緩沖區讀取數據,這將會導致發送方的TCP window size不斷減小,直到為0,雙方處于Keep-Alive狀態,消息發送方將不能再向TCP緩沖區寫入消息,這時如果采用的是同步阻塞I/O,write操作將會被無限期阻塞,直到TCP window size大于0或者發生I/O異常。

通過對輸入和輸出流的API文檔進行分析,我們了解到讀和寫操作都是同步阻塞的,阻塞的時間取決于對方I/O線程的處理速度和網絡I/O的傳輸速度。本質上來講,我們無法保證生產環境的網絡狀況和對端的應用程序能足夠快,如果我們的應用程序依賴對方的處理速度,它的可靠性就非常差。也許在實驗室進行的性能測試結果令人滿意,但是一旦上線運行,面對惡劣的網絡環境和良莠不齊的第三方系統,問題就會如火山一樣噴發。

偽異步I/O實際上僅僅只是對之前I/O線程模型的一個簡單優化,它無法從根本上解決同步I/O導致的通信線程阻塞問題。下面我們就簡單分析下如果通信對方返回應答時間過長,會引起的級聯故障。

(1)服務端處理緩慢,返回應答消息耗費60s,平時只需要10ms。

(2)采用偽異步I/O的線程正在讀取故障服務節點的響應,由于讀取輸入流是阻塞的,因此,它將會被同步阻塞60s。

(3)假如所有的可用線程都被故障服務器阻塞,那后續所有的I/O消息都將在隊列中排隊。

(4)由于線程池采用阻塞隊列實現,當隊列積滿之后,后續入隊列的操作將被阻塞。

(5)由于前端只有一個Accptor線程接收客戶端接入,它被阻塞在線程池的同步阻塞隊列之后,新的客戶端請求消息將被拒絕,客戶端會發生大量的連接超時。

(6)由于幾乎所有的連接都超時,調用者會認為系統已經崩潰,無法接收新的請求消息。如何破解這個難題?下節的NIO將給出答案。

主站蜘蛛池模板: 任丘市| 永年县| 丰城市| 泰来县| 华池县| 蓝田县| 长丰县| 叶城县| 错那县| 全椒县| 榆树市| 枣强县| 南开区| 大方县| 长岭县| 长子县| 宜章县| 青神县| 河间市| 吕梁市| 阆中市| 蓬莱市| 丁青县| 延长县| 寻乌县| 泾阳县| 泸溪县| 阳谷县| 甘洛县| 宣威市| 上思县| 娄底市| 上思县| 金寨县| 长岛县| 平遥县| 巴马| 萨嘎县| 富蕴县| 临湘市| 油尖旺区|