整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          一個輕量的企業(yè)級Web的控制終端程序

          個輕量的企業(yè)級Web的控制終端程序,匯集了大多數(shù)同類產品優(yōu)點于一身,支持SSH2/lrzsz、(RDP/RFB/Telnet)、審計和錄屏等

          快速開始

          1. 安裝

          git clone https://github.com/wl4g/xcloud-webconsole.git # 上游,最新
          # git clone https://gitee.com/wl4g/xcloud-webconsole.git
          cd xcloud-webconsole/scripts
          ./build.sh  # 交叉編譯為Windows程序
          # build.bat # 交叉編譯為Linux程序

          2. 部署到nginx支持https. (可選)

          因為webconsole是基于HTML的,瀏覽器的復制和粘貼功能受到安全機制的限制,只能在HTTPS下使用,當然若不想麻煩,也可忽略此步驟,直接使用HTTP本地測試,只是不能使用瀏覽器的復制和粘貼功能。

          2.1 添加hosts

          127.0.0.1   webconsole.wl4g.debug
          sudo mkdir -p /etc/nginx/conf.d && \
          cat > /etc/nginx/conf.d/webconsole.conf <<EOF
          # Generated by WebConsole docs sample.
          
          # WebConsole Webapps pages.
          server {
              listen 443;
              server_name webconsole.sunwuu.fat;
              ssl on;
              ssl_certificate   certs/_wildcard.wl4g.debug.pem;
              ssl_certificate_key  certs/_wildcard.wl4g.debug-key.pem;
              ssl_session_timeout 5m;
              ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
              ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
              ssl_prefer_server_ciphers on;
              location / {
                 root /usr/share/nginx/html/webconsole;
                 index index.html;
              }
          }
          
          # WebConsole APIs.
          server {
              listen 26088 ssl;
              server_name  webconsole.sunwuu.fat;
              ssl_certificate   certs/_wildcard.wl4g.debug.pem;
              ssl_certificate_key  certs/_wildcard.wl4g.debug-key.pem;
              ssl_session_timeout  5m;
              ssl_prefer_server_ciphers    on;
              ssl_protocols TLSv1 TLSv1.1 TLSv1.2;         
              ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
              location / {
                  proxy_http_version 1.1;    
                  proxy_set_header Upgrade $http_upgrade;
                  proxy_set_header Connection "upgrade";     
                  proxy_set_header X-real-ip $remote_addr;
                  proxy_set_header X-Forwarded-For $remote_addr;
                  proxy_pass http://127.0.0.1:16088;
              }
          }
          EOF
          
          sudo chmod 755 /etc/nginx/conf.d/webconsole.conf
          sudo systemctl restart nginx

          2.2. 安裝測試CA跟證書 (可選, 跟隨步驟2)

          • 將CA跟證書安裝到系統(tǒng)及chrome,使其受信任. 例如在Chrome84.x中:
          chrome://settings/security

          管理證書 -> 受信任的根證書頒發(fā)機構 -> 導入 然后重啟chrome瀏覽器嘗試訪問: https://webconsole.wl4g.debug

          特性

          • 它被設計成一個原生JavaScript類庫,可以很容易地與React/Vue/AngularJS和其他框架集成
          • 它可以運行在 Android iOS 和任何其他可以呈現(xiàn)HTML的終端上。它幾乎可以完全取代基于安裝程序的shell客戶端
          • 完全支持 lrzsz 命令集(基于zmodem實現(xiàn))
          • 增強了對移動終端的復制、粘貼、快進、后退等按鍵組合命令的支持,用戶友好的操作習慣
          • 無縫對接 prometheus 度量采集

          度量及指標

          curl http://localhost:16089/metrics
          
          # HELP goroutines_num Number of goroutines
          # TYPE goroutines_num gauge
          goroutines_num 16
          # HELP mysql_active_conn Current active connections of MySQL
          # TYPE mysql_active_conn gauge
          mysql_active_conn{dbconnectstr="gzsm:******@tcp(10.0.0.160:3306)/devops_dev?charset=utf8",host="10.0.0.172"} 1
          # HELP ssh2_active_dispatch_channels Current active channels of SSH2 dispatcher
          # TYPE ssh2_active_dispatch_channels gauge
          ssh2_active_dispatch_channels{host="10.0.0.172",user="admin"} 0
          # HELP threads_num Number of threads
          # TYPE threads_num gauge
          threads_num 8
          # HELP virtual_free_memory Size of virtual free memory
          # TYPE virtual_free_memory gauge
          virtual_free_memory 1.731424256
          # HELP virtual_total_memory Size of virtual total memory
          # TYPE virtual_total_memory gauge
          virtual_total_memory 8.50089984

          運行環(huán)境

          • 客戶端建議使用 Chrome 40+、Firefox 38+、Safari 9+
          • 二次開發(fā)建議基于 Golang 1.13+ 構建
          • 本程序只能對 Unix/Linux 類的操作系統(tǒng)的 SSH 協(xié)議的 OS 遠程操作(Windows RDP支持需參考具體發(fā)行版是否有RDP實現(xiàn))

          運行截圖

          說明:界面未設置css樣式的最精簡測試頁面

          主要依賴項目

          • 日志框架 go.uber.org/zap
          • 通用web框架 github.com/gin-gonic/gin
          • 普羅米修斯 github.com/prometheus
          • 主機指標采集 github.com/shirou/gopsutil
          • JSON序列化 github.com/json-iterator/go
          • Websocket處理 github.com/gorilla/websocket

          其他說明(如果需要)

          • 生成臨時調試https SSL證書

          待辦清單

          • [√] 完全統(tǒng)一每個組件的日常輸出,如“gin”框架。
          • [√] 增強webconsole服務的管理員功能,例如自身的health/metrics/indicator(CPU/Mem/Network/Connections…)和更詳細的指示器
          • Canvas + Object Storage 審計錄屏功能
          • 為了實現(xiàn)與windows RDP(遠程桌面協(xié)議)兼容的基于Web的遠程圖像UI控制協(xié)議, 以及RFB/Telnet等

          自定義開發(fā)指南

          • 推薦IDE使用 VSCode 進行二次開發(fā),因為項目根目錄已包含 .vscode 編輯器配置文件
          • 修改數(shù)據(jù)庫配置: resources/webconsole.yml#datasource.mysql.dbconnectstr,也可以使用環(huán)境變量:.vscode/launch.json => WEBCONSOLE_DATASOURCE_MYSQL_DBCONNECTSTR
          • 配置文件說明:本項目使用viper配置框架,加載優(yōu)先級依次為:Set()/Flags/Env/Config/Default
          • 如果需要添加新的配置項,則必須使用config_generator.go 生成和xxx-config.go 對應的默認配置項webconsole.default.yml.go,參考命令:

          背景

          是不是在實際開發(fā)工作當中經(jīng)常碰到自己寫的代碼在開發(fā)、測試環(huán)境行云流水穩(wěn)得一筆,可一到線上就經(jīng)常不是缺這個就是少那個反正就是一頓報錯抽風似的,線上調試代碼又很麻煩,讓人頭疼得抓狂;而且debug不一定是最高效的方法,遇到線上問題不能debug了怎么辦。原先我們Java中我們常用分析問題一般是使用JDK自帶或第三方的分析工具如jstat、jmap、jstack、 jconsole、visualvm、Java Mission Control、MAT等。但此刻的你沒有看錯,還有一款神器Arthas工具著實讓人吃驚,可幫助程序員解決很多繁瑣的問題,使得加班解決線上問題成為過去的可能性大大提高。

          定義

          Arthas是一個Java診斷工具,由阿里巴巴中間件團隊開源,目前已在Java開發(fā)人員中被廣泛采用。Arthas能夠分析,診斷,定位Java應用問題,例如:JVM信息,線程信息,搜索類中的方法,跟蹤代碼執(zhí)行,觀測方法的入?yún)⒑头祷貐?shù)等等。并能在不修改應用代碼的情況下,對業(yè)務問題進行診斷,包括查看方法的出入?yún)ⅲ惓#O(jiān)測方法執(zhí)行耗時,類加載信息等,大大提升線上問題排查效率。簡單的話:就是再不重啟應用的情況下達到排查問題的目的。

          特性

          • 儀表盤實時查看系統(tǒng)的運行狀態(tài)。
          • OGNL表達式查看參數(shù)和返回值/例外,查看方法參數(shù)、返回值和異常。
          • 通過jad/sc/redefine實現(xiàn)在線熱插拔。
          • 快速解決類沖突問題,定位類加載路徑。
          • 快速定位應用熱點和生成火焰圖。
          • 支持在線診斷WebConsole。
          • Arthas對應用程序沒有侵入(但對宿主機jvm有侵入),代碼或項目中不需要引入jar包或依賴,因為是通過attach的機制實現(xiàn)的,我們的應用的程序和arthas都是獨立的進程,arthas是通過和jvm底層交互來獲取運行在其上的應用程序實時數(shù)據(jù)的,靈活查看運行時的值,這個和hickwall,jprofiler等監(jiān)控軟件的區(qū)別(JPofiler也有這樣的功能,但是是收費的)動態(tài)增加aop代理和監(jiān)控日志功能,無需重啟服務,而且關閉arthas客戶端后會還原所有增強過的類,原則上是不會影響現(xiàn)有業(yè)務邏輯的。
          • 對應用程序所在的服務器性能的影響,個別命令使用不當?shù)脑挘赡軙伪琷vm內存或導致應用程序響應變慢,命令的輸出太多,接口調用太頻繁會記錄過多的數(shù)據(jù)變量到內存里,比如tt指令,建議加 -n 參數(shù) 限制輸出次數(shù),sc * 通配符的使用不當,范圍過大,使用異步任務時,請勿同時開啟過多的后臺異步命令,以免對目標JVM性能造成影響,一把雙刃劍(它甚至可以修改jdk里的原生類),所以在線上運行肯定是需要權限和流程控制的。

          使用場景

          在日常開發(fā)中,當我們發(fā)現(xiàn)應用的某個接口響應比較慢,這個時候想想要分析一下原因,找到代碼中耗時的部分,比較容易想到的是在接口鏈路的 IO 操作上下游打印時間日志,再根據(jù)幾個時間點的日志算出耗時長的 IO 操作。這種方式?jīng)]有問題,但是加日志需要發(fā)布,既繁瑣又低效,這個時候可以引入一些線上 debug 的工具,arthas 就是很好的一種,除了分析耗時,還可以打印調用棧、方法入?yún)⒓胺祷兀惣虞d情況,線程池狀態(tài),系統(tǒng)參數(shù)等等,其實現(xiàn)原理是解析 JVM 在操作系統(tǒng)中的文件,大部分操作是只讀的,對服務進程沒有侵入性,因此可以放心使用。

          實戰(zhàn)

          CPU占用高示例

          創(chuàng)建一個springboot項目并打包成arthas-demo-1.0.jar,啟動arthas-demo-1.0.jar

          代碼示例如下

          package cn.itxs;
          
          import org.springframework.boot.SpringApplication;
          import org.springframework.boot.autoconfigure.SpringBootApplication;
          import java.util.UUID;
          import java.util.concurrent.TimeUnit;
          ?
          @SpringBootApplication
          public class App 
          {
              public static void main(String[] args) {
                  SpringApplication.run(App.class,args);
                  new Thread( () -> {
                      while (true) {
                          String str = UUID.randomUUID().toString().replaceAll("-", "");
                      }
                  },"cpu demo thread").start();
          ?
                  new Thread( () -> {
                      while (true) {
                          String str = UUID.randomUUID().toString().replaceAll("-", "");
                          try {
                              TimeUnit.MILLISECONDS.sleep(10);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                      }
                  },"cpu with sleep thread").start();
              }
          }
          

          安裝與使用

          推薦方式

          # 下載`arthas-boot.jar`這種也是官方推薦的方式
          curl -O https://arthas.aliyun.com/arthas-boot.jar
          # 啟動arthas-boot.jar,必須啟動至少一個 java程序,否則會自動退出。運行此命令會自動發(fā)現(xiàn) java進程,輸入需要 attach 進程對應的序列號,例如,輸入1按回車則會監(jiān)聽該進程。
          java -jar arthas-boot.jar
          # 比如輸入JVM (jvm實時運行狀態(tài),內存使用情況等)
          

          CPU占用高示例

          package cn.itxs.controller;
          ?
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.ResponseBody;
          import org.springframework.web.bind.annotation.RestController;
          ?
          import java.util.concurrent.TimeUnit;
          ?
          @RestController
          @RequestMapping("/thread")
          public class ThreadController {
              private Object obj1 = new Object();
              private Object obj2 = new Object();
          ?
              @RequestMapping("/test")
              @ResponseBody
              public String test(){
                  new Thread(() -> {
                      synchronized (obj1){
                          try {
                              TimeUnit.SECONDS.sleep(10);
                          } catch (InterruptedException e) {
                              synchronized (obj2){
                                  System.out.printf("thread 1執(zhí)行到此");
                              }
                          }
                      }
                  },"thread 1").start();
          ?
                  new Thread(() -> {
                      synchronized (obj2) {
                          synchronized (obj1){
                              System.out.printf("thread 2執(zhí)行到此");
                          }
                      }
                  },"thread 2").start();
                  return "thread test";
              }
          }
          

          SpringBoot啟動類

          package cn.itxs;
          ?
          import org.springframework.boot.SpringApplication;
          import org.springframework.boot.autoconfigure.SpringBootApplication;
          ?
          @SpringBootApplication
          public class App 
          {
              public static void main(String[] args) {
                  SpringApplication.run(App.class,args);
              }
          }
          
          # 訪問頁面http://192.168.50.100:8080/cpu/test
          # 儀表盤命令,通過上面我們可以發(fā)現(xiàn)線程ID為29也即是線程名稱為“cpu demo thread”占用的cpu較高
          dashboard
          

          • 第一部分時顯示JVM中運行的所有線程:所在線程組,優(yōu)先級,線程的狀態(tài),CPU的占有率,是否是后臺進程等。
          • 第二部分顯示的JVM內存的使用情況和GC的信息。
          • 第三部分是操作系統(tǒng)的一些信息和 Java版本號。
          # 當前最忙的前N個線程 thread -b, ##找出當前阻塞其他線程的線程 thread -n 5 -i 1000 #間隔一定時間后展示,本例中可以看到最忙CPU線程為id=45,代碼行數(shù)為19
          thread -n 5 
          # jad查看反編譯的代碼
          jad cn.itxs.controller.CpuController
          

          線程死鎖示例

          package cn.itxs.controller;
          ?
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.ResponseBody;
          import org.springframework.web.bind.annotation.RestController;
          import java.util.concurrent.TimeUnit;
          ?
          @RestController
          @RequestMapping("/thread")
          public class ThreadController {
              private Object obj1 = new Object();
              private Object obj2 = new Object();
          ?
              @RequestMapping("/test")
              @ResponseBody
              public String test(){
                  new Thread(() -> {
                      synchronized (obj1){
                          try {
                              TimeUnit.SECONDS.sleep(10);
                          } catch (InterruptedException e) {
                          }
                          synchronized (obj2){
                              System.out.println("thread 1執(zhí)行到此");
                          }
                      }
                  },"thread 1").start();
                  try {
                      TimeUnit.SECONDS.sleep(2);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  new Thread(() -> {
                      synchronized (obj2) {
                          synchronized (obj1){
                              System.out.println("thread 2執(zhí)行到此");
                          }
                      }
                  },"thread 2").start();
                  return "thread test";
              }
          }
          
          # 啟動SpringBoot演示程序,訪問頁面http://192.168.50.100:8080/thread/test
          # 運行arthas,查看線程
          thread
          
          # 查看阻塞線程
          thread -b
          # jad反編譯查看代碼
          jad --source-only cn.itxs.controller.ThreadController
          

          線上修復熱部署

          準備一個有問題的java類

          package cn.itxs.controller;
          
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.ResponseBody;
          import org.springframework.web.bind.annotation.RestController;
          
          import java.util.UUID;
          import java.util.concurrent.TimeUnit;
          
          @RestController
          @RequestMapping("/hot")
          public class HotController {
          
              @RequestMapping("/test")
              @ResponseBody
              public String test(){
                  boolean flag = true;
                  if (flag) {
                      System.out.println("開始處理邏輯");
                      throw new RuntimeException("出異常了");
                  }
                  System.out.println("結束流程");
                  return "hot test";
              }
          }
          

          啟動Spring Boot程序,訪問頁面http://192.168.50.94:8080/hot/test發(fā)現(xiàn)報錯,當我們分析到這段程序出異常后,我們分析異常后進行線上代碼修改不停機不重新發(fā)包的情況下的熱更新,操作流程如下:

          # 第一步:`jad命令` 將需要更改的文件先進行反編譯,保存下來 ,編譯器修改,-c 指定這個類的classloader的哈希值,–source-only只顯示源碼,最后是文件反編譯之后的存放路徑
          jad --source-only cn.itxs.controller.HotController > /home/commons/arthas/data/HotController.java
          # 我們將HotController.java中的throw new RuntimeException("出異常了")代碼刪掉,修改完后需要將類重新加載到JVM
          # 第二步:`SC命令` 查找當前類是哪個classLoader加載的,首先,使用sc命令找到要修改的類.sc全稱-search class, -d表示detail,主要是為了獲取classLoader的hash值
          sc -d *HotController | grep classLoader
          classLoaderHash   6267c3bb #類加載器  編號  
          # 第三步:`MC命令` 用指定的classloader重新將類在內存中編譯
          mc -c 6267c3bb /home/commons/arthas/data/HotController.java -d /home/commons/arthas/class
          # 第四步:`redefine命令` 將編譯后的類加載到JVM,參數(shù)是編譯后的.class文件地址
          redefine /home/commons/arthas/class/cn/itxs/controller/HotController.class  
          

          以上操作后再次訪問一下頁面http://192.168.50.94:8080/hot/test,發(fā)現(xiàn)異常沒有了程序已經(jīng)是我們修改正確后的,class文件替換成功,功能確實很強大。

          上面我們是手工一步步執(zhí)行,當然我們可以使用shell腳本串起來簡單操作。

          此外還可以安裝Alibaba Cloud Toolkit熱部署組件(一鍵retransform),熱部署組件支持一鍵將編輯器中修改的 Java 源碼快速編譯,并更新到遠端應用服務中,免去手動 dump、mc 的過程。此外,也可以一鍵還原 retransform 的類文件。

          由于Arthas命令還是較復雜,Arthas-idea插件(部分命令可視化)是一個幫助生成命令的IDEA插件,使用文檔:https://www.yuque.com/arthas-idea-plugin

          安裝基于Arthas實現(xiàn)的簡單好用的熱部署插件ArthasHotSwap可以一鍵生成熱部署命令,提高我們線上維護的效率。

          線上問題常見定位

          watch(方法執(zhí)行數(shù)據(jù)觀測)

          package cn.itxs.controller;
          
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.ResponseBody;
          import org.springframework.web.bind.annotation.RestController;
          
          import java.util.ArrayList;
          import java.util.List;
          import java.util.Random;
          
          @RestController
          @RequestMapping("/watch")
          public class WatchController {
              private static Random random = new Random();
              private int illegalArgumentCount = 0;
          
              @RequestMapping("/test")
              @ResponseBody
              public String test(){
                  String res = null;
                  try {
                      int number = random.nextInt() / 10000;
                      List<Integer> idStrs = this.getIdStr(number);
                      res = printList(number, idStrs);
                  }
                  catch (Exception e) {
                      System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
                  }
                  return res;
              }
          
              private List<Integer> getIdStr(int number) {
                  if (number < 5) {
                      ++this.illegalArgumentCount;
                      throw new IllegalArgumentException("number is: " + number + ", need >= 5");
                  }
                  ArrayList<Integer> result = new ArrayList<Integer>();
                  int count = 2;
                  while (count <= number) {
                      if (number % count == 0) {
                          result.add(count);
                          number /= count;
                          count = 2;
                          continue;
                      }
                      ++count;
                  }
                  return result;
              }
          
              private String printList(int number, List<Integer> primeFactors) {
                  StringBuffer sb = new StringBuffer(number + "=");
                  for (int factor : primeFactors) {
                      sb.append(factor).append('*');
                  }
                  if (sb.charAt(sb.length() - 1) == '*') {
                      sb.deleteCharAt(sb.length() - 1);
                  }
                  System.out.println(sb);
                  return sb.toString();
              }
          }
          

          啟動Spring Boot程序,通過Jmeter每秒訪問一次http://192.168.50.100:8080/watch/test

          # Arthas中的**watch**命令可以讓我們能方便的觀察到指定方法的調用情況,可以觀察到返回值,入?yún)ⅲ约白兞康取?# watch 全路徑類名 方法名 觀察表達式 -x 3  ,觀察表達式匹配ognl表達式,觀察的維度也比較多。
          # 比如:watch cn.itxs.controller.WatchController printList "{params,returnObj}" -x 3
          # 查看printList方法的入?yún)⒑统鰠ⅲ?x表示的是遍歷結果深度默認1,只會打印對象的堆地址,看不到具體的屬性值,-x 2會打印結果的屬性值的信息 -x 3會輸出入?yún)傩灾岛徒Y果屬性值
          # -n 1只抓緊一次,由于我們這里是模擬一直請求的
          watch cn.itxs.controller.WatchController printList '{params}' -n 1
          # -x 表示的是遍歷結果深度默認3
          watch cn.itxs.controller.WatchController printList '{params}' -n 1 -x 3
          # params[0]代表第一個參數(shù)
          watch cn.itxs.controller.WatchController printList '{params[0]}' -n 1 -x 3
          

          # 方法的返回值
          watch cn.itxs.controller.WatchController getIdStr '{returnObj}' -n 1 -x 3
          # 方法參數(shù)和返回值
          watch cn.itxs.controller.WatchController getIdStr '{params,returnObj}' -n 1 -x 3
          

          # 觀察方法執(zhí)行前后當前對象屬性值
          watch cn.itxs.controller.WatchController getIdStr 'target.illegalArgumentCount'
          

          # 觀察異常信息,觀察表達式里增加throwExp就好了。如果增加-e 參數(shù)就能過濾掉非異常的監(jiān)聽了。
          

          # 在觀察表達式后面,我們可以增加條件表達式,例如按時間過濾:#cost>0.5,單位是毫秒,那么控制臺輸出來的都是耗時在0.5毫秒以上的方法調用
          watch cn.itxs.controller.WatchController getIdStr '{params}' '#cost>0.5'
          

          # 按條件過濾觀察params[1].size>4:這里支持ognl表達式。下面例子的意思是:第二個參數(shù)(也就是List primeFactors),的size大于4的時候才觀察入?yún)ⅰ?watch cn.itxs.controller.WatchController printList '{params}' 'params[1].size>4' -x 3
          

          monitor(方法執(zhí)行監(jiān)控)

          monitor結果包括如下

          • **timestamp:時間戳 **
          • class:Java類
          • method:方法(構造方法、普通方法)
          • total:調用次數(shù)
          • success:成功次數(shù)
          • fail:失敗次數(shù)
          • rt:平均RT
          • fail-rate:失敗率
          # -c :統(tǒng)計周期,默認值為10秒
          monitor -c 10 cn.itxs.controller.WatchController getIdStr
          # 在方法調用之前計算condition-express,方法后可帶表達式
          monitor -b -c 10 cn.itxs.controller.WatchController getIdStr
          

          trace

          # trace:方法內部調用路徑,并輸出方法路徑上的每個節(jié)點上耗時
          trace cn.itxs.controller.WatchController test -n 2
          #包含jdk的函數(shù)--skipJDKMethod <value>  skip jdk method trace, default value true.默認情況下,trace不會包含jdk里的函數(shù)調用,如果希望trace jdk里的函數(shù),需要顯式設置--skipJDKMethod false。
          trace --skipJDKMethod false cn.itxs.controller.WatchController test -n 2
          # 調用耗時過濾,只會展示耗時大于10ms的調用路徑,有助于在排查問題的時候,只關注異常情況
          trace cn.itxs.controller.WatchController test '#cost > 1'
          

          stack

          # 輸出當前方法被調用的調用路徑,getIdStr是從test方法調用進來的
          stack cn.itxs.controller.WatchController getIdStr -n 1
          # 輸出當前方法被調用的調用路徑,條件表達過濾,第0個參數(shù)小于0,也可以根據(jù)執(zhí)行時間來過濾,'#cost>1'
          stack cn.itxs.controller.WatchController getIdStr 'params[0]<0' -n 1
          

          tt

          tt(TimeTunnel):方法執(zhí)行數(shù)據(jù)的時空隧道,記錄下指定方法每次調用的入?yún)⒑头祷匦畔ⅲ⒛軐@些不同的時間下調用進行觀測。對于一個最基本的使用來說,就是記錄下當前方法的每次調用環(huán)境現(xiàn)場。

          # 記錄指定方法的每次調用環(huán)境現(xiàn)場
          tt -t cn.itxs.controller.WatchController getIdStr 
          # 列出所有調用記錄
          tt -l cn.itxs.controller.WatchController getIdStr
          

          # 篩選調用記錄
          tt -s 'method.name=="getIdStr"'
          # 查看調用信息
          tt -i 1001
          

          # 重新發(fā)起一次調用
          tt -i 1001 -p
          

          Web Console

          # 啟動時指定Linux的ip
          java -jar arthas-boot.jar --target-ip 192.168.50.94
          

          profiler

          profiler** 命令支持生成應用熱點的火焰圖。本質上是通過不斷的采樣,然后把收集到的采樣結果生成火焰圖。一般分析性能可以先通過Arthas profiler命令生成**jfr文件;在本地通過 jprofiler來分析 jfr文件,定位誰在調用我。

          # 啟動profiler 默認情況下,生成的是cpu的火焰圖,即event為cpu。可以用--event參數(shù)來指定
          profiler start
          # 獲取已采集的sample的數(shù)量
          profiler getSamples
          # 查看profiler狀態(tài)
          profiler status
          # 停止profiler 生成html格式結果,默認情況下,結果文件是html格式,也可以用--format參數(shù)指定;或者在--file參數(shù)里用文件名指名格式。比如--file /tmp/result.html
          profiler stop --format html
          

          通過瀏覽器查看arthas-output下面的profiler結果,http://192.168.50.100:3658/arthas-output/

          # profiler支持的events
          profiler list
          

          # 可以用--event參數(shù)指定要采樣的事件,比如對alloc事件進入采樣:
          profiler start --event alloc
          # 使用execute來執(zhí)行復雜的命令
          profiler execute 'start,framebuf=5000000'
          # 生成 jfr格式結果;注意,jfr只支持在 start時配置。如果是在stop時指定,則不會生效。
          profiler start --file /tmp/test.jfr
          # 配置 include/exclude 來過濾數(shù)據(jù)
          profiler start --include 'java/*' --include 'demo/*' --exclude '*Unsafe.park*'
          # profiler執(zhí)行 300 秒自動結束,可以用 -d/--duration 參數(shù)指定
          profiler start --duration 300
          

          其他功能

          • 提供Http API可以提供結構化的數(shù)據(jù),支持更復雜的交互功能,比如特定應用場景的一系列診斷操作。Http API接口地址為:http://ip:port/api**,必須使用POST方式提交請求參數(shù)。如POST **http://127.0.0.1:8563/api
          {
            "action": "exec",
            "requestId": "req112",
            "sessionId": "94766d3c-8b39-42d3-8596-98aee3ccbefb",
            "consumerId": "955dbd1325334a84972b0f3ac19de4f7_2",
            "command": "version",
            "execTimeout": "10000"
          }
          
          • docker使用,很多時候,應用在docker里出現(xiàn)arthas無法工作的問題,是因為應用沒有安裝 JDK ,而是安裝了 JRE 。如果只安裝了 JRE,則會缺少很多JAVA的命令行工具和類庫,Arthas也沒辦法正常工作,可以使用公開的JDK鏡像和包管理軟件來安裝這兩種方式在Docker里使用JDK。# 選擇需要監(jiān)控應用的進程編號,回車后Arthas會attach到目標進程上,并輸出日志: docker exec -it arthas-demo /bin/sh -c "java -jar /opt/arthas/arthas-boot.jar" # 甚至我們可以直接把arthas放到容器鏡像文件中:
          • Arthas Spring Boot Starter:應用啟動后,spring會啟動arthas,并且attach自身進程。 <dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-spring-boot-starter</artifactId> <version>${arthas.version}</version> </dependency>
          • 非spring boot應用使用方式
                  <dependency>
                      <groupId>com.taobao.arthas</groupId>
                      <artifactId>arthas-agent-attach</artifactId>
                      <version>${arthas.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>com.taobao.arthas</groupId>
                      <artifactId>arthas-packaging</artifactId>
                      <version>${arthas.version}</version>
                  </dependency>
          
          import com.taobao.arthas.agent.attach.ArthasAgent;
           
          public class ArthasAttachExample {
            
              public static void main(String[] args) {
                  ArthasAgent.attach();
              }
          }
          

          原文來自IT小神博客 http://www.itxiaoshen.cn

          rthas對于SpringBoot2的支持和監(jiān)控體系

          在SpringBoot2應用中加入arthas-spring-boot-starter后,Spring會啟動arthas服務,并且進行attach自身進程,并配合tunnel server實現(xiàn)遠程管理。這樣的方案非常適合在微服務容器環(huán)境中進行遠程診斷,在容器網(wǎng)絡環(huán)境中僅需要對外暴露tunnel server的端口。

          Arthas的監(jiān)控體系所需要的組件支持

          • Arthas Tunnel Server/Client(Java agent探針的管理和監(jiān)控,方便我們管理服務和探針)
          • Web Console

          什么是Arthas Tunnel

          在容器化部署的環(huán)境內部,Java進程可以是在不同的機器啟動的,想要使用Arthas去診斷會比較麻煩,因為用戶通常沒有機器的權限,即使登陸機器也分不清是哪個Java進程。在這種情況下,可以使用 Arthas Tunnel Server/Client。

          Arthas Tunnel的作用和目的

          整個Arthas的功能體系中,可以通過Arthas Tunnel Server/Client來遠程管理/連接多個Agent(也就代表著可以監(jiān)控多個JVM進程)。主要目的用于監(jiān)控和獲取目標的JVM的進程數(shù)據(jù)信息。

          下載部署Arthas tunnel server

          Github源碼倉庫下載

          下載地址Arthas tunnel server,目前最新版本為arthas-all-3.6.7版本,如下圖所示。

          針對于Arthas的安裝包進行下載資料進行介紹:

          • arthas-3.6.7.deb:主要用于debian操作系統(tǒng)去運行的安裝包
          • arthas-bin.zip:二進制可運行執(zhí)行包
          • arthas-doc.zip:針對于arthas的文檔
          • arthas-tunnel-server-3.6.7-fatjar.jar:Arthas tunnel server服務的Jar可以執(zhí)行包
          • Source code(zip):源碼zip壓縮包
          • Source code(tar.gz):源碼tar包

          Maven倉庫下載

          阿里云的下載地址:arthas.aliyun.com/download/ar…

          直接運行對應的Arthas tunnel server

          Arthas tunnel server是一個Spring boot fat jar 應用,直接java -jar啟動:

          java -jar  arthas-tunnel-server.jar
          復制代碼

          默認情況下,arthas tunnel server的web端口是8080,Arthas agent 連接的端口是7777

          打開WebConsole,分別輸入Arthas agent的ip(127.0.0.1)和port(7777),和SpringBoot應用里配置的agent-id(URJZ5L48RPBR2ALI5K4V),點Connect即可。

          Web Console

          如果希望可以通過瀏覽器連接Arthas服務,此時這里的Arthas服務指的不是Arthas tunnel server,Arthas是總體的服務控制端,發(fā)送指令的部分,而Arthas tunnel server屬于對接和管理agent的專門服務(依賴于Arthas Spring Boot Starter的服務)。

          出了CLI模式之外,Arthas目前支持 Web Console,用戶在attach成功之后,可以直接訪問:http://127.0.0.1:8563/。 可以填入 IP,遠程連接其它機器上的arthas。啟動之后,可以訪問 http://127.0.0.1:8080/ ,再通過agentId連接到已注冊的arthas agent 上,如下圖所示。

          通過Spring Boot的Endpoint,可以查看到具體的連接信息: http://127.0.0.1:8080/actuator/arthas ,

          登陸用戶名是arthas,密碼在 arthas tunnel server 的日志里可以找到,比如:

          注意:默認情況下,arthas 只 listen 127.0.0.1,所以如果想從遠程連接,則可以使用 --target-ip參數(shù)指定 listen 的 IP,更多參考-h的幫助說明。 注意會有安全風險,考慮下面的 tunnel server 的方案。

          如何將服務連接Arthas tunnel server

          主要有兩種模式連接Arthas tunnel server:

          1. 遠程運行的Arthas server連接Arthas tunnel server
          2. 遠程運行的Arthas Spring Boot Starter的agent探針服務連接Arthas tunnel server

          啟動 arthas 時連接到 tunnel server

          在啟動 arthas,可以傳遞--tunnel-server參數(shù),比如:

          as.sh --tunnel-server 'ws://127.0.0.1:7777/ws'
          復制代碼

          如果有特殊需求,可以通過--agent-id參數(shù)里指定 agentId。默認情況下,會生成隨機 ID。attach 成功之后,會打印出 agentId。

            ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
           /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
          |  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
          |  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
          `--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
          
          wiki      https://arthas.aliyun.com/doc
          tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
          version   3.1.2
          pid       86183
          time      2022-11-30 15:40:53
          id        URJZ5L48RPBR2ALI5K4V
          
          復制代碼

          即使是啟動時沒有連接到 tunnel server,也可以在后續(xù)自動重連成功之后,通過 session 命令來獲取 agentId:

          [arthas@86183]$ session
           Name           Value
          -----------------------------------------------------
           JAVA_PID       86183
           SESSION_ID     f7273eb5-e7b0-4a00-bc5b-3fe55d741882
           AGENT_ID       URJZ5L48RPBR2ALI5K4V
           TUNNEL_SERVER  ws://127.0.0.1:7777/ws
          復制代碼

          在瀏覽器里訪問 http://localhost:8080/arthas,輸入agentId,就可以連接到本機/其他機器上上的 arthas 了。

          tunnel server的注意要點

          • agentId要保持唯一,否則會在 tunnel server 上沖突,不能正常工作。
          • 如果arthas agent配置了appName,則生成的agentId會帶上appName的前綴。

          添加對應的app-name參數(shù)

          啟動參數(shù)

          as.sh --tunnel-server 'ws://127.0.0.1:7777/ws' --app-name demoapp ,則生成的 agentId 可能是demoapp_URJZ5L48RPBR2ALI5K4V。
          復制代碼

          Tunnel server 會以_做分隔符,提取出appName,方便按應用進行管理

          配置參數(shù)

          解壓的 arthas 目錄下的 arthas.properties,或者在 spring boot 應用的application.properties里配置appName。

          Arthas Spring Boot Starter的agent服務連接Jar

          只支持 springboot2

          • maven的倉庫地址:search.maven.org/search?q=a:…

          • 配置 maven 依賴:

          arthas.version:3.6.7

          <dependency>
               <groupId>com.taobao.arthas</groupId>
              <artifactId>arthas-spring-boot-starter</artifactId>
              <version>${arthas.version}</version>
          </dependency>
          復制代碼

          應用啟動后,spring 會啟動 arthas,并且 attach 自身進程。如果你不知道如何創(chuàng)建或者引入哪些依賴,可以采用一鍵創(chuàng)建包含 Arthas Spring Boot Starter 的工程:點擊跳轉到云原生腳手架

          可以看到最下面已經(jīng)自動勾選了arthas的監(jiān)控機制體系。

          application.yml配置

          arthas:
            agent-name: nihaotest
            agent-id: URJZ5L48RPBR2ALI5K4V  #需手工指定agent-id
            tunnel-server: ws://127.0.0.1:7777/ws
          復制代碼

          查看 Endpoint 信息

          需要配置 spring boot 暴露 endpoint:假定endpoint 端口是 8080,則通過下面 url 可以查看:

          http://localhost:8080/actuator/arthas

          {
              "arthasConfigMap": {
                  "agent-id": "hsehdfsfghhwertyfad",
                  "tunnel-server": "ws://47.75.156.201:7777/ws",
              }
          }
          復制代碼

          最后,啟動SpringBoot服務即可

          非 spring boot 應用使用方式

          非 Spring Boot 應用,可以通過下面的方式來使用:

           <dependency>
               <groupId>com.taobao.arthas</groupId>
               <artifactId>arthas-agent-attach</artifactId>
               <version>${arthas.version}</version>
           </dependency>
           <dependency>
                <groupId>com.taobao.arthas</groupId>
               <artifactId>arthas-packaging</artifactId>
               <version>${arthas.version}</version>
          </dependency>
          復制代碼

          attach本身的服務進行探針探測。

          import com.taobao.arthas.agent.attach.ArthasAgent;
          public class ArthasAttachExample {
          	public static void main(String[] args) {
          		ArthasAgent.attach();
          	}
          }
          復制代碼

          也可以配置屬性:

          HashMap<String, String> configMap = new HashMap<String, String>();
          configMap.put("arthas.appName", "demo");
          configMap.put("arthas.tunnelServer", "ws://127.0.0.1:7777/ws");
          ArthasAgent.attach(configMap);
          復制代碼

          Tunnel Server 的管理頁面

          需要在 spring boot 的application.properties里配置 arthas.enable-detail-pages=true

          注意,開放管理頁面有風險!管理頁面沒有安全攔截功能,務必自行增加安全措施。

          在本地啟動 tunnel-server,然后使用as.sh attach,并且指定應用名--app-name test:

          $ as.sh --tunnel-server 'ws://127.0.0.1:7777/ws' --app-name test
          telnet connecting to arthas server... current timestamp is 1627539688
          Trying 127.0.0.1...
          Connected to 127.0.0.1.
          Escape character is '^]'.
            ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
           /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
          |  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
          |  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
          `--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
          
          wiki       https://arthas.aliyun.com/doc
          tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
          version    3.5.3
          main_class demo.MathGame
          pid        65825
          time       2022-07-29 14:21:29
          id         test_PE3LZO9NA9ENJYTPGL9L
          
          復制代碼

          然后訪問 tunnel-server,可以看到所有連接的應用列表:

          http://localhost:8080/apps.html
          復制代碼

          再打開詳情,則可以看到連接的所有 agent 列表:

          http://localhost:8080/agents.html?app=test
          復制代碼


          鏈接:https://juejin.cn/post/7213744681393176633


          主站蜘蛛池模板: 中文字幕精品无码一区二区三区 | 国产主播一区二区三区 | 色婷婷亚洲一区二区三区 | 亚洲福利精品一区二区三区| 亚洲视频在线观看一区| 国产一区二区三区高清视频| 一区二区三区福利视频| 精品伦精品一区二区三区视频| 国产精品av一区二区三区不卡蜜| 99久久精品日本一区二区免费| 日韩精品一区二区三区中文| 精品无码人妻一区二区免费蜜桃| 国产午夜精品一区理论片飘花| 香蕉视频一区二区三区| 在线精品动漫一区二区无广告| 国产成人精品一区二区三区| 国产精华液一区二区区别大吗| 综合无码一区二区三区| 亚洲视频一区二区三区| 日韩一区二区在线免费观看| 久久精品一区二区三区中文字幕 | 久久无码人妻一区二区三区 | 中文字幕精品一区二区三区视频| 国产嫖妓一区二区三区无码| 香蕉久久AⅤ一区二区三区| 久久久久女教师免费一区| 日韩电影一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 中文精品一区二区三区四区 | 免费萌白酱国产一区二区| 日韩人妻无码一区二区三区| 亚洲综合色一区二区三区小说| 天天躁日日躁狠狠躁一区| 人妻无码久久一区二区三区免费 | 国产一区二区在线观看视频| 无码人妻AV免费一区二区三区| 国产福利一区二区| AV无码精品一区二区三区| 国产91一区二区在线播放不卡| 色婷婷香蕉在线一区二区| 国产亚洲3p无码一区二区|