CPU負載120%
阿新 • • 發佈:2018-12-08
CPU負載120%
概述
- 背景:生產環境服務響應緩慢,出現RPC介面超時
- 排查:
- 服務雙機部署,登入兩臺日誌機器,登入兩臺部署機器
- 檢視部署機器服務負載,
- top 檢視,同一臺機器上部署三個服務
- 其中A服務,CPU 120%
- 檢視剛出現 CPU 負載過高的時間,運維提供監控日誌顯示上午,檢視日誌,這期間發生的疑似操作
- 定位問題,近期優化的一個批量初始化資料到快取中的功能被觸發了多次,且該功能為了快速響應,建立執行緒池,核心執行緒數10,最大執行緒數20,使用者進行了多次點選,每一次的資料請求量都很大,上一次操作沒有完成,下一次的請求即開始了
堆疊資訊1
- 檢視負載高的程序
- 進入部署伺服器
- top , 按 P ,記錄CPU負載高的程序編號
- 檢視負載高的程序
- top -Ph pid 程序編號,按P ,記錄CPU負載高的執行緒編號
- 執行緒編號轉為十六進位制,通過windows提供的科學計算器
- 檢視堆疊資訊
- jstack pid | grep “0xtid”
異常資訊
java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000073e4aa000> (a java.util.concurrent.SynchronousQueue$TransferStack) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458) at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359) at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745)
private static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(10, 20, 300, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1000), new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true); return t; } }, new ThreadPoolExecutor.CallerRunsPolicy());
根據堆疊資訊配置原始碼跟蹤問題原因定位於
伺服器CPU數量 2 個,A服務中存在不同的多個執行緒池,功能執行過程中交叉多個執行緒池的執行,每個執行緒在規定的時間內都沒有得到反饋,每個執行緒都在執行SQL查詢,沒有得到資料響應,執行緒掛起;不斷建立新的執行緒執行掛起的任務,發生資源爭搶,導致CPU負載過高
異常反思
- 執行緒池使用要根據伺服器效能合理設定,建立數量過多會導致CPU負載過高