JVM調優


1.了解JVM常用命令行參數

HotSpot參數分類

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

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

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

java -XX:+PrintFlagsFinal | grep xxx 找到對應的參數

java -XX:+PrintFlagsFinal -version |grep GC

參考鏈接:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

2.調優前的基礎概念

1.吞吐量:用戶代碼時間 /(用戶代碼執行時間 + 垃圾回收時間)。吞吐量優先的一般:(PS + PO)

2.響應時間:STW越短,響應時間越好。響應時間優先用G1

3.什么是調優

1.根據需求進行JVM規划和預調優

2.優化JVM運行環境(慢,卡頓)

3.解決JVM運行過程中出現的各種問題(OOM)

4.調優從規划開始

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

  • 無監控(壓力測試,能看到結果),不調優

  • 步驟

    1.熟悉業務場景(沒有最好的垃圾回收器,只有最合適的垃圾回收器)

    1.響應時間、停頓時間 [CMS G1 ZGC] (需要給用戶作響應)

    2.吞吐量 = 用戶時間 /( 用戶時間 + GC時間) [PS]

    2.選擇回收器組合

    3.計算內存需求(經驗值)

    4.選定CPU(越高越好)

    5.設定年代大小、升級年齡(一般不需要設置)

    6.設定日志參數

    1.-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause (gc日志文件路徑,循環打印,一共5個日志文件,每個文件大小20mb,打印gc詳細信息,發生gc的時間和原因)

    2.或者每天產生一個日志文件

    7.觀察日志情況

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

    很業余的問法

    這種情況一般要估算業務最高峰值(比如5000訂單/秒),根據最高峰值來估算系統資源,然后壓測

  • 案例2:12306遭遇春節大規模搶票應該如何支撐?

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

    CDN -> LVS -> NGINX -> 業務系統 -> 每台機器1W並發(10K問題) 100台機器

    大流量的處理方法:分而治之

5.優化環境

  1. 有一個50萬PV的資料類網站(從磁盤提取文檔到內存)原服務器32位,1.5G的堆,用戶反饋網站比較緩慢,因此公司決定升級,新的服務器為64位,16G的堆內存,結果用戶反饋卡頓十分嚴重,反而比以前效率更低了

    1.為什么原網站慢:很多用戶瀏覽數據,很多數據load到內存,內存不足,頻繁GC,STW長,響應時間變慢

    2.升級服務器后為什么會更卡頓:內存越大,FGC時間越長

    3.如何優化:PS+PO -> PN + CMS 或者 G1,最直接的應該是從業務上優化,不要把文檔加載到內存,而是用一個文件服務器之類的

  2. 系統CPU經常100%,如何調優?(面試高頻)

    1.CPU100%那么一定有線程在占用系統資源

    2.找出哪個進程cpu高(top)

    3.該進程中的哪個線程cpu高(top -Hp)

    4.導出該線程的堆棧 (jstack)

    5.查找哪個方法(棧幀)消耗時間 (jstack)

    6.觀察是工作線程占比高 | 垃圾回收線程占比高

  3. 系統內存飆高,如何查找問題?(面試高頻)

    1.導出堆內存 (jmap)

    2.分析 (jhat jvisualvm mat jprofiler ... )

  4. 如何監控JVM

    jstat jvisualvm jprofiler arthas top...

6.解決JVM運行中的問題

  • 一個案例理解常用工具

    1.測試代碼:

    import java.math.BigDecimal;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.ScheduledThreadPoolExecutor;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 從數據庫中讀取信用數據,套用模型,並把結果進行記錄和傳輸
     */
    
    public class T15_FullGC_Problem01 {
    
        private static class CardInfo {
            BigDecimal price = new BigDecimal(0.0);
            String name = "張三";
            int age = 5;
            Date birthdate = new Date();
    
            public void m() {}
        }
    
        private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
                new ThreadPoolExecutor.DiscardOldestPolicy());
    
        public static void main(String[] args) throws Exception {
            executor.setMaximumPoolSize(50);
    
            for (;;){
                modelFit();
                Thread.sleep(100);
            }
        }
    
        private static void modelFit(){
            List<CardInfo> taskList = getAllCardInfo();
            taskList.forEach(info -> {
                // do something
                executor.scheduleWithFixedDelay(() -> {
                    //do sth with info
                    info.m();
    
                }, 2, 3, TimeUnit.SECONDS);
            });
        }
    
        private static List<CardInfo> getAllCardInfo(){
            List<CardInfo> taskList = new ArrayList<>();
    
            for (int i = 0; i < 100; i++) {
                CardInfo ci = new CardInfo();
                taskList.add(ci);
            }
    
            return taskList;
        }
    }
    

    2.java -Xms200M -Xmx200M -XX:+PrintGC T15_FullGC_Problem01

    3.一般是運維團隊首先受到報警信息(CPU Memory)

    4.top命令觀察到問題:內存不斷增長 CPU占用率居高不下

    5.top -Hp 觀察進程中的線程,哪個線程CPU和內存占比高

    6.jps定位具體java進程;jstack 定位線程狀況,重點關注:WAITING BLOCKED

    eg.waiting on <0x0000000088ca3310> (a java.lang.Object)
    假如有一個進程中100個線程,很多線程都在waiting on ,一定要找到是哪個線程持有這把鎖.怎么找?搜索jstack dump的信息,找 ,看哪個線程持有這把鎖RUNNABLE

    7.為什么阿里規范里規定,線程的名稱(尤其是線程池)都要寫有意義的名稱

    怎么樣自定義線程池里的線程名稱?(自定義ThreadFactory)

    8.jinfo pid

    9.jstat -gc 動態觀察gc情況 / 閱讀GC日志發現頻繁GC / arthas觀察 / jconsole/jvisualVM/ Jprofiler(最好用)

    jstat -gc 4655 500 : 每個500個毫秒打印GC的情況

    如果面試官問你是怎么定位OOM問題的?如果你回答用圖形界面(錯誤)
    1:已經上線的系統不用圖形界面用什么?(cmdline arthas)
    2:圖形界面到底用在什么地方?測試!測試的時候進行監控!(壓測觀察)

    10.jmap - histo 4655 | head -20,查找有多少對象產生

    11.jmap -dump:format=b,file=xxx pid :

    線上系統,內存特別大,jmap執行期間會對進程產生很大影響,甚至卡頓(電商不適合)
    1:設定了參數HeapDump,OOM的時候會自動產生堆轉儲文件
    2:很多服務器備份(高可用),停掉這台服務器對其他服務器不影響
    3:在線定位(一般小點兒公司用不到)

    12.java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError T15_FullGC_Problem01

    13.使用MAT / jhat /jvisualvm 進行dump文件分析

    https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html

    jhat -J-mx512M xxx.dump
    http://192.168.17.11:7000
    拉到最后:找到對應鏈接
    可以使用OQL查找特定問題對象

    14.找到代碼的問題

  • jconsole遠程連接

    1.程序啟動加入參數:

    java -Djava.rmi.server.hostname=192.168.17.11 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=11111 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false XXX
    

    2.如果遭遇 Local host name unknown:XXX的錯誤,修改/etc/hosts文件,把XXX加入進去

    192.168.17.11 basic localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    

    3.關閉linux防火牆(實戰中應該打開對應端口)

    service iptables stop
    chkconfig iptables off #永久關閉
    

    4.windows上打開 jconsole遠程連接 192.168.17.11:11111

  • jvisualvm遠程連接

    https://www.cnblogs.com/liugh/p/7620336.html (簡單做法)

  • jprofiler (收費)

  • arthas在線排查工具

    為什么需要在線排查:在生產上我們經常會碰到一些不好排查的問題,例如線程安全問題,用最簡單的threaddump或者heapdump不好查到問題原因。為了排查這些問題,有時我們會臨時加一些日志,比如在一些關鍵的函數里打印出入參,然后重新打包發布,如果打了日志還是沒找到問題,繼續加日志,重新打包發布。對於上線流程復雜而且審核比較嚴的公司,從改代碼到上線需要層層的流轉,會大大影響問題排查的進度。

    jvm觀察jvm信息

    thread定位線程問題

    dashboard 觀察系統情況

    heapdump + jhat分析

    jad反編譯

    動態代理生成類的問題定位
    第三方的類(觀察代碼)
    版本問題(確定自己最新提交的版本是不是被使用)

    redefine 熱替換

    目前有些限制條件:只能改方法實現(方法已經運行完成),不能改方法名, 不能改屬性

    sc - search class

    watch - watch method

    沒有包含的功能:jmap


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM