之前產品線上發生過若干次因為tomcat連接池被耗盡而導致宕機的故障,而具體根源原因則各不盡相同。有因為調用和被調用的服務申請相同的分布式鎖而導致死鎖的,有因為發送內部或外部的JMS消息發生堵塞的,有因為某個存在性能問題的接口被較多調用導致的,還有某些超高頻接口沒有做好專門優化而導致的。。。
所有上述問題的本質解決,肯定是要針對各種問題根源,分別予以解決。解決死鎖問題,外部接口做好嚴格的訪問超時控制,非核心業務邏輯盡量異步處理,盡可能的通過增加cache來減少數據庫壓力等等。但除此之外,系統中任何一個業務點都可能拖垮整個系統,系統整體的脆弱程度值得深思。為什么瘸了腿的人會死?不,他應該還要能編程。
其實,這個問題的本質在于tomcat只有一個共享線程池,所有的業務請求都會分配給一個線程,直至請求處理完畢,線程才會被回收。任何一個長請求,都會長期侵占導致寶貴的tomcat連接池資源。這點其實在tomcat7上已經做了優化支持,tomcat7支持了異步處理。此特性將http線程池和業務service線程池做了分離,這樣一個IO等待的業務請求,只會侵占業務service線程池。但這沒有解決本質問題,因為雖然解決了http線程池的資源問題,但累積膨脹的業務service線程池,對jvm內存、cpu,數據庫等仍是一個威脅。壞孩子和調皮的孩子其實放到哪里都是問題,他們需要被好好管理。需要控制他們的發言次數,這樣哪些無辜的乖孩子才有機會發言,老師也才能聽到有意義的反饋。
那么,我們需要做什么呢?
1.我們需要做好資源隔離,防止任何一個業務功能消耗過多的連接池資源,甚至,在必要的時候,可以完全禁止這個問題業務功能。
2.業務功能的流量閾值或開關,能夠及時、動態的予以調整。
3.業務功能如果流量超限,可以定制的做異常處理。
解決問題一,我們設計了一個Aspect。它攔截了所有的業務功能請求,然后根據具體業務功能的流量閾值對請求進行控制。如果未超限,則放行,放行前增加計數,業務功能執行完成后回收計數;如果超限,則獲取相應的異常處理策略進行處理。主要包含了流量計數器,閾值管理器和異常處理器這3個部分。
框架簡圖如下:
處理流程圖如下:
解決問題二和三,即閾值和處理策略動態調整的問題。顯然,配置文件是不合適的,那意味著要做應用重啟。將配置信息保存到memcache中?那意味著每個業務請求都需要訪問至少2次網絡請求,這是不小的開銷。那看來,如果能將這些信息冗余在服務器節點的內存里會性能不錯,那內容如何獲取和更新呢?服務器節點應該初始化的時候從一個中心節點拉取配置,然后通過長連接的方式監聽在中心節點的配置變更時間,在發生變更新,從中心節點拉取相應新內容。中心節點最好還能是高可用的,高性能的,以及擁有良好的一致性。聽起來美好,要真開發起來可還真不簡單。幸運的是,牛人們早已為我們鋪好大路了,那就是Zookeeper!它從核心上完美地解決了我們的需求。不過,到這里,其實還不夠。我們的配置需要能持久保存,如果zookeeper真的掛了怎么辦?最好有個漂亮的配置管理界面,你會喜歡在一個黑乎乎的界面上瘋狂的敲打鍵盤嗎,那是黑客帝國的劇情。此外,最好還能有非常方便的客戶端編程接口API,不,甚至不要給我任何API,我添加幾個注解就一切搞定最好,好吧,我們程序員就是懶!~
讓我們來看看開源的配置管理服務框架吧,diamond(阿里),disconf(百度),qconf(奇虎360)。隨都是師出名門,但由于研發年代、測重點都會略有不同。先看看Diamond和Disconf的對比:
推拉模型和編程模型上,disconf都更加符合我們的需求。可能后來者好是因為能站在前面巨人的肩膀上。下圖的disconf的核心流程圖:
更完整的的關于disconf的信息請大家看:
https://github.com/knightliao/disconf/wiki/%E5%88%86%E5%B8%83%E5%BC%8F%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0Disconf 。
至于qconf,基本特性同disconf差不多,當相關文檔比較少,也沒有特別詳細,也就沒有考慮了。感興趣的同學可以看下:
https://github.com/Qihoo360/QConf/blob/master/README_ZH.md ,和http://v.youku.com/v_show/id_XOTI1NTI2ODI0.html(視頻教程)
現在增加到并發攔截監控到公司監控系統。下圖是一個某段時間內的監控結果。
本文章為作者原創
🈲禁止🈲
其他公眾賬號轉載,若有轉載,請標明出處
文章列表