diff --git a/site/src/site/sphinx/en/thread.md b/site/src/site/sphinx/en/thread.md index a99295528..416a0571e 100644 --- a/site/src/site/sphinx/en/thread.md +++ b/site/src/site/sphinx/en/thread.md @@ -1,6 +1,8 @@ thread ====== +[`thread` online tutorial](https://alibaba.github.io/arthas/arthas-tutorials?language=en&id=command-thread) + > Check the basic info and stack trace of the target thread. ### Parameters diff --git a/site/src/site/sphinx/thread.md b/site/src/site/sphinx/thread.md index f932795fe..c52c6a097 100644 --- a/site/src/site/sphinx/thread.md +++ b/site/src/site/sphinx/thread.md @@ -1,6 +1,8 @@ thread === +[`thread`在线教程](https://alibaba.github.io/arthas/arthas-tutorials?language=cn&id=command-thread) + > 查看当前线程信息,查看线程的堆栈 diff --git a/tutorials/katacoda/command-thread-cn/CPU-ratios-calculate.md b/tutorials/katacoda/command-thread-cn/CPU-ratios-calculate.md new file mode 100644 index 000000000..292d6b204 --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/CPU-ratios-calculate.md @@ -0,0 +1,6 @@ + +这里的cpu统计的是,一段采样间隔内,当前JVM里各个线程所占用的cpu时间占总cpu时间的百分比。其计算方法为: 首先进行一次采样,获得所有线程的cpu的使用时间(调用的是`java.lang.management.ThreadMXBean#getThreadCpuTime`这个接口),然后睡眠一段时间,默认100ms,可以通过`-i`参数指定,然后再采样一次,最后得出这段时间内各个线程消耗的cpu时间情况,最后算出百分比。 + +注意: 这个统计也会产生一定的开销(JDK这个接口本身开销比较大),因此会看到as的线程占用一定的百分比,为了降低统计自身的开销带来的影响,可以把采样间隔拉长一些,比如5000毫秒。 + +如果想看从Java进程启动开始到现在的cpu占比情况:可以使用[`show-busy-java-threads`](https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads)这个脚本 diff --git a/tutorials/katacoda/command-thread-cn/arthas-boot.md b/tutorials/katacoda/command-thread-cn/arthas-boot.md new file mode 100644 index 000000000..d53c8ff8a --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/arthas-boot.md @@ -0,0 +1,16 @@ + + + + +在新的`Terminal 2`里,下载`arthas-boot.jar`,再用`java -jar`命令启动: + +`wget https://alibaba.github.io/arthas/arthas-boot.jar +java -jar arthas-boot.jar --target-ip 0.0.0.0`{{execute T2}} + +`arthas-boot`是`Arthas`的启动程序,它启动后,会列出所有的Java进程,用户可以选择需要诊断的目标进程。 + +选择第一个进程,输入 `1`{{execute T2}} ,再`Enter/回车`: + +Attach成功之后,会打印Arthas LOGO。输入 `help`{{execute T2}} 可以获取到更多的帮助信息。 + +![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png) diff --git a/tutorials/katacoda/command-thread-cn/arthas-demo.md b/tutorials/katacoda/command-thread-cn/arthas-demo.md new file mode 100644 index 000000000..f1136e88e --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/arthas-demo.md @@ -0,0 +1,10 @@ + + + + +下载`arthas-demo.jar`,再用`java -jar`命令启动: + +`wget https://alibaba.github.io/arthas/arthas-demo.jar +java -jar arthas-demo.jar`{{execute T1}} + +`arthas-demo`是一个很简单的程序,它随机生成整数,再执行因式分解,把结果打印出来。如果生成的随机数是负数,则会打印提示信息。 diff --git a/tutorials/katacoda/command-thread-cn/finish.md b/tutorials/katacoda/command-thread-cn/finish.md new file mode 100644 index 000000000..107012025 --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/finish.md @@ -0,0 +1,12 @@ + +在“thread”中,我们演示了了Arthas的thread命令。如果有更多的技巧或者使用疑问,欢迎在Issue里提出。 + +* Issues: https://github.com/alibaba/arthas/issues +* 文档: https://alibaba.github.io/arthas + + +如果您在使用Arthas,请让我们知道,您的使用对我们非常重要:[查看](https://github.com/alibaba/arthas/issues/111) + +欢迎关注公众号,获取Arthas项目的信息,源码分析,案例实践。 + +![Arthas公众号](/arthas/scenarios/common-resources/assets/qrcode_gongzhonghao.jpg) \ No newline at end of file diff --git a/tutorials/katacoda/command-thread-cn/index.json b/tutorials/katacoda/command-thread-cn/index.json new file mode 100644 index 000000000..a9b18a444 --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/index.json @@ -0,0 +1,43 @@ +{ + "title": "Arthas thread命令", + "description": "Arthas thread命令", + "difficulty": "精通者", + "time": "10-20 分钟", + "details": { + "steps": [ + { + "title": "Arthas demo", + "text": "arthas-demo.md" + }, + { + "title": "启动arthas-boot", + "text": "arthas-boot.md" + }, + { + "title": "Thread命令", + "text": "thread.md" + }, + { + "title": "cpu占比是如何统计出来的?", + "text": "CPU-ratios-calculate.md" + }, + { + "title": "Thread用法", + "text": "thread-usage.md" + } + ], + "intro": { + "text": "intro.md" + }, + "finish": { + "text": "finish.md" + } + }, + "environment": { + "uilayout": "terminal" + }, + "backend": { + "imageid": "java", + "environmentsprotocol": "http" + } +} diff --git a/tutorials/katacoda/command-thread-cn/intro.md b/tutorials/katacoda/command-thread-cn/intro.md new file mode 100644 index 000000000..2263feb68 --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/intro.md @@ -0,0 +1,23 @@ + + + +![Arthas](https://alibaba.github.io/arthas/_images/arthas.png) + +`Arthas` 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。 + +`Arthas` 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 `Tab` 自动补全功能,进一步方便进行问题的定位和诊断。 + +当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决: + +- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? +- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? +- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? +- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! +- 是否有一个全局视角来查看系统的运行状况? +- 有什么办法可以监控到JVM的实时运行状态? +- 怎么快速定位应用的热点,生成火焰图? + +本教程会以一个普通的Spring Boot应用为例,演示thread命令。 + +* Github: https://github.com/alibaba/arthas +* 文档: https://alibaba.github.io/arthas/ diff --git a/tutorials/katacoda/command-thread-cn/thread-usage.md b/tutorials/katacoda/command-thread-cn/thread-usage.md new file mode 100644 index 000000000..17fce7390 --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/thread-usage.md @@ -0,0 +1,162 @@ + +### 支持一键展示当前最忙的前N个线程并打印堆栈: + +`thread -n 3`{{execute T2}} + +```bash +$ 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) +``` + +### 当没有参数时,显示所有线程的信息。 + +`thread`{{execute T2}} + +```bash +$ thread +Threads Total: 16, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 4, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTE DAEMON +30 as-command-execute-daemon system 9 RUNNABLE 72 0:0 false true +23 as-session-expire-daemon system 9 TIMED_WAIT 27 0:0 false true +22 Attach Listener system 9 RUNNABLE 0 0:0 false true +11 pool-2-thread-1 main 5 TIMED_WAIT 0 0:0 false false +12 Thread-2 main 5 RUNNABLE 0 0:0 false true +13 pool-3-thread-1 main 5 TIMED_WAIT 0 0:0 false false +25 as-selector-daemon system 9 RUNNABLE 0 0:0 false true +14 Thread-3 main 5 TIMED_WAIT 0 0:0 false false +26 pool-5-thread-1 system 5 WAITING 0 0:0 false false +15 Thread-4 main 5 RUNNABLE 0 0:0 false false +1 main main 5 WAITING 0 0:2 false false +2 Reference Handler system 10 WAITING 0 0:0 false true +3 Finalizer system 8 WAITING 0 0:0 false true +4 Signal Dispatcher system 9 RUNNABLE 0 0:0 false true +20 NonBlockingInputStreamThread main 5 WAITING 0 0:0 false true +21 Thread-8 main 5 RUNNABLE 0 0:0 false true +``` + +### thread id, 显示指定线程的运行堆栈 + +查看线程ID 16的栈: + +`thread 16`{{execute T2}} + +```bash +$ thread 1 +"main" Id=1 WAITING on java.util.concurrent.CountDownLatch$Sync@29fafb28 + at sun.misc.Unsafe.park(Native Method) + - waiting on java.util.concurrent.CountDownLatch$Sync@29fafb28 + at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304) + at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231) +``` + +### thread -b, 找出当前阻塞其他线程的线程 + +有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题, arthas提供了`thread -b`, 一键找出那个罪魁祸首。 + +`thread -b`{{execute T2}} + +```bash +$ thread -b +"http-bio-8080-exec-4" Id=27 TIMED_WAITING + at java.lang.Thread.sleep(Native Method) + at test.arthas.TestThreadBlocking.doGet(TestThreadBlocking.java:22) + - locked java.lang.Object@725be470 <---- but blocks 4 other threads! + 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 test.filter.TestDurexFilter.doFilter(TestDurexFilter.java:46) + 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:122) + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) + at com.taobao.tomcat.valves.ContextLoadFilterValve$FilterChainAdapter.doFilter(ContextLoadFilterValve.java:191) + at com.taobao.eagleeye.EagleEyeFilter.doFilter(EagleEyeFilter.java:81) + at com.taobao.tomcat.valves.ContextLoadFilterValve.invoke(ContextLoadFilterValve.java:150) + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) + 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:429) + at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085) + at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625) + at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) + - locked org.apache.tomcat.util.net.SocketWrapper@7127ee12 + 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) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@31a6493e +``` + +**注意**, 目前只支持找出synchronized关键字阻塞住的线程, 如果是`java.util.concurrent.Lock`, 目前还不支持。 + +### thread -i, 指定采样时间间隔 + +`thread -n 3 -i 5000`{{execute T2}} + +```bash +$ thread -n 3 -i 1000 +"as-command-execute-daemon" Id=4759 cpuUsage=23% RUNNABLE + at sun.management.ThreadImpl.dumpThreads0(Native Method) + at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440) + at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:133) + at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:79) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:96) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:27) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:125) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:122) + at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:332) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) + at java.lang.Thread.run(Thread.java:756) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@546aeec1 +... +``` + +### thread –state ,查看指定状态的线程 + +`thread --state WAITING`{{execute T2}} + +```bash +[arthas@28114]$ thread --state WAITING +Threads Total: 15, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 3, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRU DAEMON +198 AsyncAppender-Worker-arth system 9 WAITING 0 0:0 false true +3 Finalizer system 8 WAITING 0 0:0 false true +14 RMI Scheduler(0) system 9 WAITING 0 0:0 false true +2 Reference Handler system 10 WAITING 0 0:0 false true +204 pool-8-thread-1 system 5 WAITING 0 0:0 false false +``` diff --git a/tutorials/katacoda/command-thread-cn/thread.md b/tutorials/katacoda/command-thread-cn/thread.md new file mode 100644 index 000000000..2d369ae04 --- /dev/null +++ b/tutorials/katacoda/command-thread-cn/thread.md @@ -0,0 +1,11 @@ + +查看当前线程信息,查看线程的堆栈 + +### 参数说明 + +| 参数名称 | 参数说明 | +| ---- | ---- | +| id | 线程id | +| [n:] | 指定最忙的前N个线程并打印堆栈 | +| [b] | 找出当前阻塞其他线程的线程 | +| [i ] | 指定cpu占比统计的采样间隔,单位为毫秒 | diff --git a/tutorials/katacoda/command-thread-en/CPU-ratios-calculate.md b/tutorials/katacoda/command-thread-en/CPU-ratios-calculate.md new file mode 100644 index 000000000..3a408eaf3 --- /dev/null +++ b/tutorials/katacoda/command-thread-en/CPU-ratios-calculate.md @@ -0,0 +1,6 @@ + +CPU ratio for a given thread is the CPU time it takes divided by the total CPU time within a specified interval period. It is calculated in the following way: sample CPU times for all the thread by calling `java.lang.management.ThreadMXBean#getThreadCpuTime` first, then sleep for a period (the default value is 100ms, which can be specified by `-i`), then sample CPU times again. By this, we can get the time cost for this period for each thread, then come up with the ratio. + +**Note**: this operation consumes CPU time too (getThreadCpuTime is time-consuming), therefore it is possible to observe Arthas’s thread appears in the list. To avoid this, try to increase sample interval, for example: 5000 ms. + +If you’d like to check the CPU ratios from the very beginning of the Java process, [`show-busy-java-threads`](https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#-show-busy-java-threads) can come to help. diff --git a/tutorials/katacoda/command-thread-en/arthas-boot.md b/tutorials/katacoda/command-thread-en/arthas-boot.md new file mode 100644 index 000000000..29c6aa95e --- /dev/null +++ b/tutorials/katacoda/command-thread-en/arthas-boot.md @@ -0,0 +1,16 @@ + + + + +In the new `Terminal 2`, download `arthas-boot.jar` and start with the `java -jar` command: + +`wget https://alibaba.github.io/arthas/arthas-boot.jar +java -jar arthas-boot.jar --target-ip 0.0.0.0`{{execute T2}} + +`arthas-boot` is the launcher for `Arthas`. It lists all the Java processes, and the user can select the target process to be diagnosed. + +Select the first process, type `1`{{execute T2}} ,then type `Enter`: + +After the Attach is successful, Arthas LOGO is printed. Enter `help`{{execute T2}} for more help. + +![Arthas Boot](/arthas/scenarios/common-resources/assets/arthas-boot.png) diff --git a/tutorials/katacoda/command-thread-en/arthas-demo.md b/tutorials/katacoda/command-thread-en/arthas-demo.md new file mode 100644 index 000000000..7ba2cf1fa --- /dev/null +++ b/tutorials/katacoda/command-thread-en/arthas-demo.md @@ -0,0 +1,11 @@ + + + + +Download `arthas-demo.jar` and start with the `java -jar` command: + +`wget https://alibaba.github.io/arthas/arthas-demo.jar +java -jar arthas-demo.jar`{{execute T1}} + +`arthas-demo` is a very simple program that randomly generates integers, performs factorization, and prints the results. +If the generated random number is negative, a error message will be printed. diff --git a/tutorials/katacoda/command-thread-en/finish.md b/tutorials/katacoda/command-thread-en/finish.md new file mode 100644 index 000000000..22a2bc239 --- /dev/null +++ b/tutorials/katacoda/command-thread-en/finish.md @@ -0,0 +1,8 @@ + +The `thread Tutorial` demonstrates the usage of thread. If you have more tips or questions, please feel free to ask in Issue. + +* Issues: https://github.com/alibaba/arthas/issues +* Documentation: https://alibaba.github.io/arthas + + +If you are using Arthas, please let us know. Your use is very important to us: [View](https://github.com/alibaba/arthas/issues/111) \ No newline at end of file diff --git a/tutorials/katacoda/command-thread-en/index.json b/tutorials/katacoda/command-thread-en/index.json new file mode 100644 index 000000000..b65bf56b7 --- /dev/null +++ b/tutorials/katacoda/command-thread-en/index.json @@ -0,0 +1,43 @@ +{ + "title": "Arthas thread Command", + "description": "Arthas thread Command", + "difficulty": "master", + "time": "10-20 minutes", + "details": { + "steps": [ + { + "title": "Arthas demo", + "text": "arthas-demo.md" + }, + { + "title": "Start arthas-boot", + "text": "arthas-boot.md" + }, + { + "title": "Thread Command", + "text": "thread.md" + }, + { + "title": "How the CPU ratios are calculated?", + "text": "CPU-ratios-calculate.md" + }, + { + "title": "Thread Usage", + "text": "thread-usage.md" + } + ], + "intro": { + "text": "intro.md" + }, + "finish": { + "text": "finish.md" + } + }, + "environment": { + "uilayout": "terminal" + }, + "backend": { + "imageid": "java", + "environmentsprotocol": "http" + } +} diff --git a/tutorials/katacoda/command-thread-en/intro.md b/tutorials/katacoda/command-thread-en/intro.md new file mode 100644 index 000000000..40865913a --- /dev/null +++ b/tutorials/katacoda/command-thread-en/intro.md @@ -0,0 +1,40 @@ + + + +![Arthas](https://alibaba.github.io/arthas/_images/arthas.png) + +`Arthas` is a Java diagnostic tool open-sourced by Alibaba middleware team. Arthas helps developers in trouble-shooting issues in production environment for Java based applications without modifying code or restarting servers. + +`Arthas` supports JDK 6+, supports Linux/Mac/Windows. + +## Background + +Oftentimes the production system network is inaccessible from local development environment. If issues are encountered in production systems, it is impossible to use IDE to debug the application remotely. What’s even worse, debugging in production environment is unacceptable, as it will suspend all the threads, leading to services downtime. + +Developers could always try to reproduce the same issue on the test/staging environment. However, this is tricky as some issues cannot be reproduced easily in a different environment, or even disappear once restarted. + +And if you’re thinking of adding some logs to your code to help trouble-shoot the issue, you will have to go through the following lifecycle: test, staging, and then to production. Time is money! This approach is inefficient! Worse still, the issue may not be fixed since it might be irreproducible once the JVM is restarted, as described above. + +Arthas is built to solve these issues. A developer can troubleshoot production issues on the fly. No JVM restart, no additional code changes. Arthas works as an observer, that is, it will never suspend your running threads. + +## Key features + +- Check whether a class is loaded? Or where the class is loaded from? (Useful for trouble-shooting jar file conflicts) +- Decompile a class to ensure the code is running as expected. +- Check classloader statistics, e.g. the number of classloaders, the number of classes loaded per classloader, the classloader hierarchy, possible classloader leaks, etc. +- Check the method invocation details, e.g. method parameter, returned values, exceptions and etc. +- Check the stack trace of specified method invocation. This is useful when a developer wants to know the caller of the method. +- Trace the method invocation to find slow sub-invocations. +- Monitor method invocation statistics, e.g. QPS (Query Per Second), RT (Return Time), success rate and etc. +- Monitor system metrics, thread states and CPU usage, GC statistics and etc. +- Supports command line interactive mode, with auto-complete feature enabled. +- Supports telnet and WebSocket, which enables both local and remote diagnostics with command line and browsers. +- Supports profiler/Flame Graph +- Supports JDK 6+ +- Supports Linux/Mac/Windows + +This tutorial takes a normal Spring Boot application as an example to demonstrate the the usage of thread. + +* Github: https://github.com/alibaba/arthas +* Docs: https://alibaba.github.io/arthas/ + diff --git a/tutorials/katacoda/command-thread-en/thread-usage.md b/tutorials/katacoda/command-thread-en/thread-usage.md new file mode 100644 index 000000000..bb12c6797 --- /dev/null +++ b/tutorials/katacoda/command-thread-en/thread-usage.md @@ -0,0 +1,162 @@ + +### List the top n busiest threads with detailed stack trace + +`thread -n 3`{{execute T2}} + +```bash +$ 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) +``` + +### List all threads’ info when no options provided + +`thread`{{execute T2}} + +```bash +$ thread +Threads Total: 16, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 4, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTE DAEMON +30 as-command-execute-daemon system 9 RUNNABLE 72 0:0 false true +23 as-session-expire-daemon system 9 TIMED_WAIT 27 0:0 false true +22 Attach Listener system 9 RUNNABLE 0 0:0 false true +11 pool-2-thread-1 main 5 TIMED_WAIT 0 0:0 false false +12 Thread-2 main 5 RUNNABLE 0 0:0 false true +13 pool-3-thread-1 main 5 TIMED_WAIT 0 0:0 false false +25 as-selector-daemon system 9 RUNNABLE 0 0:0 false true +14 Thread-3 main 5 TIMED_WAIT 0 0:0 false false +26 pool-5-thread-1 system 5 WAITING 0 0:0 false false +15 Thread-4 main 5 RUNNABLE 0 0:0 false false +1 main main 5 WAITING 0 0:2 false false +2 Reference Handler system 10 WAITING 0 0:0 false true +3 Finalizer system 8 WAITING 0 0:0 false true +4 Signal Dispatcher system 9 RUNNABLE 0 0:0 false true +20 NonBlockingInputStreamThread main 5 WAITING 0 0:0 false true +21 Thread-8 main 5 RUNNABLE 0 0:0 false true +``` + +### thread id, show the running stack for the target thread + +View the stack of thread ID 16: + +`thread 16`{{execute T2}} + +```bash +$ thread 1 +"main" Id=1 WAITING on java.util.concurrent.CountDownLatch$Sync@29fafb28 + at sun.misc.Unsafe.park(Native Method) + - waiting on java.util.concurrent.CountDownLatch$Sync@29fafb28 + at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997) + at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304) + at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231) +``` + +### thread -b, locate the thread bocking the others + +In some occasions, we experience the whole application is stuck because there’s one particular thread hold one lock that other threads are relying on. To diagnose such an issue, Arthas provides thread -b to find the problematic thread in one single command. + +`thread -b`{{execute T2}} + +```bash +$ thread -b +"http-bio-8080-exec-4" Id=27 TIMED_WAITING + at java.lang.Thread.sleep(Native Method) + at test.arthas.TestThreadBlocking.doGet(TestThreadBlocking.java:22) + - locked java.lang.Object@725be470 <---- but blocks 4 other threads! + 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 test.filter.TestDurexFilter.doFilter(TestDurexFilter.java:46) + 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:122) + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) + at com.taobao.tomcat.valves.ContextLoadFilterValve$FilterChainAdapter.doFilter(ContextLoadFilterValve.java:191) + at com.taobao.eagleeye.EagleEyeFilter.doFilter(EagleEyeFilter.java:81) + at com.taobao.tomcat.valves.ContextLoadFilterValve.invoke(ContextLoadFilterValve.java:150) + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) + 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:429) + at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085) + at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625) + at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) + - locked org.apache.tomcat.util.net.SocketWrapper@7127ee12 + 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) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@31a6493e +``` + +**Note**: By now Arthas only supports to locate the thread blocked by synchronzied, while `java.util.concurrent.Lock` is not supported yet. + +### thread -i, specify the sampling interval + +`thread -n 3 -i 5000`{{execute T2}} + +```bash +$ thread -n 3 -i 1000 +"as-command-execute-daemon" Id=4759 cpuUsage=23% RUNNABLE + at sun.management.ThreadImpl.dumpThreads0(Native Method) + at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:440) + at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:133) + at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:79) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:96) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:27) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:125) + at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:122) + at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:332) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) + at java.lang.Thread.run(Thread.java:756) + + Number of locked synchronizers = 1 + - java.util.concurrent.ThreadPoolExecutor$Worker@546aeec1 +... +``` + +### thread –state , view the special state theads + +`thread --state WAITING`{{execute T2}} + +```bash +[arthas@28114]$ thread --state WAITING +Threads Total: 15, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 3, TERMINATED: 0 +ID NAME GROUP PRIORITY STATE %CPU TIME INTERRU DAEMON +198 AsyncAppender-Worker-arth system 9 WAITING 0 0:0 false true +3 Finalizer system 8 WAITING 0 0:0 false true +14 RMI Scheduler(0) system 9 WAITING 0 0:0 false true +2 Reference Handler system 10 WAITING 0 0:0 false true +204 pool-8-thread-1 system 5 WAITING 0 0:0 false false +``` diff --git a/tutorials/katacoda/command-thread-en/thread.md b/tutorials/katacoda/command-thread-en/thread.md new file mode 100644 index 000000000..4c09defda --- /dev/null +++ b/tutorials/katacoda/command-thread-en/thread.md @@ -0,0 +1,14 @@ + + +## thread + +Check the basic info and stack trace of the target thread. + +### Parameters + +| Name | Specification | +| ---- | ---- | +| id | thread id in JVM | +| [n:] | the top n busiest threads with stack traces printed | +| [b] | locate the thread blocking the others | +| [i ] | specify the interval to collect data to compute CPU ratios (ms) |