偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

簡明的 Arthas 配置及基礎(chǔ)運(yùn)維教程

開發(fā) 開源
Arthas是一款強(qiáng)大的開源Java診斷程序,它可以非常方便的啟動并以界面式的方式和Java程序進(jìn)行交互,支持監(jiān)控程序的內(nèi)存使用情況、線程信息、gc情況、甚至可以反編譯并修改現(xiàn)上代碼等。

Arthas是一款強(qiáng)大的開源Java診斷程序,它可以非常方便的啟動并以界面式的方式和Java程序進(jìn)行交互,支持監(jiān)控程序的內(nèi)存使用情況、線程信息、gc情況、甚至可以反編譯并修改現(xiàn)上代碼等。

一、簡述Arthas的運(yùn)行原理(理解)

arthas的運(yùn)行原理大致是以下幾個步驟:

  • 啟動arthas選擇目標(biāo)Java程序后,artahs會向目標(biāo)程序注入一個代理。
  • 代理會創(chuàng)建一個集HTTP和Telnet的服務(wù)器與客戶端建立連接。
  • 客戶端與服務(wù)端建立連接。
  • 后續(xù)客戶端需要監(jiān)控或者調(diào)整程序都可以通過服務(wù)端Java Instrumentation機(jī)制和應(yīng)用程序產(chǎn)生交互。

二、詳解Arthas基礎(chǔ)使用

1.下載安裝

在介紹幾個典型的案例之前,我們需要先下載安裝一下Arthas,Arthas的官方地址如下:

Arthas的官方地址:https://arthas.aliyun.com/

考慮到方便筆者一般是使用命令行的方式下載:

curl -O https://arthas.aliyun.com/arthas-boot.jar

完成后我們通過下面這個命令就可以將Arthas啟動了。

java -jar arthas-boot.jar

此時我們就可以看到對應(yīng)的進(jìn)程序號和進(jìn)程的pid,以筆者為例,開啟arthas之后就會看到一個序號為1的9121的Java進(jìn)程,我們可以直接點(diǎn)擊1并輸入回車對此進(jìn)程進(jìn)行監(jiān)控管理:

[INFO] JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64/jre
[INFO] arthas-boot version: 3.7.2
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 9121 arthasExample.jar

隨后arthas初次會進(jìn)行相關(guān)依賴下載,然后我們就可以正式的使用arthas管理當(dāng)前進(jìn)程了:

2.離線用戶的使用姿勢(可選閱讀)

考慮到內(nèi)網(wǎng)用戶無法聯(lián)網(wǎng)進(jìn)行arthas初始化,所以arthas也人性化的提供了全量包的下載方式,有需要的讀者可移步到下載頁面選擇全量包下載即可獲取全量的arthas包:

完成后下載并解壓之后,我們可以直接通過下面這個腳本指令快速啟動arthas:

./as.sh

3.常見指令介紹

步入arthas我們就可以進(jìn)行一些比較基礎(chǔ)的操作,以下是筆者日常用的比較多的指令,和Linux差不多,讀者可自行參閱了解

  • cat:打印文件內(nèi)容。
  • cls:清空當(dāng)前屏幕區(qū)域內(nèi)容。
  • grep:匹配查找。
  • history:打印歷史命令。
  • pwd:輸入當(dāng)前Java進(jìn)程所在的位置。
  • quit:退出當(dāng)前arthas客戶端。
  • stop:關(guān)閉arthas服務(wù)端,所有arthas客戶端都會退出。

這里筆者就簡單的演示一下,可以看到pwd輸出的就是筆者所監(jiān)控的Java進(jìn)程所處的文件目錄:

[arthas@9121]$ pwd
# 當(dāng)前監(jiān)控的進(jìn)程在服務(wù)器上的目錄
/home/sharkchili/arthasExample
[arthas@9121]$

又比如筆者通過memory查看堆內(nèi)存使用情況,如果只想看老年代的數(shù)據(jù),就可以使用grep:

memory |grep ps_old_gen

點(diǎn)擊quit會直接退出當(dāng)前進(jìn)程的客戶端,stop同理只不過多是連著服務(wù)端和其他客戶端一并殺掉,這里就不多做演示了:

[arthas@9121]$ quit
# 直接返回到服務(wù)器的目錄
sharkchili@DESKTOP-7IPKPVJ:~/arthas$

4.快捷啟動配置

為了快捷啟動arthas,筆者也給出個人的配置方式,首先vim一個名為as.sh的腳本,其內(nèi)容為arthas-boot.jar的啟動指令:

java -jar /home/sharkchili/arthas/arthas-boot.jar

完成腳本編寫確認(rèn)啟動無誤之后,我們將這個腳本通過alias重命名的方式追加到/etc/profile下,內(nèi)容如下即sh指令加上上述腳本的全路徑:

alias as="sh /home/sharkchili/arthas/as.sh"

然后通過source指令使其生效:

可以看到完成這樣一段配直接后,我們可以直接通過as指令完成arthas的快捷啟動:

# 鍵入as
sharkchili@DESKTOP-xxx:~$ as
# 直接快速啟動arthas
[INFO] JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64/jre
[INFO] arthas-boot version: 3.7.2
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 9121 arthasExample.jar

三、Arthas中比較常用的運(yùn)維指令

1.查看實時數(shù)據(jù)面板

日常開發(fā)維護(hù)過程中對于項目的巡檢還是蠻重要的,通過Arthas的dashboard可以非常直觀的查看當(dāng)前系統(tǒng)中進(jìn)程的運(yùn)行情況。

在arthas的控制面板輸入dashboard,默認(rèn)情況下5s進(jìn)行一次刷新:

這里我們來簡單介紹一下第一板塊線程中的字段的含義:

  • ID:java級別的線程id號,注意與jstack中的native id的區(qū)別。
  • NAME:線程名稱。
  • GROUP:線程所在線程組名。
  • PRIORITY:線程優(yōu)先級,值越大優(yōu)先級越高。
  • STATE:線程運(yùn)行狀態(tài)。
  • CPU%:線程CPU使用率。
  • DELTA_TIME:上次采樣之后,線程運(yùn)行的CPU時間,單位為秒。
  • TIME:線程運(yùn)行的總CPU時長,數(shù)據(jù)格式為分:秒。
  • INTERRUPTED:線程當(dāng)前的中斷位狀態(tài)。
  • DAEMON :是否為守護(hù)線程。

第二板塊就是內(nèi)存使用版塊,記錄各個堆區(qū)、元空間的內(nèi)存使用情況以及GC情況。而第三板塊則是服務(wù)器運(yùn)行參數(shù)版塊,這一版塊記錄著程序當(dāng)前運(yùn)行服務(wù)器的內(nèi)核版本信息、jdk版本等。

需要了解的是arthas中的操作指令可以通過--help了解查閱,我們以dashboard為例,其使用說明如下,可以看到我們可以通過-i決定面板刷新間隔(單位是毫秒),用-n決定面板刷新次數(shù):

所以如果我們希望每1s刷新1次,刷新5次,那么對應(yīng)的命令就是:

dashboard -i 1000 -n 5

2.查看JVM信息

arthas也可能非常直觀的查看jvm信息,對應(yīng)的指令也就是jvm。

同樣的這個指令也會輸出多個板塊的內(nèi)容,我們先來看看第一個板塊,可以可以看到該指令可以非常直觀的看到機(jī)器名稱、jvm啟動時間、jdk版本以及我們配置jvm參數(shù)信息:

由于板塊比較多,這里筆者就說幾個筆者比較常用的板塊,分別是線程板塊和文件描述符板塊,通過這兩個板塊筆者可以日常巡檢了解是否發(fā)生線程死鎖或者程序中是否出現(xiàn)資源未能及時關(guān)閉的情況:

  • THREAD:它記錄當(dāng)前活躍線程數(shù)、活躍的守護(hù)線程數(shù)、從JVM啟動開啟曾經(jīng)活著的最大線程數(shù)、總共啟動線程數(shù)以及發(fā)生死鎖的線程數(shù)。
  • FILE-DESCRIPTOR:這個板塊記錄JVM可以打開的最大文件描述符和當(dāng)前已經(jīng)打開的文件描述符數(shù)。

3.查看和修改日志

logger指令也算是筆者比較喜歡的指令,它可以非常直觀的查看我們對于日志的配置,如下圖,以筆者當(dāng)前運(yùn)行的程序為例,可以看到如下幾個信息:

  • 日志級別為INFO。
  • 存儲錯誤日志的ERROR_FILE的相對路徑。
  • 存儲普通日志INFO_FILE的相對路徑。

當(dāng)然我們也可以查看指定名字的日志信息,例如我們想查看com.example.arthasExample.TestController的日志信息,就可以直接鍵入logger -n com.example.arthasExample.TestController指令進(jìn)行查看:

logger指令還有一個比較實用的功能,即直接修改日志級別,例如我們希望修改ROOT這個名稱的日志級別,就可以基于如下步驟完成修改:

  • 獲取classLoader的哈希碼。
  • 基于哈希碼通過logger指令修改日志級別。

我們程序中有這樣一段代碼,此時我們請求下面這個接口只會輸出info級別的日志:

 @GetMapping(value = {"/user/logger"})
    public String loggerPrint() {
        log.info("info logger");
        log.debug("debug logger");
        return "success";
    }

對應(yīng)的輸出結(jié)果為:

2024-08-19 23:53:29.454  INFO  c.e.a.TestController          :138  http-nio-8080-exec-1                    info logger

接下來我們就直接通過arthas修改日志級別,首先我們需要獲取當(dāng)前classloader的哈希碼:

sc -d com.example.arthasExample.TestController

然后我們直接通過這個哈希碼,執(zhí)行如下指令將日志設(shè)置為debug

logger -c 306a30c7 --name ROOT --level debug

于是debug日志就出現(xiàn)了:

2024-08-20 00:13:31.438  INFO  c.e.a.TestController          :138  http-nio-8080-exec-6                    info logger
2024-08-20 00:13:31.439  DEBUG c.e.a.TestController          :139  http-nio-8080-exec-6                    debug logger

4.查看JVM內(nèi)存信息

接下來就是memory指令,這也是筆者比較常用的指令之一,通過memory我們可以監(jiān)控到當(dāng)前內(nèi)存的使用情況: 如下圖所示,鍵入memory指令后我們就可以看到這些區(qū)域的內(nèi)存已用、總大小、最大值以及使用率等信息:

對應(yīng)的我們也給出上文中memory各行代表的含義:

  • heap:堆區(qū)內(nèi)存。
  • ps_eden_space:堆內(nèi)存中新生代Eden區(qū)。
  • ps_survivor_space:堆內(nèi)存中新生代survivor區(qū)。
  • ps_old_gen:堆內(nèi)存老年代區(qū)。
  • nonheap:非堆內(nèi)存,即堆內(nèi)存之外的內(nèi)存。
  • code_cache:因為Java執(zhí)行是將字節(jié)碼編譯為機(jī)器碼,而這個區(qū)域就是用于緩存這部分代碼。
  • metaspace:元空間,以jdk1.8為例該空間是用于存儲Java類和方法的元數(shù)據(jù)信息、常量池等。
  • compressed_class_space:存放類文件信息的區(qū)域。

對應(yīng)的我們在這里也簡單的復(fù)習(xí)一下JVM內(nèi)存區(qū)域的分布,建議讀者可參考下圖了解memory指令中各個字段的含義:

5.查看JVM的環(huán)境變量

arthas的sysenv指令常用于獲取系統(tǒng)環(huán)境變量信息,鍵入這條指令我們可以看到當(dāng)前java程序所使用的系統(tǒng)大部分環(huán)境變量信息,如下圖,可以看到大部分的當(dāng)前系統(tǒng)用戶名稱、編碼格式、當(dāng)前程序路徑以及客戶端ip和端口號等信息:

根據(jù)help的提示,這條指令同樣也支持查詢單個環(huán)境變量,不過意義不大,畢竟不是每個都知道環(huán)境變量叫什么,只有查看了才知道(笑):

[arthas@23543]$ sysenv PWD
 KEY                                              VALUE                                                                                                                                                                                               
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 PWD                                              /home/sharkchili/arthasExample

6.查看和修改JVM系統(tǒng)屬性

sysprop查看的jvm的系統(tǒng)屬性,基本上通過這個指令我們可以看到大部分的JVM參數(shù)配置信息,如下輸出結(jié)果,我們大體可以看到JDK版本、程序名稱以及日志編碼格式和當(dāng)前系統(tǒng)用戶名稱等:

7.查看當(dāng)前JVM線程堆棧信息

arthas提供thread指令用于查看線程情況,如下所示,它基本打印了線程計數(shù)信息和幾個活躍的線程的實時情況,默認(rèn)情況下,它是按照CPU增量時間降序進(jìn)行排序:

按照help的提示,我們也可以通過-n打印前幾個忙碌的線程調(diào)用堆棧信息,如下所示,筆者希望打印出前2條忙碌的線程,鍵入的指令為thread -n 2:

同時arthas也支持按照時間間隔進(jìn)行輸出打印,比如我們希望列出5s內(nèi)最忙的3個線程,那么對應(yīng)的指令就是:

thread -n 3 -i 5000

當(dāng)我們的Java程序有大量的線程時候,我們希望篩選中某種狀態(tài)的線程,我們可以通過--state指定,例如我們希望打印處于RUNNABLE狀態(tài)的線程,那么我們就可以鍵入thread --state RUNNABLE來獲得輸出結(jié)果:

對于死鎖問題,我們也可以通過-b指令來定位查看當(dāng)前程序是否存在阻塞其他線程的線程,如下圖所示,以筆者為例當(dāng)前程序就不存在死鎖的情況:

此時我們給出一個觸發(fā)死鎖的接口并調(diào)用:

@RequestMapping("dead-lock")
    public void deadLock() {
        //線程1先取得鎖1,休眠后取鎖2
        new Thread(() -> {
            synchronized (lock1) {
                try {
                    log.info("t1 successfully acquired the lock1......");
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }


                synchronized (lock2) {
                    log.info("t1 successfully acquired the lock1......");
                }
            }
        }, "t1").start();

        //線程2先取得鎖2,休眠后取鎖1
        new Thread(() -> {
            synchronized (lock2) {
                try {
                    log.info("t2 successfully acquired the lock2......");
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }


                synchronized (lock1) {
                    log.info("t2 successfully acquired the lock1......");
                }
            }
        }, "t2").start();
    }

此時,鍵入-b指令就可以定位阻塞其他線程的線程以及所在代碼段:

8.vmtool對于JVM的調(diào)控

vmtool算是筆者用的比較多的一個工具指令,可用于查詢對象或者強(qiáng)制GC等功能,這些功能讀者可自行參考官網(wǎng)查閱:

vmtool:https://arthas.aliyun.com/doc/vmtool.html

而筆者這里想要介紹的是一個強(qiáng)制打斷線程的功能,這個指令對于特定場景下應(yīng)急處理還是蠻實用的。

我們的程序調(diào)用下面的接口被系統(tǒng)監(jiān)控到CPU100%,此時我們就可以通過arthas進(jìn)行特定場景下的應(yīng)急處理:

@RequestMapping("cpu-100")
    public static void cpu() {
        //無限循環(huán)輸出打印
        new Thread(() -> {
            while (true) {
                log.info("cpu working");
            }
        }, "thread-1").start();
    }

我們通過thread指令看到thread-1基本將單個CPU跑滿了,并且我們通過控制臺定位到對應(yīng)的id為48:

此時我們可以通過vmtool的action指令將線程打斷:

vmtool --action interruptThread -t 48

完成操作之后即可看到這個線程被我們成功打斷了:

同時vmTool也支持觀測變量的詳情,以下面這個實例變量dateTimeStr 為例,每次接口請求都會實時刷新:

private String dateTimeStr = DateUtil.formatDateTime(new Date());

    @RequestMapping(value = "/getVal")
    public String getVal() {
        dateTimeStr = DateUtil.formatDateTime(new Date());
        log.info("dateTimeStr: {}", dateTimeStr);
        return "success";
    }

如果我們希望查看此刻dateTimeStr 的值,我們就可以通過vmtool的action指定為getInstances ,然后指定類的全路徑(以筆者這段代碼為例則是com.example.arthasExample.TestController),最后鍵入表達(dá)式instances[0].dateTimeStr意為獲取當(dāng)前實例的dateTimeStr:

vmtool  --action getInstances --className com.example.arthasExample.TestController  --express 'instances[0].dateTimeStr' 

此時我們就可以非常直觀的監(jiān)控到這個變量的信息了:

常見面試題:arthas統(tǒng)計方法耗時的原理是什么

watch指令示例如下:

watch com.example.MyService sayHello "{params, result, throwExp} -> { return 'Exception: ' + throwExp; }" -E

我們從指令即可看出他可以獲取到類的全路徑,對此我們不拿猜測它就是基于這個類的全路徑進(jìn)行一個字節(jié)碼樁技術(shù)對類進(jìn)行增強(qiáng),插入一段代碼進(jìn)行在方法執(zhí)行前后插入時間,實現(xiàn)耗時統(tǒng)計。

責(zé)任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關(guān)推薦

2025-05-08 08:20:00

Arthas開源Java

2024-11-12 15:46:37

2010-05-26 10:42:20

SVN1.5配置

2018-10-15 14:26:23

運(yùn)維IT技術(shù)架構(gòu)

2015-06-24 10:42:19

云計算運(yùn)維自動化運(yùn)維ANSIBLE

2019-03-15 10:13:10

運(yùn)維云計算運(yùn)營

2013-12-03 13:05:30

Lua腳本語言

2009-05-19 10:19:49

網(wǎng)絡(luò)拓?fù)?/a>運(yùn)維管理摩卡

2015-08-12 17:06:28

2023-10-20 14:08:35

digDNS

2013-03-29 09:15:08

IT運(yùn)維運(yùn)維人員運(yùn)維工程師

2015-07-13 10:06:11

超融合基礎(chǔ)架構(gòu)運(yùn)維數(shù)據(jù)中心

2024-07-25 11:22:23

2012-06-25 16:40:54

2016-01-29 15:15:17

運(yùn)維性能優(yōu)化模式

2017-12-15 09:20:20

IT運(yùn)維順豐

2016-12-13 13:15:49

運(yùn)維

2019-02-15 08:51:22

2014-06-20 10:51:35

Linux LVM邏輯卷

2021-12-01 09:53:46

CSS 技巧代碼重構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號