運維告訴我CPU飆升300%,爲什麼我的程序上線就奔潰了

線上服務CPU飆升的一次經歷

前言

  • 功能開發完成僅僅是項目週期中的第一步,一個完美的項目是在運行期體現的
  • 今天我們就來看看筆者之前遇到的一個問題CPU飆升的問題。 代碼層面從功能上看沒有任何問題但是投入使用後卻讓我頭大

問題描述

系統上點擊數據錄入功能在全局監控中會受到相關消息的通知。此時服務器CPU飆升300%

問題定位

  • 首先我們先梳理下Websocket的數據發送的簡單原理示意圖。往往定位問題得清楚我們的邏輯是什麼
  • 當一個客戶端啓動時除了和Websocket建立連接之外,我們還需要向Websocket服務註冊當前客戶端需要哪些接口的實時數據
  • 我在代碼內部是通過一個Map來存儲這些接口簽名信息的。然後客戶註冊時候將這些接口和客戶端綁定在一起
  • 當我們監聽程序堅挺到數據變動就會對綁定到相關接口的客戶端發送最新數據

業務定位

  • 業務上很好定位,問題就是出現在我們的監聽程序中。當監聽到數據給websocket客戶端發送訂閱的最新變動接口時就會出現CPU飆升。持續時間還很長,稍等一會就會降下來
  • 這很明顯是我們推送消息的時候出現了問題

隔離業務看本質

  • 作爲一個合格的程序員呢,必須擺脫業務纔能有所收穫 。業務是我們代碼的外殼所有的問題基本上都是我們本質的問題。我們線上使用用戶1W內。在這種的併發場景下應該是不會出問題的。現在出了問題肯定我們的程序邏輯有缺陷
  • 上面是我們的發送消息的代碼。代碼也很簡單。先獲取所有符合發送條件的客戶端 。然後通過客戶端內部提供的sendMessage方法進行推送。
  • 但是這個時候的message 是我們的接口信息。在內部會基於客戶端保存的方法簽名進行反射調用從而獲取最新數據。在推送給客戶端的
  • 在上面的代碼中核心的是WebsocketManager.messageParse 。這段是獲取消息然後發送。裏面獲取消息是基於resultful格式解析的
  • 這個方法內部我們有內置了我們的四種解析方式。這裏我們只需要關心RequestMappingMessageParseHandlerImpl 這個協議。
  • 關於我們內部的協議這裏也不需要太在意。這是我們自己的一個設計。根據上面的圖示我們也能看的出來裏面RequestMappingMessageParseHandlerImpl 是核心

產生原因

  • 上面我們簡單的梳理了下代碼的邏輯。
  • 仔細分析下我們是遍歷所有客戶端然後在反射調用接口數據進行返回的。實際上在消息推送時我們沒必要在每個客戶端內部調用數據。我們完全可以先調用數據然後在遍歷客戶端進行發送。
  • 這也是導致CPU過高的問題。我們1W個用戶同事在線的可能有5000+ 。 那麼我們需要5000次以上的反射着肯定是喫不消的。這也是爲什麼本文開頭說功能正常不代表業務正常。

解決方案

  • 這就是量變引起質變。在多客戶的情況下我們的設計弊端就暴露出來。這裏也是筆者自己給自己挖坑。既然找到問題我們就好解決了。下面我們對代碼做了一下改動
  • 我將數據緩存起來。因爲在同一批次推送時本來也應該保證數據一致性。而且我們系統對數據實時性也是可以接受一定時間延遲的。我在這裏又加上緩存這樣就解決了我們循環的問題

  • 經過測試本次改動在CPU上大概優化了100倍。

總結

  • 功能開發完成僅僅代表功能的實驗沒有問題
  • 單用戶和多用戶完全是兩種不同的用戶形態。我們功能設計初期就應該儘量考慮數據量的問題
  • 唯一做的好的地方是我通過責任鏈模式將數據解析隔離出來。否則這樣的問題定位將會更加麻煩

作者: zxhtom
鏈接:https://juejin.cn/post/6960795554406367269
來源:juejin

有時候一個小小的問題就會引起很大的波動現象,那麼處理起來也是非常的痛楚,只有找到合適的方法,這次筆者自己給自己挖坑,在這裏做了一下記錄。特別是在高併發到的時候,小問題會帶來更大的麻煩。

技術github學習地址:https://github.com/codeGoogler/JavaCodeHub

程序員編程書籍:https://github.com/codeGoogler/ProgramBooks

關於如何學習Java,一方面需要不斷的去學習,把基礎知識學紮實,另一方面也要認識到java的學習不能僅僅靠理論,更多的是靠實操,所以要多練習多做項目,在實踐中學習纔是最好的學習方法。很多人剛開始不知道怎麼去學習,這裏我將一些重要的技術文章整理到了github上開源項目上,希望能給大家帶來一些幫助,項目是:JavaCodeHub

另外,還整理了一些針對於程序員的編程書籍項目,都放到了github上面,項目爲:ProgramBooks 需要的話可以自取。地址:https://github.com/codeGoogler/ProgramBooks

如果github訪問太慢?我同時也把去放到了碼雲上面ProgramBooks

最後,照舊安利一波我們的公號:「終端研發部」,目前每天都會推薦一篇優質的技術相關的文章,主要分享java相關的技術與面試技巧,我們的目標是: 知道是什麼,爲什麼,打好基礎,做好每一點!這個主創技術公衆號超級值得大家關注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章