An overview,
Deploying projects with Docker container has become a skill that developers must master. After deploying projects with Docker container, how to conduct real-time diagnosis of Java applications in the container is mainly introduced in this article. There is not much difference between using Arthas in a container and using it on a server. Normally there is only one Java process running in a container, our application service, so using Arthas in a container will only see one Java process. For detailed description of Arthas, please see the official document below. Here, we will only introduce the Arthas commands that we have used in docker containers through cases.
This article deals with the following:
- Change the log level in real time
- View method call input and output parameters in real time
- Live online hot update code
Arthas Chinese documentation: arthas.gitee. IO /
Install Arthas in a Docker container
Build the Docker container
This is done using a Spring Boot demo that includes only one controller:
@Slf4j
@RestController
public class TestController {
@GetMapping("hello/{content}")
public String hello(@PathVariable(value = "content") String content) {
log.debug("----------log debug----------");
log.info("----------log info----------");
log.warn("----------log warn----------");
log.error("----------log error----------");
return "Return result:"+ content; }}Copy the code
The Dockerfile for building the image is as follows:
FROM openjdk:8u232-jdk
WORKDIR /app
LABEL maintainer="peterwd" app="devops-demo"
COPY target/devops-demo.jar devops-demo.jar
EXPOSE 8080
CMD java -jar devops-demo.jar
Copy the code
Run the following command to build an image:
docker build -t devops-demo .
Copy the code
Start the container with the following command:
docker run --name devop-demo -d -p 8080:8080 devops-demo
Copy the code
After building the image, use the following command to enter the Docker container:
docker exec -it devops-demo bash
Copy the code
2. Install Arthas
Once inside the Docker container, install Arthas using the following command:
wget https://arthas.aliyun.com/arthas-boot.jar
Copy the code
Run the following command to start Arthas:
java -jar arthas-boot.jar
Copy the code
In the process of starting Arthas, the corresponding Java process will be selected. There is usually only one Java process in the Docker container, so 1 is ok. If there are multiple Java processes, enter the previous number. As shown in the figure below:
Introduction to Arthas commands
Please note that these commands, through the bytecode enhancement technology to realize, will insert some aspects in the specified class methods to implement the data statistics and observation, so online, use pretest, please try to clear need classes, methods and conditions for observation, diagnosis end to stop or will enhance the reset command.
1. Basic commands
Help — Displays the help information about the command
Cat — prints the contents of the file, similar to the cat command in Linux
Echo – Prints parameters, similar to the Echo command in Linux
Grep – match lookup, similar to the Linux grep command
Base64 — Base64 encoding conversion, similar to the Base64 command in Linux
Tee – copies standard input to standard output and the specified file, similar to the Linux tee command
PWD — Returns the current working directory, similar to the Linux command
CLS — Clears the current screen area
Session — Displays information about the current session
Reset — resets the enhanced classes. All Arthas enhanced classes are restored. All Arthas enhanced classes are reset when the Arthas server is shut down
Version — Prints the Arthas version number loaded by the current target Java process
History — Prints the command history
Quit: Quit the current Arthas client. Other Arthas clients are not affected
Stop: Stops the Arthas server and all Arthas clients exit
Keymap — Arthas shortcut key list and custom shortcut keys
2. JVM related commands
Dashboard – A real-time data panel for the current system
Thread — View the thread stack information for the current JVM
JVM – View information about the current JVM
Sysprop – View and modify system properties of the JVM
Sysenv — Look at the ENVIRONMENT variables for the JVM
Vmoption – View and modify diagnostic related options in the JVM
Perfcounter — View Perf Counter information for the current JVM
Logger – View and modify Logger
Getstatic — Looks at the static properties of the class
Ognl — Executes ogNL expressions
Mbean – View information about mBeans
Heapdump — dumps Java Heap, similar to the heapdump function of the jmap command
Vmtool — Queries objects from the JVM and executes forceGc
3. Class/ClassLoader commands
Sc — View information about classes loaded by the JVM
Sm — View method information for loaded classes
Jad — decompiles the source code for the specified loaded class
MC — memory compiler that compiles. Java files to. Class files
Retransform – load the external.class file and retransform into the JVM (recommended)
Re-define — load the external.class file, re-define into the JVM
Dump — Dumps the loaded class’s byte code to a specific directory
Classloader – View classloader inheritance tree, urls, class loading information, use classLoader to go to getResource
4. Monitor /watch/trace related commands
Monitor — Method to perform monitoring
The watch — method performs data observation
Trace — The method calls the path internally and prints the time on each node on the method path
Stack — Prints the call path where the current method is called
The tt – method performs a time tunnel of data, recording the incoming parameters and return information of each call to the specified method, and observing these different calls at different times
3. Using Arthaslogger
Change the log level of a class in real time
Previously, Arthas commands were briefly introduced. Here, we mainly describe how to use Arthas logger to change the log level of the class in real time. The demo used here defines four log levels: DEBUG, INFO, WARN, and Error. You can dynamically change different log levels to control the display of logs.
Log4j defines eight levels OF log (excluding OFF and ALL) with the following priorities: OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, and ALL.
If the log level is set to a certain level, logs with higher priority than this level can be printed. For example, if the priority of logs is set to WARN, logs of the OFF, FATAL, ERROR, and WARN levels are printed normally, but logs of the INFO, DEBUG, TRACE, and ALL levels are ignored. Log4j recommends using only four levels, with the highest priority being ERROR, WARN, INFO, and DEBUG.
1, use,sc
Command to view information about classes loaded by the JVM
Command: sc -d [find full path of class or * class name]
The sc command supports searching for class information by class name fuzzy. -d displays detailed information. The full path name and classLoaderHash of the class are obtained as follows:
[arthas@7]$ sc -d *TestController class-info devops.demo.controller.TestController code-source file:/app/devops-demo.jar! /BOOT-INF/classes! / name devops.demo.controller.TestController isInterface false isAnnotation false isEnum false isAnonymousClass false isArray false isLocalClass false isMemberClass false isPrimitive false isSynthetic false simple-name TestController modifier public annotation org.springframework.web.bind.annotation.RestController interfaces super-class +-java.lang.Object class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@7daf6ecc +-sun.misc.Launcher$AppClassLoader@70dea4e +-sun.misc.Launcher$ExtClassLoader@1a04f701 classLoaderHash 7daf6eccCopy the code
2, use,logger
Command to view the log level of a specified class
Command: logger --name [find the full path of the class]
Logger is used to view and modify Logger information. –name specifies the full path class name, as shown below:
[arthas@7]$ logger --name devops.demo.controller.TestController name devops.demo.controller.TestController class ch.qos.logback.classic.Logger classLoader org.springframework.boot.loader.LaunchedURLClassLoader@7daf6ecc classLoaderHash 7daf6ecc level null effectiveLevel INFO additivity true codeSource jar:file:/app/devops-demo.jar! The/BOOT - INF/lib/logback - classic - 1.2.3. Jar! /Copy the code
3, use,logger
Command to change the log level of a specified class
Logger -c [value of classLoaderHash] --name [Find the full path of the class] --level [level of logs to be updated]
-c Specifies the value of classLoaderHash –level Specifies the log level to be updated, as follows:
[arthas@7]$ logger -c 7daf6ecc --name devops.demo.controller.TestController --level debug
Update logger level success.
Copy the code
4. Verify that the log level is changed
By default, the log level of the class is INFO. There is no debug information in the output log of demo, as shown in the following figure:
Run the following command to change the log level of logger to debug:
[arthas@7]$ logger -c 7daf6ecc --name devops.demo.controller.TestController --level debug
Update logger level success.
Copy the code
The output log contains debugging information, as shown in the following figure:
Run the following command to change the log level of Logger to error:
[arthas@7]$ logger -c 7daf6ecc --name devops.demo.controller.TestController --level error
Update logger level success.
Copy the code
Again, only error information is displayed, as shown in the following figure:
4. Using Arthaswatch
View method input and output parameters
Command: watch full path class name method name [expression]
The instructions for executing the watch command are as follows: The watch command is used to view the input and output parameters, return values, and exceptions thrown by a specified method call. The following expressions can be used:
target : the object
clazz : the object's class
method : the constructor or method
params : the parameters array of method
params[0..n] : the element of parameters array
returnObj : the returned object of method
throwExp : the throw exception of method
isReturn : the method ended by return
isThrow : the method ended by throwing exception
#cost : the execution time in ms of method invocation
Copy the code
A detailed description of the watch command can be seen using watch –help, but only the example method is shown here.
Use the following command to view the invocation parameters of the method:
[arthas@7]$ watch devops.demo.controller.TestController hello params Press Q or Ctrl+C to abort. Affect(class count: 1 , method count: 1) cost in 26 ms, listenerId: 3 method=devops.demo.controller.TestController.hello location=AtExit ts=2021-05-26 11:36:58; [cost=0.627099ms] result= @object [][@string [test method call parameter],]Copy the code
Run the following command to view the returned parameters of the method:
[arthas@7]$ watch devops.demo.controller.TestController hello returnObj Press Q or Ctrl+C to abort. Affect(class count: 1 , method count: 1) cost in 24 ms, listenerId: 4 method=devops.demo.controller.TestController.hello location=AtExit ts=2021-05-26 11:39:18; [cost=0.525488ms] result= @string [Returned result: test method returned parameter]Copy the code
5. Use Arthas for online code hot updates
Arthas provided four commands — SC JAD MC Re-define — to hot-update your code online, which is very powerful, but also very dangerous, to control access to the container when you use it in the container, control access to the server when you use it on the server, The following uses the provided demo as an example to explain how to use these commands to implement code hot update.
1, use,sc
Command to find information about classes loaded by the JVM
Command: sc -d [find full path of class or * class name]
The sc command supports searching for class information by class name fuzzy. -d displays detailed information. The full path name and classLoaderHash of the class are obtained as follows:
[arthas@7]$ sc -d *TestController class-info devops.demo.controller.TestController code-source file:/app/devops-demo.jar! /BOOT-INF/classes! / name devops.demo.controller.TestController isInterface false isAnnotation false isEnum false isAnonymousClass false isArray false isLocalClass false isMemberClass false isPrimitive false isSynthetic false simple-name TestController modifier public annotation org.springframework.web.bind.annotation.RestController interfaces super-class +-java.lang.Object class-loader +-org.springframework.boot.loader.LaunchedURLClassLoader@7daf6ecc +-sun.misc.Launcher$AppClassLoader@70dea4e +-sun.misc.Launcher$ExtClassLoader@1a04f701 classLoaderHash 7daf6eccCopy the code
2, use,jad
Command to decompile the loaded class source code
Command: jad --source-only The full path of the class > class name. Java
The jad command decompiles the source code of the loaded class, –source-only specifies that only the source code is output, > class name. Java Saves the output to the class name. Java file in the current directory
jad --source-only devops.demo.controller.TestController > TestController.java
Copy the code
View the decompiled content as follows:
[arthas@7]$ cat TestController.java
/* * Decompiled with CFR. * * Could not load the following classes: * org.slf4j.Logger * org.slf4j.LoggerFactory * org.springframework.web.bind.annotation.GetMapping * org.springframework.web.bind.annotation.PathVariable * org.springframework.web.bind.annotation.RestController */
package devops.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
private static final Logger log = LoggerFactory.getLogger(TestController.class);
@GetMapping(value={"hello/{content}"})
public String hello(@PathVariable(value="content") String content) {
/ * 14 * / log.debug("----------log debug----------");
/ * * / 15 log.info("----------log info----------");
/ * 16 * / log.warn("----------log warn----------");
/ * 17 * / log.error("----------log error----------");
return "Return result:"+ content; }}Copy the code
No vim editor in the CONTAINER, is not convenient to modify, the compiled source code can be duplicated, change is completed, through the docker cp [OPTIONS] SRC_PATH | – CONTAINER: DEST_PATH command copies the contents of the modified into the CONTAINER.
docker cp TestController.java devop-demo:/app
Copy the code
Modify the source code decompiled above as follows:
[arthas@7]$ cat TestController.java
/* * Decompiled with CFR. * * Could not load the following classes: * org.slf4j.Logger * org.slf4j.LoggerFactory * org.springframework.web.bind.annotation.GetMapping * org.springframework.web.bind.annotation.PathVariable * org.springframework.web.bind.annotation.RestController */
package devops.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
private static final Logger log = LoggerFactory.getLogger(TestController.class);
@GetMapping(value={"hello/{content}"})
public String hello(@PathVariable(value="content") String content) {
/ * 14 * / log.debug("----------log debug----------");
/ * * / 15 log.info("----------log info----------");
/ * 16 * / log.warn("----------log warn----------");
/ * 17 * / log.error("----------log error----------");
return "Return result: Test hot update code"+ content; }}Copy the code
3, use,mc
Memory-compiled.java files are.class files
Command MC-C class loader hash Java source path -d/TMP
The. Java file is compiled as a. Class file. The -c class loader hash specifies the classLoaderHash found earlier by using the sc -d command. -d/TMP Specifies the directory for compiling class files. If the directory is not specified, the class files are output to the current directory.
[arthas@7]$ mc -c 7daf6ecc TestController.java -d /tmp
Memory compiler output:
/tmp/devops/demo/controller/TestController.class
Affect(row-cnt:1) cost in 993 ms.
Copy the code
4, the use ofretransform
Load the external.class file
Command: retransform class File path
Fill in the class file path as shown in the preceding decompile output path:
[arthas@7]$ retransform /tmp/devops/demo/controller/TestController.class
redefine success, size: 1, classes:
devops.demo.controller.TestController
Copy the code
Verify hot update results
Root @ the conversation - demo - 7 bdf65859c - MTJQM: / app # curl localhost: 8080 / hello/test returns results: test hot update code testCopy the code
Six, summarized
This article briefly introduces the use of Arthas in the Docker container, mainly introducing logger and watch commands and how to implement the online code hot update, which will be supplemented by other commands. For details, please refer to the official documentation.