Arthas
est un outil de diagnostic Java open source par Alibaba.
Arthas permet aux développeurs de résoudre les problèmes de production des applications Java sans modifier le code ni redémarrer les serveurs.
中文说明/Documentation chinoise
Souvent, le réseau du système de production est inaccessible depuis l’environnement de développement local. Si des problèmes surviennent dans les systèmes de production, il est impossible d'utiliser les IDE pour déboguer l'application à distance. Plus important encore, le débogage dans un environnement de production est inacceptable, car il suspendra tous les threads, entraînant la suspension des services métier.
Les développeurs peuvent toujours essayer de reproduire le même problème sur l'environnement de test/stade. Cependant, cela est délicat car certains problèmes ne peuvent pas être reproduits facilement sur un environnement différent, voire disparaître une fois redémarré.
Et si vous envisagez d'ajouter des journaux à votre code pour vous aider à résoudre le problème, vous devrez suivre le cycle de vie suivant : test, mise en scène, puis mise en production. Le temps, c'est de l'argent ! Cette approche est inefficace ! En outre, le problème peut ne pas être reproductible une fois la JVM redémarrée, comme décrit ci-dessus.
Arthas a été conçu pour résoudre ces problèmes. Un développeur peut résoudre vos problèmes de production à la volée. Pas de redémarrage de la JVM, aucune modification de code supplémentaire. Arthas fonctionne comme un observateur, qui ne suspendra jamais vos discussions existantes.
arthas-boot
(recommandé) Téléchargez arthas-boot.jar
, Commencez avec la commande java
:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
Utilisation de l'impression :
java -jar arthas-boot.jar -h
as.sh
Vous pouvez installer Arthas avec une seule ligne de commande sous Linux, Unix et Mac. Copiez la commande suivante et collez-la dans la ligne de commande, puis appuyez sur Entrée pour exécuter :
curl -L https://arthas.aliyun.com/install.sh | sh
La commande ci-dessus téléchargera le script d'amorçage as.sh
dans le répertoire actuel. Vous pouvez le déplacer n'importe où ou placer son emplacement dans $PATH
.
Vous pouvez accéder à son interface interactive en exécutant as.sh
, ou exécuter as.sh -h
pour plus d'informations d'aide.
Voyez ce qui consomme votre processeur (classé selon l'utilisation la plus importante du processeur) et ce qui s'y passe en un seul coup d'œil :
$ 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)
Décompilez votre classe d'un seul coup :
$ 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 ();
}
Compilateur de mémoire, compile les fichiers .java
en fichiers .class
en mémoire.
$ mc /tmp/Test.java
Chargez les fichiers *.class
externes pour retransformer/échanger à chaud les classes chargées dans JVM.
retransform /tmp/Test.class
retransform -c 327a647b /tmp/Test.class /tmp/Test $ Inner.class
Recherchez n’importe quelle classe chargée avec des informations détaillées.
$ 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
Récupère les objets du tas qui sont des instances de la classe spécifiée.
$ 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],
]
Afficher la pile d'appels de 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)
Découvrez ce qui ralentit l'invocation de votre méthode avec la commande trace :
Surveillez le premier paramètre et l'exception levée de test.arthas.TestWatch#doGet
uniquement s'il lève une exception.
$ 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],
]
Surveillez les statistiques d'appel d'une méthode spécifique, notamment le nombre total d'appels, le temps de réponse moyen, le taux de réussite et toutes les 5 secondes :
$ 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%
Enregistrez les données d'appel de méthode afin de pouvoir vérifier ultérieurement les paramètres d'appel de méthode, la valeur renvoyée et les exceptions levées. Cela fonctionne comme si vous pouviez revenir et rejouer l'appel de méthode passé via un tunnel temporel.
$ 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
Afficher les résultats du profileur sous arthas-output via le navigateur :
Arthas compte plus de 120 utilisateurs enregistrés, Voir tout.
Bienvenue pour enregistrer le nom de l'entreprise dans ce numéro : #111 (par ordre d'enregistrement)
Ce projet existe, grâce à toutes les personnes qui ont contribué.