欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java 远程调试

程序员文章站 2022-09-01 17:34:55
用处 1. 在单体应用时代,当代码已经部署到生产或者测试环境的时候,由于特殊需求,我们要对代码进行debug来调查问题 2. 在微服务开发中,你开发的服务可能会依赖数据库、消息队列等资源,也有可能依赖其他的服务,这些服务又有新的依赖,这种情况下,在自己的开发环境中完全模拟测试、线上环境变的极其困难, ......

用处

  1. 在单体应用时代,当代码已经部署到生产或者测试环境的时候,由于特殊需求,我们要对代码进行debug来调查问题
  2. 在微服务开发中,你开发的服务可能会依赖数据库、消息队列等资源,也有可能依赖其他的服务,这些服务又有新的依赖,这种情况下,在自己的开发环境中完全模拟测试、线上环境变的极其困难,所以无法直接对本机代码进行debug

在以上两种情况下,就需要进行远程debug

原理

Java 远程调试

  1. 线上/测试环境上的应用额外开通一个端口号,例如5005
  2. 本机启动一个debug进程,通过jdpa(java platform debugger architecture) attach到线上/测试环境中正在运行的进程,就可以进行debug
  • 要保证本机和线上/测试环境代码一致性,否则不能进行debug
  • 在debug过程中,可以通过修改变量值等措施修改debug流程

例子

  1. 例子介绍

    本应用是一个简单的spring boot工程,只有一个简单的controller,里面一个restful api,接收外部请求,返回ok作为调用结果

    @restcontroller
    public class clientipcontroller {
    @requestmapping("/health")
        public string health(httpservletrequest request) {
    
            string result = "ok";
            return result;
        }
    }
    
  2. 在服务器上启动应用(ip:192.168.0.114)

    $ mvn clean package
    # 启动应用
    $ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar client-ip-test-0.0.1-snapshot.jar
    
    • 注意启动命令中追加的信息

      -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005(jdk 5-8)   
      -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 (jdk 9+)
      

      在5005端口上多启动一个监听,server=y等待外部debug进程attach进来

  3. 在本机上启动debug进程(ip:192.168.0.108),以eclipse为例
    Java 远程调试

    Java 远程调试

    • 在remote java application中新建应用,在连接信息中填写服务器的服务信息,启动debug

开始debug

通过上面的步骤,我们就在服务器上部署好了一个应用,并把本机的debug进程attach到服务器上的应用中

接着在需要debug的代码中打上断点,访问服务器上的服务,就可以正常进行debug了

额外的思考

通过上面的步骤,我们的确能够实现在本机对服务器上的应用进行调式,但是,这种情况下,要保证本机和服务器代码的同步,每次发现问题,还需要打包->部署等一套流程,即便是采用的ci/cd来做自动发布了,这个过程依旧比较长,特别是当服务器环境是现在比较流行的kubernetes、swarm等容器环境时,这个流程将更长,目前的想法是,用一个基础镜像,镜像里面有git、maven、java环境,镜像的启动命令中执行以下操作

  • 根据传入的git uri下载源码
  • 对于spring boot工程,利用命令mvn spring-boot:run直接启动服务
  • 启动镜像时,在测试环境下传入

    -e maven_opts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
    

    参数,指定可以进行远程debug

这样,每次修改完代码,上传到git上后,把对应的镜像重新启动一下就可以实现debug了

如果在线上环境不能执行远程debug,如果是kubernetes环境,可参照local development with java use telepresence on kubernetes