一、什么是远程调试
当我们的代码在线上/测试环境运行出现异常需要进行问题定位时
传统做法是:查看异常日志,根据日志定位到出错代码,然后再根据相关参数及异常信息进行推断。
但是很多异常问题需要更细致的进行debug才能够更精准的去定位和解决,这种情况下,我们希望能够像在本地调试一样去debug线上/测试环境的代码,这样可以大大提升bug修复的效率。IDEA 远程调试为我们提供了解决方案,像运行本地代码一样调试远程主机上的程序,以排查远程程序的BUG或代码执行流程。
二、远程DeBug调试原理
在本地远程调试服务器端的代码原理:本地和服务器端建立一个socket连接监听,当客户端访问服务器的时候,服务器端会先去问本地idea有没有断点,如果有会停在当前断点,如果没有就返回给客户端。
三、如何进行idea远程调试
1、主动连接调试
1.1 远程服务中先开启Debug服务
1.1.1 对于 SpringBoot (jar包)
命令行添加选项,并重启,注意新参数必须在 -jar 之前
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -jar springboottest.jar
1.1.2 对应Tomcat(war包)
启动脚本中添加选项,并重启:
## sudo vim $CATALINA_HOME/bin/catalina.sh
JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
1.2 IDEA 中指定 Debug 服务器
- 点击主窗口菜单 Run / Edit Configurations,打开Run/Debug Configurations窗口;
- 点击工具栏上的+按钮,下拉菜单中选择Remote;
- 设置 Host 为远程服务器的域名或IP,保持 Port=5005 无需调整;
- Use module classpath配置为程序模块名称;
- Command line arguments for remote JVM配置:配置Debug远程服务的命令行启动参数,形如 -Xdebug -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005,参数说明如下:
- -Xdebug:JVM在DEBUG模式下工作;
- -Xrunjdwp:JVM使用(java debug wire protocol)来运行调试环境;
- transport:监听Socket端口连接方式,常用的dt_socket表示使用socket连接;
- server:=y表示当前是调试服务端,=n表示当前是调试客户端;
- suspend:=n表示启动时不中断(如果启动时中断,一般用于调试启动不了的问题);
- address:表示本地监听的地址和端口。
1.3 远程服务器防火墙端口放行
如果调试服务器与远程服务器网络不相通则需要开放端口
### sudo vim /etc.sysconfig/iptables
-A INPUT -m state --state NEW -m tcp --dport 5005 -j ACCEPT
### 重启生效: sudo systemctl restart iptables
2、被动连接调试
首先需要IDEA配置监听,如主动连接调试的IDEA配置图片,Debugger mode选择:Listen to remote JVM,配置本地监听端口,比如默认5005。点击Debug开始等待远程连接调试。
2.1 对于 Tomcat
配置远程服务启动脚本:
## sudo vim $CATALINA_HOME/bin/catalina.sh
JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,suspend=y,address=127.0.0.1:5005"
2.2 对于SpirngBoot
参数含义和主动连接调试一样,只是这里suspend=y表示启动时就中断,需要连接本地IDE调试启动。address=ip:port,ip需要修改为本地的对外IP。 这样远程项目启动时就连接到本地,方便调试项目启动不了的问题。
java -Xdebug -Xrunjdwp:transport=dt_socket,suspend=y,address=127.0.0.1:5005 -jar springboottest.jar
四、注意事项有什么
1、停在本地的断点,关闭程序后是否会继续往下执行?
会继续往下执行
2、本地代码和远程代码不一致怎么办?
如果本地代码和远程代码不一致,是根据服务器端文件的行号来打的断点。而不是本地的Java代码 所以远程调试,一定得保证本地代码和远程代码一致,不然定位问题不准
3、远程调试代码,所有的日志是在远程打印,不会在本地控制台打印
4、远程调试某个接口,这时其他用户的访问这个接口会卡住
尽量在测试环境使用,不要在生产环境上使用。生产环境一般使用Arthas
5、远程调试可以调试Jar包,也可以调试war包