java性能調優實戰

  在項目壓測過程當中,發現系統佔用,上下文切換很是頻繁,在此記錄下調優過程,但願對後來人有所幫助。java

測試方法:模擬客戶端實際操做,向服務器高併發發送數據,查看服務器的負載狀況。linux

服務器基本配置以下服務器

 

1,基本性能監控工具 top

1) top 使用方式1   top

 

經過top命令,java應用負載極高,系統調用極高(系統調用43% ,而用戶調用只有35%),cpu的大部分資源都被系統消耗了,說明系統某部分存在極不合理的地方。網絡

2) top 使用2;輸入top後 按1,查看cpu各個核的使用狀況

 

這個圖說明了 cpu使用分佈狀況還不錯,即程序線程池配置目前沒有出現問題,若是出現單個cpu,或者幾個cpu 100%,其餘空閒的狀況,說明線程分配不合理,沒法充分利用cpu多核能力。多線程

3) top 使用 3,查看究竟是什麼線程在忙碌top -Hp 25994

 

若是你仔細觀察就會發現一個有趣的現象,那就是好多線程id就像新出的人民幣同樣,是連着號的,通常來講,他們屬於一組線程。併發

找到忙碌的線程,那麼如何才能映射到java應用中咱們本身定義的線程呢?步驟以下jvm

a. jstack 25994 >1  java線程dump出來高併發

b. 將上圖pid列的數字轉換成16進制 好比26157   16進製爲0x662d工具

c. more 1 。而後搜索662d性能

 

找到了,經過線程名字,能夠得出,當前網絡層目前比較忙碌。

注意:給線程起一個好名字很是重要,不然你刀磨的再快,命令玩兒的再溜,依然砍不到人。

2vmstat命令 執行vmstat 1 20查看大約20次數據

 

從這個圖上,咱們可以看出至少三個方面的問題

1) 內核調用 達到50%左右,很是高

2) 上下文切換過於頻繁,每秒達90000次左右

3) 調度隊列線程積壓  此刻的系統已經很是慢了。

3pidstat命令 

查看上下文切換(pidstat 命令屬於sysstat組件的內容,須要自行安裝

pidstat -wt -p 25994  1 10 查看10

 

第一列爲線程id

第二列爲主動上下文切換

第三列爲被動上下文切換

通常來講,咱們認爲,線程被動上下文切換是正常的,而主動切換多是發生了io、鎖等狀況。對於如此頻繁的上下文切換,咱們須要多dump幾回線程,看看如上的線程到底在作什麼,dump方法以及操做系統線程id如何映射到java線程,參見上文top -Hp命令。

查看 java線程dump文件,獲得以下有效數據

 

應用程序頻繁調用 netty writeAndFlush 方法,從調用棧中咱們看到:這個方法其實是執行了一個系統調用,用於喚醒selectable(多重複用)阻塞線程。

 

netty的讀寫線程在頻繁的與操做系統交互寫數據。

綜上,咱們大概獲得了兩個結論:

1,應用頻繁的調用nettywriteAndFlush方法,這可能會產生大量的系統調用.

2netty頻繁的與操做系統交互進行io操做。上文說過,io操做可能會致使線程主動切換上下文。

因而乎,兩個優化思路也呼之欲出,若是writeAndFlush方法會產出大量的中斷,那麼netty還有沒有提供其餘的方法?第二個問題,io操做太過頻繁,那麼可不能夠把消息稍微合併一下以減小io的頻繁度呢?(固然這種思路須要結合實際項目,咱們項目的特色是小包特別頻繁)。沿着這兩個思路,從新查看了netty相關部分的源碼,幸運的是找到了突破口,

 

 

這兩個方法天生就是一塊兒用的,write方法能夠先把數據記到內存中,等隨後的flush操做把內存中全部的數據一次刷新到操做系統中。這種操做徹底符合預期,即避免了系統調用,用完成了數據的 打包,美妙的是這種打包對應用而言是透明的。

調用改進策略

對於消息的發送,咱們封裝了統一接口,以下

 

這個接口被大量調用,分佈於應用的各個「角落」,改變每個調用顯然是不可能的。而且,應用層是沒法明確知道在什麼時候讓消息「等一會」再統一發送出去的。換句話說,就是在不改變現有調用的狀況下,將這種優化「神不知鬼不覺」的添加進去。根據咱們的線程分配策略,個人解決思路是在一次線程調用結束後統一發送本次調用全部消息。即將須要發送消息的Channel先存在ThreadLocal中,而後,統一操做代碼片斷以下

① 按線程存儲 channel集合

 

② 設置開關,有些線程不須要作合併

 

③ 發消息時,只須要把開啓這個功能的channel存起來便可。

 

④ 消息統一發送

 

有效代碼不超過20行,而後咱們看一下結果vmstat 1

 

爲方便觀察結果,我把上圖貼下來一塊兒對比

 

系統調用,上下文切換,調用隊列三項指標都有顯著的改善,cpu使用率提高了20%左右(觀察上圖的id列,下圖的空閒百分比爲10%左右,而上圖在30%左右)。

總結:操做系統自身提供的工具,有着無與倫比的威力,再結合jdk提供的幾個經常使用命令,如jstack(線程)、jmap(內存)、jstat(垃圾回收)等,可以幫助快速幫助咱們定位問題。通常來講,操做系統監控命令可以幫助咱們肯定,應用到底有沒有問題(諸如,cpu使用率、內存佔用狀況、網絡、磁盤、調度隊列等等),jdk工具可以進一步幫助咱們定位問題出如今哪(線程分配、jvm堆大小配置、等等)。

相關文章
相關標籤/搜索