Arthas
es una herramienta de diagnóstico Java de código abierto de Alibaba.
Arthas permite a los desarrolladores solucionar problemas de producción de aplicaciones Java sin modificar el código ni reiniciar los servidores.
中文说明/Documentación china
Muchas veces, la red del sistema de producción es inaccesible desde el entorno de desarrollo local. Si se encuentran problemas en los sistemas de producción, es imposible utilizar IDE para depurar la aplicación de forma remota. Más importante aún, la depuración en un entorno de producción es inaceptable, ya que suspenderá todos los subprocesos, lo que provocará la suspensión de los servicios comerciales.
Los desarrolladores siempre pueden intentar reproducir el mismo problema en el entorno de prueba/ensayo. Sin embargo, esto es complicado ya que algunos problemas no se pueden reproducir fácilmente en un entorno diferente, o incluso desaparecen una vez reiniciado.
Y si está pensando en agregar algunos registros a su código para ayudar a solucionar el problema, deberá pasar por el siguiente ciclo de vida; prueba, puesta en escena y luego a producción. ¡El tiempo es dinero! ¡Este enfoque es ineficiente! Además, es posible que el problema no se pueda reproducir una vez que se reinicia la JVM, como se describe anteriormente.
Arthas fue creado para resolver estos problemas. Un desarrollador puede solucionar sus problemas de producción sobre la marcha. Sin reinicio de JVM, sin cambios de código adicionales. Arthas trabaja como un observador, que nunca suspenderá los hilos existentes.
arthas-boot
(recomendado) Descargue arthas-boot.jar
, comience con el comando java
:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
Uso de impresión:
java -jar arthas-boot.jar -h
as.sh
Puede instalar Arthas con un comando de una sola línea en Linux, Unix y Mac. Copie el siguiente comando y péguelo en la línea de comando, luego presione Entrar para ejecutar:
curl -L https://arthas.aliyun.com/install.sh | sh
El comando anterior descargará el script de arranque as.sh
al directorio actual. Puedes moverlo a cualquier otro lugar que desees o poner su ubicación en $PATH
.
Puede ingresar a su interfaz interactiva ejecutando as.sh
o ejecutar as.sh -h
para obtener más información de ayuda.
Vea qué está consumiendo su CPU (clasificado según el mayor uso de CPU) y qué sucede allí de un vistazo:
$ 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)
Descompila tu clase de una sola vez:
$ 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 ();
}
Compilador de memoria, compila archivos .java
en archivos .class
en la memoria.
$ mc /tmp/Test.java
Cargue los archivos *.class
externos para retransformar/intercambiar en caliente las clases cargadas en JVM.
retransform /tmp/Test.class
retransform -c 327a647b /tmp/Test.class /tmp/Test $ Inner.class
Busque cualquier clase cargada con información detallada.
$ 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
Obtiene objetos en el montón que son instancias de la clase especificada.
$ 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],
]
Ver la pila de llamadas 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)
Vea qué está ralentizando la invocación de su método con el comando trace:
Observe el primer parámetro y la excepción lanzada de test.arthas.TestWatch#doGet
solo si arroja una excepción.
$ 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],
]
Supervise las estadísticas de invocación de un método específico, incluido el número total de invocaciones, el tiempo de respuesta promedio, la tasa de éxito y cada 5 segundos:
$ 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%
Registre los datos de invocación del método, para que pueda verificar los parámetros de invocación del método, el valor devuelto y las excepciones lanzadas más adelante. Funciona como si pudieras volver y reproducir la invocación del método anterior a través del túnel del tiempo.
$ 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
Vea los resultados del perfilador en arthas-output a través del navegador:
Arthas tiene más de 120 usuarios registrados, Ver todos.
Bienvenido a registrar el nombre de la empresa en esta edición: #111 (en orden de registro)
Este proyecto existe, gracias a todas las personas que contribuyeron.