热部署在 Java 定制项目的使用

2023年 9月 16日 35.5k 0

什么热部署

热部署,即用户在使用服务或软件时,可以在无感知的情况下对系统或软件进行升级,以修复BUG或实现功能的迭代。在Java项目中,热部署是在运行时执行Java类文件,触发Spring或其他第三方框架以更新源代码的过程。在热部署过程中,Java程序无需重启,服务可以持续提供服务,并且程序代码在热部署后能够立即更新。

为什么需要热部署

对于后端开发人员来说,最重要的任务是自测、联调和上线。在自测阶段,我们需要根据代码质量进行适当的调试;在联调阶段,我们需要与前端同学进行不断的适配和调试;在上线阶段,我们要确保项目万无一失,尽可能减少项目出现的问题。

在上述的3个场景中,后端开发人员需要不断地进行排查、修复bug和重启的过程。在本地IDEA中,重启项目的时间可以暂时忽略。然而,一旦进入联调和测试阶段,由于需要使用公司的pack平台和公司内部研发平台进行打包、部署的CI/CD流程,这部分时间将大大增加。

热部署的目的在于尽可能降低项目的重启和部署次数,减少部署过程中消耗的大量无效时间,节省碎片化时间,为开发同事提供额外的开发时间,以便更加关注于程序的开发与优化。

热部署的难度

目前,市面上有许多Java热部署的方案,但是它们的功能差异较大。一般而言,开发人员在开发项目时并不会过多考虑热部署的相关技术方案。这主要是因为热部署不同于重启,它不仅需要兼容各种第三方框架,还需要开发人员对字节码有深入的了解。同时,考虑热部署时还需要考虑到Spring和HOTSWAP等相关限制。

对于公司内部的服务,我们可以方便地进行项目部署,因此热部署的技术方案可以暂时不考虑。然而,对于客户定制项目,由于其特殊性和定制化,往往涉及到现场部署难度大、申请流程长、代码规范要求高等问题。因此,客户项目的热部署需求在这种背景下应运而生。

常见的热部署方案

  • Spring Boot DevTools:
    • Spring Boot DevTools是Spring官方提供的工具,它可以监控类文件的更改并自动重启应用程序。它还支持属性文件的热加载。
  • JRebel:
    • JRebel是一款商业的热部署工具,它可以在应用程序运行时直接将新的Java代码加载到虚拟机中,而不需要重新启动。它支持各种Java应用服务器和框架。
  • JVM工具:
    • Java虚拟机本身提供了一些工具来支持热部署。例如,使用Java的-XX:PermSize和-XX:MaxPermSize参数可以动态调整永久代内存大小,这在一些情况下可以避免类加载时的内存不足错误。
  • HotSwap:
    • HotSwap是一个开源的工具,它可以与各种IDE(如Eclipse、IntelliJ IDEA)一起使用,允许你在调试会话中替换类的字节码,以实现热部署。

    客户定制项目中的热部署使用

    1.开发与调试

    开发过程中,因为项目运行在我们本地,因此项目只需要简单的配置 spring-dev-tool即可。

     
         
            org.springframework.boot  
             spring-boot-devtools  
            true 
         
    
    

    接着,我们在 IDEA 中启动热部署即可。

    File -> Settings -> Build,Execution,Deplyment -> Compiler,选中打勾 Build project automatically。

    2.项目部署

    JavaCompiler

    其实JDK的底层本身就提供了动态加载类文件的能力,它就是JavaCompiler。如果使用JavaCompiler动态加载类文件内容,那就需要经过下述流程:

    • 将Java代码组装成符合标准的源码格式,然后通过编译将其转化为class字节码。
    • 运用ClassLoader工具将这个class字节码加载到JVM中,生成可运行的class对象。
    • 借助反射机制,在运行时动态调用这个class中的逻辑代码,实现灵活的程序控制。
    String javaCode = "public class HelloWorld {"
                    + "    public static void main(String[] args) {"
                    + "        System.out.println("Hello, World!");"
                    + "    }"
                    + "}";
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
    
    // 创建一个Java文件对象
    JavaFileObject javaFileObject = new JavaSourceFromString("HelloWorld", javaCode);
    
    // 设置编译选项,例如生成的字节码版本
    Iterable options = Arrays.asList("-source", "1.8", "-target", "1.8");
    
    // 编译Java代码
    JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, Collections.singletonList(javaFileObject));
    boolean result = task.call() == true;
    
    // 关闭文件管理器
    fileManager.close();
    
    if (result) {
        System.out.println("Compilation succeeded.");
    } else {
        System.out.println("Compilation failed.");
    }
    

    得到class之后,我们想要调用class的方法,最直接的就是反射调用,相对就比较简单了。

    import javax.tools.*;
    import java.io.*;
    import java.lang.reflect.*;
    
    public class DynamicCompilationExample {
        public static void main(String[] args) {
            try {
                // 编译源码
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
                JavaFileObject javaFileObject = new JavaSourceFromString("MyBusinessLogic", javaCode);
                Iterable myClass = classLoader.loadClass("MyBusinessLogic");
    
                // 创建类的实例并调用其方法
                Object instance = myClass.newInstance();
                Method executeMethod = myClass.getDeclaredMethod("execute");
                executeMethod.invoke(instance);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    Arthas

    阿里的arthas非常受欢迎,因为它提供了一套解决线上问题的解决方案,如在线查看服务器状态,支持热更新,以及跟踪执行情况,打印执行参数和返回参数等功能。它的功能非常强大,而且对应用没有侵入性,不会影响目标应用的业务逻辑。

    在 Arthas Shell 中,我们可以使用 redefine 命令进行热部署。例如,如果你想热部署一个类 com.example.MyClass,可以执行以下命令(在此之前,你需要Java 代码编译为字节码) :

    redefine --class com.example.MyClass --source /path/to/MyClass.class
    

    总结

    热部署技术是能够极大方便开发部署的,但需谨慎使用。在客户项目中,我们不仅需评估热部署的适用范围,还需遵守客户的安全规范。过多依赖热部署可能引发问题,应尽量避免。

    作为开发或者是项目负责人,确保在开发和测试环境中合理使用热部署以提高效率,但在生产环境中,需遵循最佳实践,确保稳定性和安全性。客户的规定和标准是首要考虑因素,应积极遵循以确保项目的成功和安全运行。

    参考文件:

  • yeas.fun/archives/ho…
  • juejin.cn/post/715269…
  • pdai.tech/md/spring/s…
  • www.cnblogs.com/wchukai/p/5…
  • tech.meituan.com/2022/03/17/…
  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论