架構師的能力源于你的信任
普瑞特有幸爭取到了為一個架構師的架構師工作的機會。這位架構師的架構師能夠設計出功能更強,性能更佳,比任何其它設計更優的系統。任何出自這個家伙之手的設計或編碼,跟其它任何人設計的相似的組件相比,跟任何地方已經有了的相似系統相比,都會具有更全的功能,更強的能力,更堅不可破的性能。無人能企及。
回溯到我們要講的這個系統的設計之初,架構師的架構師命令說這個系統的通信機制將采用JMS消息傳送。并且,要準備兩個隊列;一個傳送普通消息,一個傳送高優先級消息。其它應用軟件對這個新系統的服務的要求是,普通優先級的消息,系統收集后批量處理,高優先級的消息在用戶間直接傳送。這個兩個消息隊列的活動情況都受應用軟件的監控,但高優先級的消息能跳到隊列的最前面以達到最快的響應。還有,由于這個系統將要去替代的系統是長久以來以bug多多和穩定性極差而聞名,所以,這些新系統必須要刀槍不入。它絕對不允許宕機。
當普瑞特接受培訓了解這個系統時,他問架構師的架構師,當如果有這樣或那樣的錯誤發生時,系統會做什么響應?
架構師的架構師高傲的宣稱,絕對不會有任何事情能導致系統宕機。沒有任何錯誤能阻擋它運行。沒有任何情況能使它失去控制。它是無可阻擋的。它會絕對可靠,直到最后一分鐘。你要相信我!
普瑞特明白這位架構師的架構師對自己深信不疑。然而,事情并不是總會按計劃運行。
一天,普瑞特接到一個負責監控這個系統運行的人的電話:“你們的這個系統的日志體積增長出現異常。你們的系統在過去24小時里產生了以前一個月才會有的體積量,系統負載上沒有特別的增長;請檢查一下。”
普瑞特登錄生產服務器,發現了一排排按序號排列的日志,每個日志文件都有20GB,全是這一天產生的!沒有任何編輯器能打開這樣大的文件。辦法只能是用grep搜尋里面的異常。異常多的如火山洶涌。看起來系統會每秒鐘吐出數百次異常事件和堆棧信息。用tail獲取日志尾部片段,顯示所有的異常都相同:“無法訪問隊列:隊列控制器似乎已經停止運行。”
不幸的是,隊列控制器并不認可這種說法;它很健康,并在處理著消息。
與此同時,客戶對系統性能的抱怨不斷升級。經理跑過來詢問怎么回事。耳朵在冒煙。眼睛在噴火。普瑞特感覺到死神正在上面盯著他。
進一步調查顯示,雖然有一部分應用的實例在不斷的出現并拋出大量的異常,但有些卻在順利的收發信息、處理數據。
深挖之后,普瑞特發現處理消息的外層代碼是這樣寫的:
- Connection conn; // injected via Spring
- Queue receiveQueueNormal; // injected via Spring
- Queue receiveQueuePriority; // injected via Spring
- ...
- Session session = conn.createSession(true,Session.SESSION_TRANSACTED);
- MessageConsumer consumerNormal = session.createConsumer(receiveQueueNormal);
- MessageConsumer consumerPriority = session.createConsumer(receiveQueuePriority);
- ...
- while (true) { // AA: This will never fail: trust me!
- try {
- Message msg = consumerPriority.receiveNoWait();
- if (msg == null) {
- msg = consumerNormal.receiveNoWait();
- if (msg == null) {
- continue;
- }
- }
- // process the message here
- } catch (Throwable t) {
- log.error("...",t);
- }
- }
進一步在隊列配置文件里發現問題:
- <policyEntry topic=">" producerFlowControl="true" memoryLimit="1mb">
當消息的體積很小或消息很少時,這段代碼會呼嘯的運行,它能每秒鐘檢查無數次隊列看有沒有消息可處理。
但隨著業務的增長,當消息的體積增長到某種程度,消息控制器就會耗盡內存,結果就會放棄一些消息,但并不是放棄所有的連接(可能是采用了自我保護模式)。這個系統——設計和開發都基于不會出現意外情況的假設——仍然在快速的最大限度的利用著CPU,但現在卻因為無法和隊列管理器取得聯系,每個循環都會拋出異常日志信息。
沒有重新獲取連接的代碼。沒有讓連續相同的日志錯誤信息做合并延遲輸出。沒有郵件發送給支持人員說“不好的事情發生了!
出自架構師的架構師的源代碼里只有一句孤單的注釋:”相信我!“
英文原文:Trust Me!





















