Arthas
ist ein Open-Source-Java-Diagnosetool von Alibaba.
Mit Arthas können Entwickler Produktionsprobleme für Java-Anwendungen beheben, ohne Code zu ändern oder Server neu zu starten.
中文说明/Chinesische Dokumentation
Oftmals ist das Netzwerk des Produktionssystems von der lokalen Entwicklungsumgebung aus nicht zugänglich. Wenn in Produktionssystemen Probleme auftreten, ist es nicht möglich, IDEs zum Remote-Debuggen der Anwendung zu verwenden. Noch wichtiger ist, dass das Debuggen in der Produktionsumgebung nicht akzeptabel ist, da dadurch alle Threads angehalten werden, was zur Unterbrechung der Geschäftsdienste führt.
Entwickler könnten immer versuchen, das gleiche Problem in der Test-/Staging-Umgebung zu reproduzieren. Dies ist jedoch schwierig, da einige Probleme nicht einfach in einer anderen Umgebung reproduziert werden können oder sogar nach einem Neustart verschwinden.
Und wenn Sie darüber nachdenken, einige Protokolle zu Ihrem Code hinzuzufügen, um das Problem zu beheben, müssen Sie den folgenden Lebenszyklus durchlaufen: Test, Staging und dann zur Produktion. Zeit ist Geld! Dieser Ansatz ist ineffizient! Außerdem ist das Problem möglicherweise nicht reproduzierbar, wenn die JVM wie oben beschrieben neu gestartet wird.
Arthas wurde gebaut, um diese Probleme zu lösen. Ein Entwickler kann Ihre Produktionsprobleme im Handumdrehen beheben. Kein JVM-Neustart, keine zusätzlichen Codeänderungen. Arthas fungiert als Beobachter, der Ihre bestehenden Threads niemals unterbrechen wird.
arthas-boot
(empfohlen) Laden Sie arthas-boot.jar
herunter. Starten Sie mit java
-Befehl:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
Drucknutzung:
java -jar arthas-boot.jar -h
as.sh
Sie können Arthas mit einem einzigen Zeilenbefehl unter Linux, Unix und Mac installieren. Kopieren Sie den folgenden Befehl, fügen Sie ihn in die Befehlszeile ein und drücken Sie dann die Eingabetaste , um ihn auszuführen:
curl -L https://arthas.aliyun.com/install.sh | sh
Der obige Befehl lädt das Bootstrap-Skript as.sh
in das aktuelle Verzeichnis herunter. Sie können es an einen beliebigen anderen Ort verschieben oder seinen Speicherort in $PATH
angeben.
Sie können die interaktive Schnittstelle aufrufen, indem Sie as.sh
ausführen oder as.sh -h
ausführen, um weitere Hilfeinformationen zu erhalten.
Sehen Sie auf einen Blick, was Ihre CPU verbraucht (nach höchster CPU-Auslastung geordnet) und was dort vor sich geht:
$ thread -n 3
" as-command-execute-daemon " Id=29 cpuUsage=75% RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440)
at com.taobao.arthas.core.command.monitor200.ThreadCommand $1 .action(ThreadCommand.java:58)
at com.taobao.arthas.core.command.handler.AbstractCommandHandler.execute(AbstractCommandHandler.java:238)
at com.taobao.arthas.core.command.handler.DefaultCommandHandler.handleCommand(DefaultCommandHandler.java:67)
at com.taobao.arthas.core.server.ArthasServer $4 .run(ArthasServer.java:276)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor $Worker .run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Number of locked synchronizers = 1
- java.util.concurrent.ThreadPoolExecutor $Worker @6cd0b6f8
" as-session-expire-daemon " Id=25 cpuUsage=24% TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.taobao.arthas.core.server.DefaultSessionManager $2 .run(DefaultSessionManager.java:85)
" Reference Handler " Id=2 cpuUsage=0% WAITING on java.lang.ref.Reference $Lock @69ba0f27
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference $Lock @69ba0f27
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference $ReferenceHandler .run(Reference.java:133)
Dekompilieren Sie Ihre Klasse mit einem Schuss:
$ jad javax . servlet . Servlet
ClassLoader :
+- java . net . URLClassLoader @ 6108 b2d7
+- sun . misc . Launcher$AppClassLoader @ 18 b4aac2
+- sun . misc . Launcher$ExtClassLoader @ 1d df84b8
Location :
/ Users / xxx / work / test / lib / servlet - api . jar
/*
* Decompiled with CFR 0_122.
*/
package javax . servlet ;
import java . io . IOException ;
import javax . servlet . ServletConfig ;
import javax . servlet . ServletException ;
import javax . servlet . ServletRequest ;
import javax . servlet . ServletResponse ;
public interface Servlet {
public void init ( ServletConfig var1 ) throws ServletException ;
public ServletConfig getServletConfig ();
public void service ( ServletRequest var1 , ServletResponse var2 ) throws ServletException , IOException ;
public String getServletInfo ();
public void destroy ();
}
Speicher-Compiler, kompiliert .java
Dateien in .class
Dateien im Speicher.
$ mc /tmp/Test.java
Laden Sie die externen *.class
Dateien, um die geladenen Klassen in der JVM erneut zu transformieren/im laufenden Betrieb auszutauschen.
retransform /tmp/Test.class
retransform -c 327a647b /tmp/Test.class /tmp/Test $ Inner.class
Durchsuchen Sie jede geladene Klasse mit detaillierten Informationen.
$ sc -d org.springframework.web.context.support.XmlWebApplicationContext
class-info org.springframework.web.context.support.XmlWebApplicationContext
code-source /Users/xxx/work/test/WEB-INF/lib/spring-web-3.2.11.RELEASE.jar
name org.springframework.web.context.support.XmlWebApplicationContext
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name XmlWebApplicationContext
modifier public
annotation
interfaces
super-class +-org.springframework.web.context.support.AbstractRefreshableWebApplicationContext
+-org.springframework.context.support.AbstractRefreshableConfigApplicationContext
+-org.springframework.context.support.AbstractRefreshableApplicationContext
+-org.springframework.context.support.AbstractApplicationContext
+-org.springframework.core.io.DefaultResourceLoader
+-java.lang.Object
class-loader +-org.apache.catalina.loader.ParallelWebappClassLoader
+-java.net.URLClassLoader@6108b2d7
+-sun.misc.Launcher $AppClassLoader @18b4aac2
+-sun.misc.Launcher $ExtClassLoader @1ddf84b8
classLoaderHash 25131501
Ruft Objekte im Heap ab, die Instanzen der angegebenen Klasse sind.
$ vmtool --action getInstances --className java.lang.String --limit 10
@String[][
@String[com/taobao/arthas/core/shell/session/Session],
@String[com.taobao.arthas.core.shell.session.Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/taobao/arthas/core/shell/session/Session.class],
@String[com/],
@String[java/util/concurrent/ConcurrentHashMap $ValueIterator ],
@String[java/util/concurrent/locks/LockSupport],
]
Sehen Sie sich den Aufrufstapel von test.arthas.TestStack#doGet
:
$ stack test.arthas.TestStack doGet
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 286 ms.
ts=2018-09-18 10:11:45 ; thread_name=http-bio-8080-exec-10 ; id=d9 ; is_daemon=true ; priority=5 ; TCCL=org.apache.catalina.loader.ParallelWebappClassLoader@25131501
@test.arthas.TestStack.doGet ()
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
...
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:451)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1121)
at org.apache.coyote.AbstractProtocol $AbstractConnectionHandler .process(AbstractProtocol.java:637)
at org.apache.tomcat.util.net.JIoEndpoint $SocketProcessor .run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor $Worker .run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread $WrappingRunnable .run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Sehen Sie mit dem Trace-Befehl, was Ihren Methodenaufruf verlangsamt:
Beobachten Sie den ersten Parameter und die ausgelöste Ausnahme von test.arthas.TestWatch#doGet
nur, wenn er eine Ausnahme auslöst.
$ watch test.arthas.TestWatch doGet {params[0], throwExp} -e
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 65 ms.
ts=2018-09-18 10:26:28 ; result=@ArrayList[
@RequestFacade[org.apache.catalina.connector.RequestFacade@79f922b2],
@NullPointerException[java.lang.NullPointerException],
]
Überwachen Sie die Aufrufstatistik einer bestimmten Methode, einschließlich der Gesamtzahl der Aufrufe, der durchschnittlichen Antwortzeit, der Erfolgsrate und alle 5 Sekunden:
$ monitor -c 5 org.apache.dubbo.demo.provider.DemoServiceImpl sayHello
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 109 ms.
timestamp class method total success fail avg-rt(ms) fail-rate
----------------------------------------------------------------------------------------------------------------------------
2018-09-20 09:45:32 org.apache.dubbo.demo.provider.DemoServiceImpl sayHello 5 5 0 0.67 0.00%
timestamp class method total success fail avg-rt(ms) fail-rate
----------------------------------------------------------------------------------------------------------------------------
2018-09-20 09:45:37 org.apache.dubbo.demo.provider.DemoServiceImpl sayHello 5 5 0 1.00 0.00%
timestamp class method total success fail avg-rt(ms) fail-rate
----------------------------------------------------------------------------------------------------------------------------
2018-09-20 09:45:42 org.apache.dubbo.demo.provider.DemoServiceImpl sayHello 5 5 0 0.43 0.00%
Zeichnen Sie Methodenaufrufdaten auf, damit Sie die Methodenaufrufparameter, den zurückgegebenen Wert und die ausgelösten Ausnahmen später überprüfen können. Es funktioniert so, als ob Sie zurückkommen und den vergangenen Methodenaufruf über einen Zeittunnel erneut abspielen könnten.
$ tt -t org.apache.dubbo.demo.provider.DemoServiceImpl sayHello
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 75 ms.
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
-------------------------------------------------------------------------------------------------------------------------------------
1000 2018-09-20 09:54:10 1.971195 true false 0x55965cca DemoServiceImpl sayHello
1001 2018-09-20 09:54:11 0.215685 true false 0x55965cca DemoServiceImpl sayHello
1002 2018-09-20 09:54:12 0.236303 true false 0x55965cca DemoServiceImpl sayHello
1003 2018-09-20 09:54:13 0.159598 true false 0x55965cca DemoServiceImpl sayHello
1004 2018-09-20 09:54:14 0.201982 true false 0x55965cca DemoServiceImpl sayHello
1005 2018-09-20 09:54:15 0.214205 true false 0x55965cca DemoServiceImpl sayHello
1006 2018-09-20 09:54:16 0.241863 true false 0x55965cca DemoServiceImpl sayHello
1007 2018-09-20 09:54:17 0.305747 true false 0x55965cca DemoServiceImpl sayHello
1008 2018-09-20 09:54:18 0.18468 true false 0x55965cca DemoServiceImpl sayHello
$ classloader
name numberOfInstances loadedCountTotal
BootstrapClassLoader 1 3346
com.taobao.arthas.agent.ArthasClassloader 1 1262
java.net.URLClassLoader 2 1033
org.apache.catalina.loader.ParallelWebappClassLoader 1 628
sun.reflect.DelegatingClassLoader 166 166
sun.misc.Launcher $AppClassLoader 1 31
com.alibaba.fastjson.util.ASMClassLoader 6 15
sun.misc.Launcher $ExtClassLoader 1 7
org.jvnet.hk2.internal.DelegatingClassLoader 2 2
sun.reflect.misc.MethodUtil 1 1
$ profiler start
Started [cpu] profiling
$ profiler stop
profiler output file: /tmp/demo/arthas-output/20211207-111550.html
OK
Profiler-Ergebnisse unter arthas-output über den Browser anzeigen:
Arthas hat mehr als 120 registrierte Benutzer, Alle anzeigen.
Willkommen bei der Eintragung des Firmennamens in dieser Ausgabe: Nr. 111 (in der Reihenfolge der Eintragung)
Dieses Projekt existiert, dank aller Menschen, die dazu beigetragen haben.