Arthas
เป็นเครื่องมือวินิจฉัย Java โอเพ่นซอร์สโดย Alibaba
Arthas ช่วยให้นักพัฒนาแก้ไขปัญหาการผลิตสำหรับแอปพลิเคชัน Java โดยไม่ต้องแก้ไขโค้ดหรือรีสตาร์ทเซิร์ฟเวอร์
中文说明/เอกสารภาษาจีน
บ่อยครั้ง เครือข่ายระบบการผลิตไม่สามารถเข้าถึงได้จากสภาพแวดล้อมการพัฒนาท้องถิ่น หากพบปัญหาในระบบที่ใช้งานจริง จะไม่สามารถใช้ IDE เพื่อดีบักแอปพลิเคชันจากระยะไกลได้ ที่สำคัญกว่านั้น ไม่สามารถยอมรับการดีบักในสภาพแวดล้อมการผลิตได้ เนื่องจากจะระงับเธรดทั้งหมด ส่งผลให้บริการทางธุรกิจหยุดชะงัก
นักพัฒนาซอฟต์แวร์สามารถพยายามจำลองปัญหาเดียวกันในสภาพแวดล้อมการทดสอบ/จัดเตรียมได้เสมอ อย่างไรก็ตาม นี่เป็นเรื่องยุ่งยากเนื่องจากปัญหาบางอย่างไม่สามารถเกิดขึ้นซ้ำได้อย่างง่ายดายในสภาพแวดล้อมอื่น หรือแม้กระทั่งหายไปเมื่อรีสตาร์ทแล้ว
และหากคุณคิดจะเพิ่มบันทึกลงในโค้ดของคุณเพื่อช่วยแก้ไขปัญหา คุณจะต้องผ่านวงจรการใช้งานต่อไปนี้ ทดสอบ จัดเตรียม จากนั้นจึงเข้าสู่การใช้งานจริง เวลาคือเงิน! วิธีนี้ใช้ไม่ได้ผล! นอกจากนี้ ปัญหาอาจไม่เกิดขึ้นอีกเมื่อรีสตาร์ท JVM ตามที่อธิบายไว้ข้างต้น
Arthas ถูกสร้างขึ้นเพื่อแก้ไขปัญหาเหล่านี้ นักพัฒนาสามารถแก้ไขปัญหาการผลิตของคุณได้ทันที ไม่มีการรีสตาร์ท JVM ไม่มีการเปลี่ยนแปลงโค้ดเพิ่มเติม Arthas ทำงานเป็นผู้สังเกตการณ์ ซึ่งจะไม่มีวันระงับเธรดที่มีอยู่ของคุณ
arthas-boot
(แนะนำ) ดาวน์โหลด arthas-boot.jar
เริ่มต้นด้วยคำสั่ง java
:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
การใช้งานการพิมพ์:
java -jar arthas-boot.jar -h
as.sh
คุณสามารถติดตั้ง Arthas ด้วยคำสั่งบรรทัดเดียวบน Linux, Unix และ Mac คัดลอกคำสั่งต่อไปนี้และวางลงในบรรทัดคำสั่ง จากนั้นกด Enter เพื่อรัน:
curl -L https://arthas.aliyun.com/install.sh | sh
คำสั่งด้านบนจะดาวน์โหลดสคริปต์บูต as.sh
ไปยังไดเร็กทอรีปัจจุบัน คุณสามารถย้ายมันไปที่อื่นที่คุณต้องการหรือใส่ตำแหน่งของมันใน $PATH
คุณสามารถเข้าสู่อินเทอร์เฟซแบบโต้ตอบได้โดยดำเนินการ as.sh
หรือดำเนินการ as.sh -h
เพื่อดูข้อมูลความช่วยเหลือเพิ่มเติม
ดูว่ามีอะไรกิน CPU ของคุณ (จัดอันดับตามการใช้งาน CPU สูงสุด) และเกิดอะไรขึ้นโดยสรุป:
$ 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)
แยกส่วนชั้นเรียนของคุณด้วยช็อตเดียว:
$ 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 ();
}
คอมไพเลอร์หน่วยความจำ คอมไพล์ไฟล์ .java
ให้เป็นไฟล์ .class
ในหน่วยความจำ
$ mc /tmp/Test.java
โหลดไฟล์ *.class
ภายนอกเพื่อแปลงใหม่/hotswap คลาสที่โหลดใน JVM
retransform /tmp/Test.class
retransform -c 327a647b /tmp/Test.class /tmp/Test $ Inner.class
ค้นหาคลาสที่โหลดด้วยข้อมูลโดยละเอียด
$ 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
รับวัตถุในฮีปที่เป็นอินสแตนซ์ของคลาสที่ระบุ
$ 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],
]
ดู call stack ของ 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)
ดูว่าอะไรทำให้การเรียกใช้เมธอดของคุณช้าลงด้วยคำสั่งติดตาม:
ดูพารามิเตอร์แรกและส่งข้อยกเว้นของ test.arthas.TestWatch#doGet
เฉพาะในกรณีที่ส่งข้อยกเว้น
$ 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],
]
ตรวจสอบสถิติการเรียกใช้เมธอดเฉพาะ รวมถึงจำนวนการเรียกใช้ทั้งหมด เวลาตอบสนองโดยเฉลี่ย อัตราความสำเร็จ และทุกๆ 5 วินาที:
$ 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%
บันทึกข้อมูลการเรียกใช้เมธอด เพื่อให้คุณสามารถตรวจสอบพารามิเตอร์การเรียกใช้เมธอด ค่าที่ส่งคืน และข้อยกเว้นที่ส่งในภายหลัง มันทำงานเหมือนกับว่าคุณสามารถกลับมาเล่นซ้ำการเรียกใช้เมธอดที่ผ่านมาผ่านอุโมงค์เวลาได้
$ 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
ดูผลลัพธ์ของผู้สร้างโปรไฟล์ภายใต้ arthas-output ผ่านเบราว์เซอร์:
Arthas มีผู้ลงทะเบียนมากกว่า 120 ราย ดูทั้งหมด
ยินดีต้อนรับสู่การจดทะเบียนชื่อบริษัทในฉบับนี้ #111 (ตามลำดับการจดทะเบียน)
โครงการนี้มีอยู่ ขอบคุณทุกคนที่มีส่วนร่วม