什么是远程debug
远程debug即对远程部署的内容进行debug
远程debug和本地debug 区别
本地debug :idea本地启动 ——> idea 打断点 ——> postman 发送接口 ——> 进入断点 远程debug :服务器上启动 ——> idea 监听启动 ——> idea 打断点 ——> 页面上操作发送接口 ——> 进入断点
应用场景
1 例如我们部署的项目在线上出现问题了 ,而我们又不知道具体是哪里出现问题 ,我们就可以使用远程debug进行排查问题。
2 当你在本地开发的时候 ,你需要调试服务器上的程序 时,远程调试就显得非常有用。
3 开发环境正常 测试过的功能在测试环境甚至生产环境下出现bug 的情况。一般情况下,你可能需要多次重复这个过程(分析日志->猜测问题->加日志->部署->获取日志 )来慢慢逼近问题。这时可以——远程调试 ——将程序在测试环境中以debug模式启动 ,在本机使用IDEA在工程中设置断点进行调试 。
远程debug原理
Java远程调试的原理是两个JVM之间通过debug协议进行通信 ,然后以达到远程调试的目的。两者之间可以通过socket进行通信 。
被debug的机器需要开启debug模式 ,debug使用的客户端 可以是idea。
远程调试原理
Java程序的执行过程 - 分为以下几个步骤:Java的文件 - - 编译生成的类文件(class文件) - - JVM加载类文件 - - JVM运行类字节码文件 - - JVM翻译器 翻译成各个机器认识的不同的机器码
Java 程序是运行在Java 虚拟机(JVM )上 的,具有良好跨平台性 ,是因为Java程序 统一以字节码的形式在JVM中运行 ,不同平台的虚拟机 都统一使用这种相同的程序存储格式 。
因为都是类字节码文件,只要本地代码和远程服务器上的类文件相同 ,两个JVM通过调试协议进行通信 (例如通过插座在同一个端口进行通信),另外需要注意的时,被调试的服务器需要开启调试模式 ,服务器端的代码和本地代码必须保持一致,则会造成断点无法进入的问题 。 这个架构其实质还是JVM,只要确保本地的Java的源代码与目标应用程序一致,本地的Java的源码就可以用插座连接到远端的JVM,进而执行调试 。因此,在这种插座连接模式(下文介绍)下,本地只需要有源码,本地的Java的应用程序根本不用启动。
传输方式,默认为Socket ;
套接字:MACOS,Linux的系统使用此种传输方式;
共享内存:WINDOWS系统使用此种传输方式。
调试模式,默认为Attach ;
Attach :此种模式下,调试服务端(被调试远程运行的机器)启动一个端口等待我们(调试客户端)去连接;
Socket :此种模式下,是我们(调试客户端)去监听一个端口,当调试服务端准备好了,就会进行连接。
示例
k8s springcloud 多模块部署 项目
服务器上模块 pod.yml 文件修改
因为 k8s 中各个模块 是通过 kubectl apply -f pod.yml 运行模块的,所以在 pod.yml 文件中有以下内容,可以使 jar 包以 debug 模式运行,开放 debug 端口
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myweb-user
namespace: myweb
spec:
....
template:
....
spec:
containers:
- name: myweb-user
image: "registry.xxxx.com/xxxx/myweb-user-application:3.0.0-test-dirty"
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
- name: connect
containerPort: 13000
----------重点是下面--------------------重点是下面-----------------------------
- name: debug
containerPort: 12020
command: ["java"]
args: ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12021", "-server", "-Djava.net.preferIPv4Stack=true", "-Dfile.encoding=utf-8", "-Xms3g", "-Xmx3g", "-XX:SurvivorRatio=2", "-XX:+UseParallelGC", "-XX:ParallelGCThreads=5", "-XX:MaxRAMPercentage=75.0", "-XX:+UseParallelOldGC", "-XX:+PrintGCDetails", "-XX:+PrintGCDateStamps", "-XX:+HeapDumpOnOutOfMemoryError", "-Dspring.profiles.active=k8s", "-cp", "/app/resources:/app/classes:/app/libs/*", "com.公司.部门.user.MywebUserApplication"]
....
改好之后 kubectl apply 重新部署即可
这里是 kubectl exec 进入 pod ,pod 中的目录,存放了 jar包 的 source,类,和依赖的 jar 包
/app/resources:/app/classes:/app/libs
idea 中配置监听
注意host 是 监听的服务的 ip ,在 k8s 项目 中那就是 该项目 pod 的 ip port 是上一步服务器中项目启动 设置的监听端口
服务器上jar包运行
如果是 docker 部署的,可以 docker save -o registry.xxx.com/xxx/jar包 ,在服务器上保存一个 项目 jar 包 ,运行起来
pom.yml 配置
pom.xml里配置jvmArguments参数
-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n</jvmArguments>
</configuration>
</plugin>
</plugins>
</build>
加了此配置后,打包后的项目发布服务器,可支持远程DEBUG;
具体参数详解:
-Xdebug 通知JVM工作在DEBUG模式下;
-Xrunjdwp 通知JVM使用(Java debug wire protocol)运行调试环境。该参数同时包含了一系列的调试选项;
transport 指定了调试数据的传送方式,dt_socket是指用SOCKET模式,另有dt_shmem指用共享内存方式,其中,dt_shmem只适用于Windows平台;
address 调试服务器的端口号,客户端用来连接服务器的端口号;
server=y/n VM 是否需要作为调试服务器执行;
suspend=y/n 是否在调试客户端建立连接之后启动 VM;
IDEA打包jar
右侧Maven工具,双击 package打包工具;
一般打包跳过test ,可以点击箭头所指闪电图标 ,这样打包速度会快很多 ; 打包后,在target目录下,会生成一个jar包 ;我们把它复制出来即可
启动jar并且带启动参数支持远程调试
以远程 DEBUG 模式 启动 jar
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar remote-debug-v1.0.jar
启动OK,监听socket 5005端口
IDEA远程DEBUG配置
测试成功
|