热部署

  • 就是在应用正在运行的时候升级软件,却不需要重新启动应用。有下面几种方式
    • spring-boot-devtools
    • JRebel ,付费插件,支持热部署和远程热部署,。具体见JRebel特性
    • Spring Loaded:与Debug模式类似,适用范围有限,但是不依赖于Debug模式启动,需要在 run confrgration 中进行配置。
    • 使用调试模式Debug实现热部署,无法对配置文件,方法名称改变,增加类及方法进行热部署
    • 模板热部署:模板引擎的页面默认是开启缓存的

关闭模板引擎的缓存

  • 模板引擎的页面默认是开启缓存的,如果修改了页面的内容,则刷新页面是得不到修改后的页面的,因此我们可以在application.properties中关闭模版引擎的缓存,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    # Thymeleaf的配置:
    spring.thymeleaf.cache=false
    # FreeMarker的配置:
    spring.freemarker.cache=false
    # Groovy的配置:
    spring.groovy.template.cache=false
    # Velocity的配置:
    spring.velocity.cache=false

spring-boot-devtools

  • 通过重新编译的方式完成SpringBoot项目重启,热部署可以快速重启项目,一般只用在开发环境,生产环境不要使用。
  • 系统的任何变动包括配置文件修改、方法名称变化都能覆盖
  • 它是采用文件变化后重启的策略来实现了,主要是节省了我们手动点击重启的时间,提高了实效性,在体验上会稍差。
  • spring-boot-devtools 默认关闭了模版缓存,如果使用这种方式不用单独配置关闭模版缓存。
  • 生产环境devtools将被禁用,如java -jar方式或者自定义的类加载器等都会识别为生产环境。

部署原理

  • SpringBoot项目将系统的类拆分到两个ClassLoader。热部署的时候,静态类加载器保持不变,仅仅让动态类加载器加载所需要的类,加快JVM类的加载速度。
  • 官方文档
    The restart technology provided by Spring Boot works by using two classloaders. Classes that do not change (for example, those from third-party jars) are loaded into a base classloader. Classes that you are actively developing are loaded into a restart classloader. When the application is restarted, the restart classloader is thrown away and a new one is created. This approach means that application restarts are typically much faster than “cold starts”, since the base classloader is already available and populated.
    If you find that restarts are not quick enough for your applications or you encounter classloading issues, you could consider reloading technologies such as JRebel from ZeroTurnaround. These work by rewriting classes as they are loaded to make them more amenable to reloading.

开启热部署

  • 增加spring-boot-devtools依赖打开热部署

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
    </dependency>
  • 打开热部署配置 【可选项,系统已经默认打开】

    1
    2
    3
    4
    5
    6
    7
    8
    spring.devtools.restart.enabled: true
    # 关闭热部署
    spring.devtools.restart.enabled: false
    # 某些资源在更改后不一定需要触发重新启动
    # 自定义这些排除项
    spring.devtools.restart.exclude=static/**,public/**
    # 保留这些默认值并添加其他排除项,请改用该属性。
    spring.devtools.restart.additional-exclude
  • Intellij Idea修改

    • 勾上自动编译或者手动重新编译

      File > Settings > Compiler-Build Project automatically

    • 注册

      ctrl + shift + alt + / > Registry > 勾选Compiler autoMake allow when app running

注意事项

  • devtools会在windows资源管理器占用java进程,在开发工具里面杀不掉,只能手动kill掉,不然重启会选成端口重复绑定报错。
  • boot-devtools更多详细用法,点击参考官方文档。

配置触发条件

  • 但是,如果每个java源代码,随便改点东西,就频繁自动编译、重新加载,开销也比较大,也可以参考下面的设置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    server:
    port: 8080 #服务器端口
    servlet:
    context-path: /es
    spring:
    main:
    banner-mode: "off" #关闭Banner打印
    devtools:
    restart:
    # 表示只有resources/META-INF/.trigger的内容变化时,才会触发重新编译及加载
    trigger-file: .trigger
  • 一些静态资源,比如图片,css样式,js脚本文件,如果内容修改了,也有可能触发自动重启,

  • 默认情况下META-INF/resources、resources、static、public、templates等几个目录的内容已经被devtools排除在外了(即:这些目录下的文件变化,不会触发自动重启),

  • 具体可以查看spring-boot的源码:org.springframework.boot.devtools.autoconfigure.DevToolsProperties.Restart#DEFAULT_RESTART_EXCLUDES

  • 如果你的静态资源不在几个标准目录里(比如webresource),就必须手动排除了,类似这样:

    1
    2
    3
    4
    5
    spring:
    devtools:
    restart:
    trigger-file: .trigger
    exclude: /webresouce/**

LiveReload

  • LveReload chrome商店

  • spring-boot-devtools提供的另一项特别有用的功能就是LiveReload,常规web开发中,如果修改了css/javascript/html等前端内容,至少得刷新下页面,才能看到最新效果

  • 而LiveReload则可以让开发人员,在任何编辑器中,只要修改了源代码(比如:将某个标题设置成红色),网页就实时做出相应的响应(即:字变红),不需要刷新。

  • 秘密就在于spring-boot-devtools在应用启动时,自带了一个LiveReload Service,参考下面的截图:

  • 那么,浏览器怎么做到实时与LiveReload的Service保持实时内容同步呢?

  • 当然,要安装插件,chrome的应用商店里搜索LiveReload免费插件安装即可(需要反抢,你懂的),在调试时,只要激活该插件,页面就会与LiveReload建立websocket的长链接,参考下图:

  • 同时,如果查看本机建立的livereload端口连接情况,也可以印证这一点:

  • 不过要注意的是,spring-boot项目重启时,偶尔发现浏览器与liveReload的连接不会及时关闭,导致端口被占用,最终项目重启失败,另外,如果idea同时启动多个webapplication,只有第1个启动的应用会有LiveReload Server,后面的应用livereload不管用
    (这也很容易理解,如果1台机器上有多个livereload server,浏览器的livereload 插件,估计也不太好判断该连哪个web socket)

JRebel

  • Jrebel是Java开发最好的热部署工具,对 提供了极佳的支持,JRebel为收费软件,试用期14天。可直接通过插件安装。
  • 安装插件后根据指南就能实现热部署
  • https://www.jrebel.com/products/jrebel/learn

远程热部署

  • 环境说明
    • 服务器是centos 7 64位。
    • 本地电脑是win10,安装了IntelliJ IDEA,JRebel并已激活。
    • 有一个springboot项目。

服务器安装JRebel

  • JRebel目前有两种版本,一种是依赖IDE的,一种是独立的,我们的服务器上需要安装独立版。

  • 官网下载最新的jrebel-2020.3.2-nosetup.zip,点击官网链接

  • 解压下载好的Zip : unzip jrebel-2020.3.2-nosetup.zip

  • 激活JRebel

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 命令行激活示例
    bin luke$ ./activate.sh /Users/luke/.jrebel/jrebel.lic
    # 许可证服务器URL
    mars:bin luke$ ./activate.sh http://license-server:port/3789g63f-fcb2-8765-a994-598764430df455f luke.skywalker@tatooine.net

    # 以评估版许可证激活码作为参数:
    mars:bin luke$ ./activate.sh rO0ABXNyAChjb20uemVyb3R1cm5hcm91bmQubGljZW5zaW5n
    LlVzZXJMaWNlbnNlAAAAAAAAAAECAANMAAdkYXRhTWFwdAAPTGphdmEvdXRpbC9NYXA7WwAHbGljZW
    5zZXQAAltCWwAJc2lnbmF0dXJlcQB+AAJ4cHB1cgACW0Ks8xf4BghU4AIAAHhwAAACZqztAAVzcgAR
    amF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAA
    AAAAAYdwgAAAAgAAAAFHQAA3VpZHQAJDljNzMwZDgzLTdkOTItNDQzMC05MWFlLTgyMGE1NTRjYmM2
    NnQACGooF9BAJqZHyD+D76s=

服务器配置

  • 要为应用程序部署到的容器启用JRebel代理,您需要向-agentpathJVM参数列表添加一个参数。为此,您需要修改服务器启动脚本。

  • 默认情况下是禁用远程服务器支持插件。您需要添加一个JVM参数来激活它:

    1
    -agentpath:[/path/to/JRebel Agent] -Drebel.remoting_plugin=true
  • JRebel Agent库因操作系统和体系结构而:添加以下内容以使用JRebel Agent

    JDK 启动参数
    Windows 64位JDK -agentpath:[c:\path\to]\lib\jrebel64.dll
    Windows 32位JDK -agentpath:[c:\path\to]\lib\jrebel32.dll
    Mac OS X 64位JDK -agentpath:[path/to]/lib/libjrebel64.dylib
    Mac OS X 32位JDK -agentpath:[path/to]/lib/libjrebel32.dylib
    Linux 64位JDK -agentpath:[path/to]/lib/libjrebel64.so
    Linux 32位JDK -agentpath:[path/to]/lib/libjrebel32.so
  • 使用专用端口(可选)

    • 当部署到远程服务器的应用程序没有HTTP端点(例如EJB模块和独立应用程序)时,可以为远程服务器支持指定端口,以启用JRebel的嵌入式Jetty容器。-Drebel.remoting_port=[port number]
    • 添加(例如)可启用JRebel内的嵌入式Jetty容器。这将用于处理来自IDE插件的HTTP请求。
  • 服务器端密码配置

    • 要在服务器上启用基于密码的安全性,请使用以下命令设置服务器密码:

      1
      $ java -jar jrebel.jar -set-remote-password [password]

配置本地JRebel

  1. Open Settings > JRebel > Startup. Select Run on a remote server.使用下拉菜单指定您的远程服务器配置。

  2. 将远程服务器添加到IntelliJ IDEA

    • Settings > JRebel > Remote servers
    • 按**+**配置新的远程服务器。Server URL的端口是应用的web端口
    • 启动jar后点击Test Connection成功会显示 Connection successful

应用配置

  • JRebel远程服务器支持需要rebel-remote.xml配置文件才能运行。该文件用于区分不同的应用程序模块。

  • 启用远程服务器支持插件rebel.xml时,将忽略常规配置文件。该文件由IDE自动生成,永远不要手动编辑。

  • 如果是Web模块,则rebel-remote.xml配置文件应最终位于WEB-INF/classes目录中;如果是EJB模块或JAR库,则配置文件应最终位于归档文件的根目录中。将其放在项目中的源文件夹或资源文件夹的根目录中(.properties文件所在的位置),并确保将其复制到目标目录中。

  • 示例:rebel-remote.xml

    • idrebel-remote.xml配置文件中唯一必需的元素。这是应用程序模块的ID,其中将包含此配置。
    • 所谓模块,是指单个JAR或WAR文件(网络档案)。
    1
    2
    3
    4
    <?xml version="1.0" encoding="UTF-8"?>
    <rebel-remote>
    <id>module-id</id>
    </rebel-remote>
  • 进入jar所在目录,运行命令启动项目

    1
    2
    3
    nohup java -jar XXX-0.0.1-SNAPSHOT.jar &
    # 手动添加JVM参数
    nohup java "-agentpath:/usr/common/jrebel/lib/libjrebel64.so" -Drebel.remoting_plugin=true -jar baba-0.0.1-SNAPSHOT.jar &
  • 为远程服务器成功配置JRebel远程服务器支持后,在远程服务器启动期间应该会看到以下横幅:

    1
    2
    3
    4
    5
    6
    7
    8
    2019-04-02 14:23:55 JRebel:  #############################################################
    2019-04-02 14:23:55 JRebel:
    2019-04-02 14:23:55 JRebel: JRebel Agent 2020.1.0 (202001051049)
    2019-04-02 14:23:55 JRebel: (c) Copyright 2007-2020 Perforce Software, Inc.
    2019-04-02 14:23:55 JRebel:
    2019-04-02 14:23:55 JRebel: JRebel started in remote server mode.
    2019-04-02 14:23:55 JRebel:
    2019-04-02 14:23:55 JRebel: #############################################################

配置模块以支持远程服务器

  1. 进入 View > Tool Windows > JRebe Panel窗口,打勾后会在项目资源文件夹中创建rebel.xmlrebel-remote.xml配置文件。
  2. 使用maven的package命令打包,生成XXX-SNAPSHOT.jar,打开jar可以看到JRebel生成的rebel.xmlrebel-remote.xml
  3. 将包含rebel-remote.xml配置文件的应用程序生成并重新部署到远程服务器。
  4. 后续的修改使用JRebel模块工具窗口上的“同步”按钮来手动同步工作站和远程服务器。