'一次生產 CPU 100% 排查優化實踐'

中央處理器 Java 程序員聖經 2019-07-28
"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


一次生產 CPU 100% 排查優化實踐


同時查閱到其他的等待策略 BlockingWaitStrategy (也是默認的策略),它使用的是鎖的機制,對 CPU 的使用率不高。

於是在和之前同樣的條件下將等待策略換為 BlockingWaitStrategy。

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


一次生產 CPU 100% 排查優化實踐


同時查閱到其他的等待策略 BlockingWaitStrategy (也是默認的策略),它使用的是鎖的機制,對 CPU 的使用率不高。

於是在和之前同樣的條件下將等待策略換為 BlockingWaitStrategy。

一次生產 CPU 100% 排查優化實踐




"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


一次生產 CPU 100% 排查優化實踐


同時查閱到其他的等待策略 BlockingWaitStrategy (也是默認的策略),它使用的是鎖的機制,對 CPU 的使用率不高。

於是在和之前同樣的條件下將等待策略換為 BlockingWaitStrategy。

一次生產 CPU 100% 排查優化實踐




一次生產 CPU 100% 排查優化實踐


"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


一次生產 CPU 100% 排查優化實踐


同時查閱到其他的等待策略 BlockingWaitStrategy (也是默認的策略),它使用的是鎖的機制,對 CPU 的使用率不高。

於是在和之前同樣的條件下將等待策略換為 BlockingWaitStrategy。

一次生產 CPU 100% 排查優化實踐




一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


和剛才的 CPU 對比會發現到後面使用率的會有明顯的降低;同時 dump 線程後會發現大部分線程都處於 waiting 狀態。

優化解決

看樣子將等待策略換為 BlockingWaitStrategy 可以減緩 CPU 的使用,

但留意到官方對 YieldingWaitStrategy 的描述裡談道:當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。

而現有的使用場景很明顯消費線程數已經大大的超過了核心 CPU 數了,因為我的使用方式是一個 Disruptor隊列一個消費者,所以我將隊列調整為只有 1 個再試試(策略依然是 YieldingWaitStrategy)。

"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


一次生產 CPU 100% 排查優化實踐


同時查閱到其他的等待策略 BlockingWaitStrategy (也是默認的策略),它使用的是鎖的機制,對 CPU 的使用率不高。

於是在和之前同樣的條件下將等待策略換為 BlockingWaitStrategy。

一次生產 CPU 100% 排查優化實踐




一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


和剛才的 CPU 對比會發現到後面使用率的會有明顯的降低;同時 dump 線程後會發現大部分線程都處於 waiting 狀態。

優化解決

看樣子將等待策略換為 BlockingWaitStrategy 可以減緩 CPU 的使用,

但留意到官方對 YieldingWaitStrategy 的描述裡談道:當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。

而現有的使用場景很明顯消費線程數已經大大的超過了核心 CPU 數了,因為我的使用方式是一個 Disruptor隊列一個消費者,所以我將隊列調整為只有 1 個再試試(策略依然是 YieldingWaitStrategy)。

一次生產 CPU 100% 排查優化實踐


"
來源:公眾號crossoverJie 
作者:crossoverJie

前言

最近又收到了運維報警:表示有些服務器負載非常高,讓我們定位問題。

還真是想什麼來什麼,前些天還故意把某些服務器的負載提高(沒錯,老闆讓我寫個 BUG!),不過還好是不同的環境互相沒有影響。

定位問題

拿到問題後首先去服務器上看了看,發現運行的只有我們的 Java 應用。於是先用 ps 命令拿到了應用的 PID。

接著使用 ps-Hppid 將這個進程的線程顯示出來。輸入大寫的 P 可以將線程按照 CPU 使用比例排序,於是得到以下結果。

一次生產 CPU 100% 排查優化實踐


果然某些線程的 CPU 使用率非常高。

為了方便定位問題我立馬使用 jstack pid>pid.log 將線程棧 dump 到日誌文件中。

我在上面 100% 的線程中隨機選了一個 pid=194283 轉換為 16 進制(2f6eb)後在線程快照中查詢:

因為線程快照中線程 ID 都是16進制存放。


一次生產 CPU 100% 排查優化實踐


發現這是 Disruptor 的一個堆棧,前段時間正好解決過一個由於 Disruptor 隊列引起的一次 OOM:強如 Disruptor 也發生內存溢出?

沒想到又來一出。

為了更加直觀的查看線程的狀態信息,我將快照信息上傳到專門分析的平臺上。

http://fastthread.io/

一次生產 CPU 100% 排查優化實踐


其中有一項菜單展示了所有消耗 CPU 的線程,我仔細看了下發現幾乎都是和上面的堆棧一樣。

也就是說都是 Disruptor 隊列的堆棧,同時都在執行 java.lang.Thread.yield 函數。

眾所周知 yield 函數會讓當前線程讓出 CPU 資源,再讓其他線程來競爭。

根據剛才的線程快照發現處於 RUNNABLE 狀態並且都在執行 yield 函數的線程大概有 30幾個。

因此初步判斷為大量線程執行 yield 函數之後互相競爭導致 CPU 使用率增高,而通過對堆棧發現是和使用 Disruptor 有關。

解決問題

而後我查看了代碼,發現是根據每一個業務場景在內部都會使用 2 個 Disruptor 隊列來解耦。

假設現在有 7 個業務類型,那就等於是創建 2*7=14 個 Disruptor 隊列,同時每個隊列有一個消費者,也就是總共有 14 個消費者(生產環境更多)。

同時發現配置的消費等待策略為 YieldingWaitStrategy 這種等待策略確實會執行 yield 來讓出 CPU。

代碼如下:

一次生產 CPU 100% 排查優化實踐


初步看來和這個等待策略有很大的關係。


本地模擬

為了驗證,我在本地創建了 15 個 Disruptor 隊列同時結合監控觀察 CPU 的使用情況。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


創建了 15 個 Disruptor 隊列,同時每個隊列都用線程池來往 Disruptor隊列 裡面發送 100W 條數據。

消費程序僅僅只是打印一下。

一次生產 CPU 100% 排查優化實踐


跑了一段時間發現 CPU 使用率確實很高。



一次生產 CPU 100% 排查優化實踐


同時 dump 線程發現和生產的現象也是一致的:消費線程都處於 RUNNABLE 狀態,同時都在執行 yield。

通過查詢 Disruptor 官方文檔發現:

一次生產 CPU 100% 排查優化實踐


YieldingWaitStrategy 是一種充分壓榨 CPU 的策略,使用 自旋+yield的方式來提高性能。當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。


一次生產 CPU 100% 排查優化實踐


同時查閱到其他的等待策略 BlockingWaitStrategy (也是默認的策略),它使用的是鎖的機制,對 CPU 的使用率不高。

於是在和之前同樣的條件下將等待策略換為 BlockingWaitStrategy。

一次生產 CPU 100% 排查優化實踐




一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


和剛才的 CPU 對比會發現到後面使用率的會有明顯的降低;同時 dump 線程後會發現大部分線程都處於 waiting 狀態。

優化解決

看樣子將等待策略換為 BlockingWaitStrategy 可以減緩 CPU 的使用,

但留意到官方對 YieldingWaitStrategy 的描述裡談道:當消費線程(Event Handler threads)的數量小於 CPU 核心數時推薦使用該策略。

而現有的使用場景很明顯消費線程數已經大大的超過了核心 CPU 數了,因為我的使用方式是一個 Disruptor隊列一個消費者,所以我將隊列調整為只有 1 個再試試(策略依然是 YieldingWaitStrategy)。

一次生產 CPU 100% 排查優化實踐


一次生產 CPU 100% 排查優化實踐


跑了一分鐘,發現 CPU 的使用率一直都比較平穩而且不高。

總結

所以排查到此可以有一個結論了,想要根本解決這個問題需要將我們現有的業務拆分;現在是一個應用裡同時處理了 N 個業務,每個業務都會使用好幾個 Disruptor 隊列。

由於是在一臺服務器上運行,所以 CPU 資源都是共享的,這就會導致 CPU 的使用率居高不下。

所以我們的調整方式如下:

  • 為了快速緩解這個問題,先將等待策略換為 BlockingWaitStrategy,可以有效降低 CPU 的使用率(業務上也還能接受)。
  • 第二步就需要將應用拆分(上文模擬的一個 Disruptor 隊列),一個應用處理一種業務類型;然後分別單獨部署,這樣也可以互相隔離互不影響。

當然還有其他的一些優化,因為這也是一個老系統了,這次 dump 線程居然發現創建了 800+ 的線程。

創建線程池的方式也是核心線程數、最大線程數是一樣的,導致一些空閒的線程也得不到回收;這樣會有很多無意義的資源消耗。

所以也會結合業務將創建線程池的方式調整一下,將線程數降下來,儘量的物盡其用。

本文的演示代碼已上傳至 GitHub:

https://github.com/crossoverJie/JCSprout

"

相關推薦

推薦中...