相關閱讀 |
>>> 技術話題—商業文明的嶄新時代 >>> | 簡體 傳統 |
文/馬德奎
人們總是錯誤地使用隊列,最壞的情況是用它解決“超載(overload)”問題。Fred Hebert 是《Learn You Some Erlang for Great Good!》一書的作者。在這本 Erlang 入門書籍中,他結合生動的插圖、恰當的實例以淺顯易懂的方式講解了技術問題。近日,他以同樣的方式闡釋了為什么“隊列不能解決超載”。
他將系統比作一個洗手池,如下所示:
在正常的操作下,數據只從左側流入,出口可以處理所有數據。但在一些重大活動期間,比如圣誕節,可能會出現如下情況:
數據從左右兩側同時流入系統。如果數據輸入越來越快,那么出口就可能會無法及時處理所有數據。這時,人們通常會考慮增加一個隊列緩沖區(如上圖的水槽)存儲臨時數據。但不管隊列多大,持續的超載都會導致如下情況的發生:
隊列滿了,系統崩潰。這時候,開發人員會查看堆棧跟蹤、隊列、數據庫查詢以及調用的 API。但經過各種優化,甚至更換更大的服務器后,系統仍然無法承受這種持續的超載,因為瓶頸在出口(下圖中紅箭頭所示的位置):
該瓶頸可能是數據庫,可能是磁盤、帶寬或 CPU。不消除這種瓶頸,任何優化都是徒勞。所以此時,開發人員應該做的是阻塞輸入,即“反壓(back-pressure)”或者丟棄數據,即“卸載(load-shedding)”。可能有人會認為,反壓會招致用戶的不滿。但實際上,即使不主動反壓,當系統負載達到一定程度后,速度也會降低,甚至崩潰。所以,雖然反壓會降低用戶的輸入速度,但卻可以保證系統的運行。另外,引入隊列作為一種優化機制會違背端到端原則。因此,開發人員應該設置更多允許超時的地方,提供故障檢測方法,并將其反饋給用戶。
如上圖所示,開發人員可以在識別出系統瓶頸后設置相應的反壓機制,避免數據流入過快。而依據檢查點的不同,開發人員可以對延遲和吞吐量實現不同層次的優化。
借助反壓或卸載,開發人員可以獲得以下好處:
總之,如果 API 設計考慮了端到端原則和冪等性,那么反壓或卸載對調用者而言通常不會成為問題,因為它們可以安全地重試請求。
感謝郭蕾對本文的審校。
InfoQ 2015-05-19 00:39:03
稱謂:
内容: