kafka訊息堆積且CPU過高代碼優化
直接部署已有的代碼程式到線上服務器,發現CPU立馬升高500%左右,立馬停掉服務并看源代碼排查問題,翻看代碼,發現通過多執行緒消費
kafka訊息,根據對多執行緒的了解,立馬從以下方面排查問題:
1.多執行緒必須保證單例模式,才能保證多執行緒安全問題
2.共享資源的競爭問題,有共享變數必須加鎖(synchronized)同步
3.代碼性能優化(jvm和資料庫兩個方面進行優化)
逐個分析排查:
對于第一個執行緒安全問題,開啟多個執行緒來分別獲取單例,然后列印它們所獲取到的單例的hashCode值,
若它們獲取的單例是相同的(該單例模式的實作是執行緒安全的),那么它們的hashCode值一定完全一致;若它們的hashCode值不完全一致,
那么獲取的單例必定不是同一個,即該單例模式的實作不是執行緒安全的,是多例的,通過本地測驗列印發現hashCode值不一樣,立馬修改代碼,
我使用內部類實作執行緒安全的懶漢式單例,這種方式是一種效率比較高的做法(注意:使用雙重檢測同步延遲加載去創建單例的做法是一個非常優秀的做法,
其不但保證了單例,而且切實提高了程式運行效率),
保證單例模式代碼截圖:
對于第二個資源共享的問題,有成員變數的可以通過加volatile關鍵字,變數的可見性,
對于第三個代碼性能問題解決思路:
資料庫層面:單條資料插入耗資源,每次插入資料都會預編譯一次,可以改成批量插入,
jvm層面:在知道集合大小的情況下可以給集合一個初始化大小,避免多次擴容好資源,記憶體模型
初次優化后部署到線上,發現CPU在100%左右,CPU有所下降,但是還是偏高,繼續二次優化,
第二次優化,我直接本地直接注釋掉判斷經緯度是否邊界區域那部分代碼(判斷代碼見下圖),for回圈是每次都要Double.parseDouble()方法轉換耗時,有個時間復雜度,找到問題點,
代碼性能不足,經過請教后,將for回圈中的代碼double轉換在外面直接處理好,for回圈直接get取值就是double型別,
優化前代碼截圖:
優化后代碼截圖:
二次線上部署,發現CPU在30%左右,達到目標期望,
總結:用到了kafka技術和多執行緒,由于對kafka不是很了解,僅從多執行緒及jvm和資料庫層面優化,由于執行緒在CPU上運行,而CPU是搶占式的(時間片),因此記憶體模型中有個程式計數器,專門記住行號,
當運行在此執行緒中的CPU資源被其他執行緒搶走后,我們的程式計數器就會記住這個行號,等此執行緒搶到CPU資源后繼續從這個行號開始運行,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/263771.html
標籤:其他
