隨著負載的增長,你精心設計的程序可能會遭遇很多突如其來的問題:系統原有的平穩將被打破,我們將對這些問題逐一考察。當然,你可以進行橫向或縱向的擴展,也可以選擇編寫出更好的程序,讓你的系統可以處理更高的負載。這樣做可以節省更多的硬件開支,并讓你的整個應用更加可靠,具有更快的響應時間。對于程序員來說,這必將獲得非常大的滿足感。
大量的對象
當系統中的對象數量增長到一定程度,我們通常將面臨規模問題。隨著對象數目的增長,所有類型的資源開銷顯然會帶來很大的壓力。
持續的故障會產生一個無窮事件流
在大型網絡的故障場景中,我們沒有時間進行系統恢復。因為我們始終處于一個持續的壓力狀態下。
大量的高優先級任務
舉個例子,重選路由(rerouting)是個高優先級的活動。如果存在大量不能分發(shed)或取消(squelched)的重選路由任務,資源將連續不斷的被消耗以支持高優先級任務。
更大的數據流
當媒體資源大小增長得更大時,系統的負載將會增長。系統負載會隨著請求來源數目的增長而增長。
功能變更
在系統原有設計之外添加更多的功能后,系統中的漏洞也隨之暴露。
客戶端的增長
更多的客戶端意味著更多的資源消耗。需要設置線程為客戶端推送事件;客戶端隊列會消耗內存;通信會消耗帶寬;需要為每個客戶端維持一份獨立數據。
不夠好的設計決策
以下是一些會加劇規模問題的設計問題。
設計未考慮處理大量對象。
缺乏端到端應用級別的流控。
應用級別的重試將導致資源再分配和消息發送。
內存中代碼庫的開銷。
并不真正可靠的發布。
特定數據結構過度占用內存。
消息協議沒有處理所有故障場景。
使用磁盤作為存儲。
磁盤同步沒有使用塊復制。
認為應用層協議會更有好。
依靠大功耗的CPU來提升功能負載。
操作系統不支持進程架構。(譯者注:該點討論見原文鏈接處的評論)
缺乏對于某些敏感操作(甚至是單條消息的刪除)的硬件支持。
特別的網絡問題,比如ARP數據包,當網絡負載增長時就會出現丟失。
無效的假設
你所做的大部分假設都是無效的,比如你需要使用多少內存,某些任務需要運行多少時間,設置多少超時時間才算合理,一次會消費多少資源,可能發生什么樣的故障,系統在不同點的延遲,你的隊列需要多大,等等。
內存不足
內存使用基線的增長和內存使用峰值的增長,都會導致內存不足。
CPU饑餓
隨著對象操作的增加,將需要占用更長的時間,這是因為這些操作需要操作更多的對象??捎肅PU將變得更少從而導致其他的操作將面臨CPU饑餓。系統一處出現了饑餓,就會傳播到其他各處。這樣一來就沒有足夠的CPU來處理那些需要去完成的必要任務。導致這樣的原因可能是任務的基數過高或某些情況下很多高優先級的任務需要完成。
原始資源使用率增長
更多的對象將占用更多的內存。如果某人想要支持1000個并發對象,很可能是做不到的,因為你可能根本就沒有足夠的內存。
隱式資源使用率增長
大多數功能中,針對“原始”資源使用開銷中的每項資源,都將會需要大量的額外資源。如果你將一個對象存儲在兩個不同的列表里,你的對象數目和內存開銷將是原來的兩倍;隊列大小可能也需要向上調整;磁盤的數目需要增加;將數據復制到從機的時間在增長;將數據加載到應用中的時間在增長;為了處理這些工作CPU的使用率在增長;啟動時間也在增長。
事件的疊加
很多系統面臨的一個新的現實是無窮工作流。Web服務器和應用服務器服務著非常大的用戶群,這是一個真實的可預計的關于新工作的無窮流。而工作將永不結束。一周7天24小時都會有請求進來。以100%的CPU使用率進行工作可以很容易使服務器達到飽和。
習慣上我們將100%的CPU使用率視為一個不良的信號。作為補償,我們將創建復雜的基礎設施來對工作進行負載均衡,復制狀態并做好主機集群。
CPU永不疲倦,所以你可能會認為我們應該嘗試使用盡可能多的CPU。
在其他領域我們試圖通過最大限度的利用資源來提升生產率。
而在服務器的世界里,我們嘗試通過人為的方式強制地降低CPU使用率從而保證一定的響應水平。該理由是因為如果我們沒有更高的CPU可用性,我們將無法在合理的延遲時間內響應新的工作或完成現有的工作。
CPU使用率達到100%真的存在問題嗎?我們在對系統做架構設計時,寧可使用CPU可用性和任務優先級作為架構設計認知上簡略的一種解釋依據,也不愿意先去理解下我們系統的底層工作流,從而使用這些信息再來做出明確的規劃決策。難道這不正是真正的問題所在嗎?
我們基于負載均衡服務器做出了拙劣的架構決策,通過主觀臆想猜測了使用的線程數以及這些線程的優先級。除了以上這些,我們根本沒有使用工具做過任何其他事。
擴展一個系統需要仔細地關注架構。在當前框架的應用程序中,卻很少有對所轄應用是如何運行的進行說明。
延遲的增長
你所經歷的延遲增長與規模增長可能是完全不同的。CPU饑餓是該問題的主要原因。
任務優先級被證明是錯誤的
任務優先級方案可以有效地工作在較小負載下,但是在高負載下就會產生問題。舉個典型的例子,有一套簡陋的流控裝置,一個高優先級任務向一個較低優先級的任務傳遞工作將會導致工作丟失和內存使用峰值,因為低優先級的任務的運行機會將會很少。
隊列容量不足夠大
大量的對象意味著可以進行更多的并發操作,這意味著隊列容量將很可能需要擴充。
啟動時間更久
更多的對象需要更久的時間才能將它們從磁盤加載到應用中。
原文轉自:http://www.infoq.com/cn/articles/42-monster-problems