JVM從入門到精通(七):GC常用參數,Method Area,JVM調優案例分析

GC常用參數

  • -Xmn -Xms -Xmx -Xss
    年輕代 最小堆 最大堆 棧空間
  • -XX:+UseTLAB
    使用TLAB,默認打開
  • -XX:+PrintTLAB
    打印TLAB的使用情況
  • -XX:TLABSize
    設置TLAB大小
  • -XX:+DisableExplictGC
    System.gc()不管用 ,FGC
  • -XX:+PrintGC
  • -XX:+PrintGCDetails
  • -XX:+PrintHeapAtGC
  • -XX:+PrintGCTimeStamps
  • -XX:+PrintGCApplicationConcurrentTime (低)
    打印應用程序時間
  • -XX:+PrintGCApplicationStoppedTime (低)
    打印暫停時長
  • -XX:+PrintReferenceGC (重要性低)
    記錄回收了多少種不同引用類型的引用
  • -verbose:class
    類加載詳細過程
  • -XX:+PrintVMOptions
  • -XX:+PrintFlagsFinal -XX:+PrintFlagsInitial
    必須會用
  • -Xloggc:opt/log/gc.log
  • -XX:MaxTenuringThreshold
    升代年齡,最大值15
  • 鎖自旋次數 -XX:PreBlockSpin 熱點代碼檢測參數-XX:CompileThreshold 逃逸分析 標量替換 …
    這些不建議設置

JVM調優第一步,瞭解JVM常用命令行參數

  • JVM的命令行參數參考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

  • HotSpot參數分類

    標準: - 開頭,所有的HotSpot都支持

    非標準:-X 開頭,特定版本HotSpot支持特定命令

    不穩定:-XX 開頭,下個版本可能取消

    java -version

    java -X

試驗用程序:

import java.util.List;
import java.util.LinkedList;

public class HelloGC {
  public static void main(String[] args) {
    System.out.println("HelloGC!");
    List list = new LinkedList();
    for(;;) {
      byte[] b = new byte[1024*1024];
      list.add(b);
    }
  }
}

查看默認參數
默認參數查看GC詳細信息
在這裏插入圖片描述

一條GC信息的詳細信息如下:
在這裏插入圖片描述

關於上圖中的Times含義:在linux中的times代表:

在這裏插入圖片描述

Heap Dump的含義

eden space 5632K, 94% used [0x00000000ff980000,0x00000000ffeb3e28,0x00000000fff00000)
                            後面的內存地址指的是,起始地址,使用空間結束地址,整體空間結束地址

在這裏插入圖片描述

調優實戰

在這裏插入圖片描述

調優前的基礎概念:
  1. 吞吐量:用戶代碼時間 /(用戶代碼執行時間 + 垃圾回收時間)
  2. 響應時間:STW越短,響應時間越好

所謂調優,首先確定,追求啥?吞吐量優先,還是響應時間優先?還是在滿足一定的響應時間的情況下,要求達到多大的吞吐量…

問題:

科學計算,吞吐量。數據挖掘,thrput。吞吐量優先的一般:(PS + PO)
響應時間:網站 GUI API (1.8 G1)

什麼是調優?

  1. 根據需求進行JVM規劃和預調優
  2. 優化運行JVM運行環境(慢,卡頓)
  3. 解決JVM運行過程中出現的各種問題(不完全等同於解決OOM的問題,因爲前面兩項也很重要)

併發:

  • QPS
  • TPS
    淘寶雙11併發歷年最高54萬,據說12306併發比淘寶更高,號稱上百萬

調優,從規劃開始

  • 調優,從業務場景開始,沒有業務場景的調優都是耍流氓

  • 無監控(壓力測試,能看到結果),不調優(可以調整業務邏輯)

  • 步驟:

    1. 熟悉業務場景(沒有最好的垃圾回收器,只有最合適的垃圾回收器)
      1. 響應時間、停頓時間 [CMS G1 ZGC] (需要給用戶作響應)
      2. 吞吐量 = 用戶時間 /( 用戶時間 + GC時間) [PS]
    2. 選擇回收器組合
    3. 計算內存需求(沒有一定之規,是經驗值。 1.5G -> 16G,突然卡頓了,爲啥?)
    4. 選定CPU(預算能買到的,當然是越高越好,CPU多核,可以多線程運行呀)
    5. 設定年代大小、升級年齡
    6. 設定日誌參數,這是Java虛擬機的參數,也可以在Tomcat裏面配置,貌似是在叫catalinaoptions裏面指定java日誌的參數。
      1. -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
        5個日誌文件,循環產生。生產環境中的日誌參數一般這麼設置。
        %t是生成時間的意思。
        在這裏插入圖片描述
      2. 或者每天產生一個日誌文件
    7. 觀察日誌情況

如何根據需求進行JVM規劃和預調優?

有人要問你,你應該選用多大的內存?什麼樣的垃圾回收器組合?你怎麼回答?

  • 案例1:垂直電商,最高每日百萬訂單,處理訂單系統需要什麼樣的服務器配置?

    這個問題比較業餘,因爲很多不同的服務器配置都能支撐(1.5G 16G 都有可能啊)

    我們做一個假設吧,1小時360000個訂單。集中時間段, 100個訂單/秒,(找一小時內的高峯期,可能是1000訂單/秒)。我們就要找到這個最高峯的時間,保證你的架構能夠承接的住

    大多數情況下,是靠經驗值,然後做壓測。

    如果非要計算的話,你預估一下,一個訂單對象產生需要多少內存?512K * 1000 = 500M內

    專業一點的問法:要求響應時間在多少時間的情況下,比如100ms,我們去挑一個市面上性價比比較高的服務器,做壓測去測試,再不行加內存,再不行,就上雲服務器…
    這樣說就OK了

  • 案例2:12306遭遇春節大規模搶票應該如何支撐?(這個是架構上的一個設計,和調優關係不大)

    12306應該是中國併發量最大的秒殺網站:號稱併發量最高100W

    架構模型:CDN -> LVS -> NGINX -> 業務系統 -> 100臺機器,每臺機器1W併發(單機10K問題),目前這個問題已解決,主要是用redis
    .

    業務流程:普通電商訂單 -> 下單 ->訂單系統(IO)減庫存 ->生成訂單,等待用戶付款

    12306的一種可能的模型,是異步來進行的: 下單 -> 減庫存 和 訂單(redis kafka) 同時異步進行 ->等付款,付完款,持久化到Hbase, MySQL等等
    .
    減庫存最後還會把壓力壓到一臺服務器,怎麼辦?

    可以做分佈式本地庫存 + 單獨服務器做庫存均衡

    大流量的處理方法:分而治之,每臺機器只減自己機器上有的庫存
    流量傾斜的問題怎麼解決?比如有的機器上已經沒庫存了,有的機器上還剩很多?
    這時候你還需要一臺單獨的服務器,去做所有服務器的平衡,如果某臺服務器沒庫存了,從別的機器上挪一些過去。

  • 怎麼得到一個事務會消耗多少內存?
    1、弄臺機器,看能承受多少TPS?是不是達到目標?擴容或調優,讓它達到
    2、用壓測來確定

優化環境

  1. 這個可以稍微改一下寫進簡歷中
    有一個50萬PV的文檔資料類網站(從磁盤提取文檔到內存)原服務器32位,1.5G
    的堆,用戶反饋網站比較緩慢。因此公司決定升級,新的服務器爲64位,16G的堆內存,結果用戶反饋卡頓十分嚴重,反而比以前效率更低了!
    1. 爲什麼原網站慢?
      因爲很多用戶瀏覽數據,很多用戶瀏覽導致很多數據Load到內存,產生了很多文檔對應的Java包裝對象(而不是文檔對象,文檔本身可以走Nginx)。內存不足,頻繁GC,STW長,響應時間變慢
    2. 爲什麼會更卡頓
      內存越大,FGC時間越長
    3. 咋辦
      PS 換成 PN + CMS,或者 G1
      或者業務上的調整,文檔不走JVM
  2. 系統CPU經常100%,如何調優?(面試高頻)
    這樣回答:推理過程是:CPU100%,那麼一定有線程在佔用系統資源,所以
    1. 找出哪個進程cpu高(top命令)
    2. 該進程中的哪個線程cpu高(top -Hp)
    3. 如果是java程序,導出該線程的堆棧 (jstack)
    4. 查找哪個方法(棧幀)消耗時間,哪個方法調用的哪個方法 (jstack),然後去看這個方法的代碼
    5. 工作線程佔比高 | 垃圾回收線程佔比高
  3. 系統內存飆高,如何查找問題?(面試高頻)
    1. 導出堆內存 (jmap)
    2. 分析 (jhat jvisualvm mat jprofiler … )
  4. 如何監控JVM
    1. jstat jvisualvm jprofiler arthas top…
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章