記一次高併發場景下.net監控程序數據上報的性能調優

    最近在和小夥伴們作充電與通訊程序的架構遷移。遷移前的架構是,通訊程序負責接收來自充電集控設備的數據實時數據,經過Thrift調用後端的充電服務,充電服務收到響應後放到進程的Queue中,而後在管理線程的調度下,啓動多線程進程數據處理。後端

Image

    隨着業務規模的不斷擴大和對系統可用性的逐步提升。如今這個架構存在不少的問題,好比:緩存

1.充電服務重啓,可能會丟數據。多線程

2.充電服務重啓會波及影響通訊服務。架構

3.充電服務與通訊服務面對的需求和變化是不同,強依賴的架構帶來不少的問題。併發

    爲了解決上述的這些問題,項目組決定藉助Kafka對程序進行改造 。整體思路是,通訊服務收到數據後,把數據存儲到kafka,而後經過一個異步任務處理框架實時消費Kafka數據,並調用業務插件處理。框架

    經過上面思路咱們能夠看到,系統總體架構僅是引入了一個MQ中間件,業務邏輯並無發生本質的變化。可是在實際的壓測中,卻發現新架構下的程序性能比原來要慢不少。順便說一下,壓測場景是模擬10萬充電終端離網上下線,短期內會生成大約32萬的消息量,遙信:10萬,遙測:10萬,電量10萬,其餘:2萬。異步

    經過ANTS分析相關進程,發現MonitorDataUploader.AddToLocalCache方法佔用了78%左右的CPU。此方法不是業務方法,是爲了監控程序的運行狀況而加入的埋點監控。經過進一步分析看,在30多萬消息量下,會產生約1000萬甚至更高的監控消息。在如此高的併發下,這部分程序存在很嚴重的性能問題,致使系統的資源佔用很高,系統運行變慢。函數

Image

    OK。既然問題已經清楚,那就開始優化吧。雖然能夠把監控埋點屏蔽,臨時解決程序的性能問題。可是,這對一個互聯網應用來講是要不得的。沒有監控,系統的運行健康情況就一無所知,這對一個SLA要求99.95%的系統來講,是不現實的。因此,必須全力優化監控程序在上報海量監控日誌上的性能問題。性能

    爲了便於驗證問題,寫了一個模擬程序.經過模擬程序,很容易的再現了CPU佔用很高的狀況。測試

Image

Image

    代碼實現中,監控消息的存儲是經過BlockingCollection存儲的,而且設置了Collection大小爲1000萬。

var cache = new BlockingCollection<MonitorData>(boundedCapacity);

Image

    經過閱讀BlockingCollection 的說明,能夠看到空構造函數能夠不設置Collection的上限。看到這個解釋,懷疑是限制了上線的Collection存在性能問題。與是把代碼中對BlockingCollection 的構造改爲空構造,再次測試。測試結果大出意料,性能表現有了很是好的提高。

Image

    爲了進一步驗證問題,把對BlockingCollection 的構造改了限制大小,並設置上線爲1個億。測試時消息總量爲5000萬,驗證一下是不是BlockingCollection 達到上限後,引發的嚴重性能問題。經過測試數據看,CPU消耗與不限制時基本一致。經過此能夠肯定,BlockingCollection 在設置了容量上限後,若是消息超過容量,性能將會很是差。

Image

    經過上面的調優,在發送5000萬監控消息的狀況下,程序的CPU在60% 左右持續30s左右。雖然性能有所改善,可是還不是很盡如人意。 有沒有更好的解決方案呢?經過不算的思考和嘗試,終於找到了一個更好的解決方案:基於雙緩存+線程級多桶式Collection。此種模式下性能表現以下,CPU平均在30%左右,持續時間在15s左右。性能又有近一倍的提高。具體實現方案下次再分享。

Image

相關文章
相關標籤/搜索