架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法

技術瑣話發表於2019-04-18

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法

本文節選自《架構修煉之道》,作者京東王新棟。

圖 | meghan-holmes-779221-unsplash

這裡說的傳統,是按照閘道器技術演進的階段劃分的,從同步到半同步,再到全非同步,我們將同步和半同步技術下的閘道器稱為“傳統”閘道器,同步閘道器的意思是從接收請求到呼叫API介面提供方的過程都是同步呼叫;半同步則是指將I/O請求執行緒和業務處理執行緒分開,但業務執行緒內部還是同步呼叫API介面;全非同步的意思就比較清楚了,整個鏈路都是非同步請求。接下來介紹“傳統”閘道器會在什麼情況下“down掉”。

API閘道器係統有兩大特點,一個是訪問量大,另一個是依賴系統多。如下圖所示,“單純”的情況下(比如系統A提供的介面只供閘道器呼叫)閘道器係統要承受比被依賴的系統多數倍的流量,因為API閘道器是所有依賴API的集合。閘道器還會通過RPC呼叫很多底層系統,每個系統的穩定性水平參差不齊,介面的效能也會間接影響閘道器整體的執行穩定性。因此我們在做防範的時候就要從這兩個特點入手。

 

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法 

上面介紹了API閘道器的兩大特點,這兩個特點算外部因素,接著再來看一下內部因素。程式都是執行在計算機上面的,計算機的每個部件的利用率和負載水平直接影響程式的執行。比如CPU、記憶體、磁碟等。另外系統之間的互動還需要網路,這些都需考慮。一段程式在計算機中的執行依賴部件如下圖所示。

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法

關注CPU

使用者請求在進入閘道器的時候我們從技術上已經把I/O請求執行緒和業務處理執行緒隔離開了,這一點可以利用Servlet3非同步特性實現(下面還會詳細介紹Servlet3的非同步特性),如下圖所示。

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法


業務執行緒池毫無疑問是在CPU裡面執行的,執行緒是計算機CPU最寶貴的資源,我們一定要重點關注CPU利用率和CPU負載。

  • CPU利用率:顯示的是程式在執行期間實時佔用的CPU百分比。

  • CPU負載:顯示的是一段時間內正在使用和等待使用CPU的平均任務數。在Linux系統中,我們可以使用uptimetop(使用top會看到更詳細的資訊)命令來檢視系統的負載情況。如果使用uptime命令則會得到如下一行:


11:36 up 23 days, 2:31, 2users, load averages: 1.74 1.58 1.60


最後的loadaverages的意思是系統平均負載,它包含三個數字,這三個數字分別表示1分鐘、5分鐘、15分鐘內系統的負載平均值。我們可以按照1分鐘的粒度取第一個數字,從而判定系統負載的大小。

上面的23days說明筆者有23天沒有重啟過計算機了。

注意,CPU利用率高,並不意味著負載就一定大,兩者沒有必然聯絡。

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法

關於這兩個概念的理解,我們還可以舉一個例子來說明。有8個人在排隊玩一個打地鼠的遊戲機,要求1分鐘之內要打完100個地鼠,如果有人一分鐘之內沒有完成這個任務,那麼就需要重新排隊,等待下一輪。遊戲機在這裡相當於CPU,正在或等待玩打地鼠遊戲的人就相當於任務數量。

在玩遊戲的過程中,肯定有的人在規定的1分鐘之內打完100個地鼠,完成任務之後就離開了,有人沒有完成任務而去重新排隊,還有可能有新增的人來玩這個遊戲,人數的變化相當於任務的增減。有的人拿起打地鼠的錘子就開始玩,一直打完1分鐘,而有的人可能在前20秒看手機,後40秒才開始玩打地鼠。把遊戲機看作CPU,排隊的人數看作任務數,我們說前一種人(任務)的CPU利用率高,後一種人(任務)的CPU利用率低。

當然CPU不會在前20秒休息、後40秒工作,只是說,有的程式可能涉及的計算量比較大,CPU利用率就高,而有的程式涉及的計算少,CPU的利用率就低。不管CPU利用率是高是低,跟後面有多少人(任務)在排隊沒有必然的聯絡。

之所以花了一些篇幅來介紹CPU的這兩個概念,因為這兩個指標實在是太重要了,線上上生產環境中是需要重點監控的。鑑於API閘道器的訪問量大和依賴系統多的特點,如果呼叫的API效能突然變差,在大訪問量的情況下,執行緒數會逐漸升高,直至將CPU資源耗盡。蔓延到整個閘道器叢集,這就是雪崩的效應。

關注磁碟

磁碟有兩個比較重要的指標分別是磁碟使用率和磁碟負載百分比。磁碟使用率比較容易理解,我們重點說一下磁碟負載百分比這個指標。在Linux系統下檢視該指標的命令為 iostat -x 1 10 (如果沒有iostat ,則需要使用yum install sysstat進行安裝),筆者下面的圖中示例值還構不成威脅,但如果 %util 接近 100%,則說明產生的I/O請求太多,I/O系統已經滿負荷,該磁碟可能存在瓶頸,如下圖所示。

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法

程式執行的過程中我們可能都不會關注磁碟的使用,如果處理不當,這有可能是一個“定時炸彈”。閘道器的特性訪問量大,再加上有的程式裡面的日誌列印不規範,比如日誌的級別設定得不合理,把info日誌列印出來。即使在日誌級別合理的情況下,比如error日誌,這時又涉及閘道器的第二個特性,依賴系統多。當有API返回失敗錯誤的時候,就會有大量的error日誌寫入磁碟,很容易把磁碟打滿,尤其在容器時代,每臺伺服器分配的磁碟容量相對物理機來說都比較小,如果叢集的所有機器磁碟被打滿,對閘道器係統來說無疑是一場災難。

關注網路

在微服務系統架構下,應用離不開網路,尤其是閘道器係統,它的特點之一就是依賴系統多。依賴就是RPC呼叫和網路。在一個RPC環境下,網路佔據了一次RPC呼叫所耗時間的很大比重。網路質量的好壞直接影響了一次請求從進入API閘道器到返回給使用者響應的時間長短。如下圖所示,閘道器到依賴系統B之間的網路突然變差,呼叫時長增加,在請求訪問量多的時候,一請求一執行緒的模式下,會直接導致API 閘道器係統的任務執行緒數增多,如果短時間內不能恢復,則整個API閘道器的叢集所有機器的CPU資源都會被執行緒耗盡。

同時現有的線上生產環境部署並不能完全保證同機房呼叫,甚至還有跨地區呼叫,因此網路是我們要考慮的一個重要因素,同時網路的因素需要和上面講到的CPU的執行緒資源相關聯去考慮。

架構修煉之道 | 一個傳統閘道器係統有幾種 “死” 法

現在可以總結一個傳統API閘道器係統會有幾種“死”法了,因為依賴的某個系統的API效能突然變差導致請求執行緒數量逐漸升高直至執行緒佔滿了CPU,也就是API閘道器依賴系統多的特點因素,可以認為是被其他系統“拖死”的。線上生產環境下日誌輸出不規範,過度列印日誌,再加上請求量突然變大,導致清理工具來不及清理日誌,最後磁碟滿了,可以認為是被日誌“打死”的。網路一直是一個除系統本身外最不穩定的因素,在系統之間呼叫的時候,網路發生故障導致請求變慢,這一點和第一條被其他系統“拖死”類似,只是這次是網路。

查理.芒格有一句名言:“如果我知道我會死在哪裡,我將永遠不去那個地方”。同樣對於一個API閘道器係統,如果我們知道哪些因素會導致一個閘道器“掛掉”,那麼我們就會提前防範,以避免這種“災難”的發生。當然並不是宣揚傳統閘道器不好,它也有自己的優勢,比如程式設計模型簡單、開發除錯運維方便等。如果業務規模較小,比如每天呼叫量不足千萬,或者不到億級,那麼可以繼續使用這種型別的閘道器,甚至達到億級規模之後再配合有效的容錯機制(比如Netflixzuul1+Hystrix)也可以支撐上億規模的訪問量。不過我們有更好的非同步閘道器解決方案,接下來介紹非同步閘道器技術實現。

本文作者:王新棟

現就職於京東,“程式架道”公眾號作者。平時熱愛總結與分享,對高效能API閘道器、執行緒調優、NIO、微服務架構、容錯等技術有較深的研究和實戰經驗。目前致力於帶領團隊在平臺開放技術領域實現突破。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562044/viewspace-2641836/,如需轉載,請註明出處,否則將追究法律責任。

相關文章