分布式系统高可用之热部署难点,疑点
对服务的调整都需要重启系统,重启系统会带来4个问题
- JVM服务重启对上下游造成冲击,因为重启可能需要较长时间,一个服务重启5秒-30秒,较为复杂的应用,比如Spring Boot,可能需要数分钟重启成功。影响开发效率。 生产上一个小的逻辑变化,会导致千万计的服务重启。这些服务重启对上下游,对依赖的数据库,redis造成影响,比如瞬间对MySQL进行大量访问
- 重启服务,因为JIT会对类进行优化,会导致CPU较高,导致此刻访问较平时延时。如果此时客户端访问超时立刻重试,导致服务器一直过载变成雪崩
- 还有个原因 需要避免重启的原因是有服务是有状态的,比如设备网关,游戏地图等,重启将导致设备掉线,重新上报数据,数据可能需要长时间才能再平衡。应该尽量避免重启。
- 另外,如果依赖类库发布补丁包,更新补丁也需要重启,如FastJSON,Log4J安全漏洞。重启带来较大的运维工作。
大一点的系统,重启需要数天到数周时间完成,以我上家物联网公司为例子,重启需要2周(以避免对基础设施和其他系统造成冲击
一般来说,有如下几种方法可以热发布代码
| 方法 | 描述 | 用于生产 |
|---|---|---|
| 动态脚本 | 使用动态脚本,表达式引擎,比如Groovy,JRuby。这在8.2中已经说明 | 可以 |
| ClassLoader | ClassLoader 加载新的代码,像早期修改JSP立即生效,或者在应用服务器上重新部署JavaEE App采用此技术。 | 可以 |
| 重定义方法体 | JVM支持重定义方法体,比如使用Arthis可以热发布方法体。此方法不适合类的修改,如方法签名修改,类增加成员变量 | 可以 |
| DceVM | 修改JVM实现,能让JVM不受限制重新定义Class,包括新增方法,修改类继承关系等。这种方法的JVM被修改过,因此只能自担风险,目前国内有大规模公司在非生产环境实践使用DCEVM。Jetbrain提供了JDK17的DCEVM 虚拟机用于调试。DCEVM比较完美解决了热发布问题,不过还没有国内用于生产的案例。 | 国内未有大规模色生产验证。 |
| Spring Loaded | 它实现热发布原理较为复杂,大致是系统启动过程,类加载JVM的时候,它字节码扫描,将对此目标动态的类的方法和属性调用字节码,转化成一个代理类调用字节码,此代理类内部调用真正的目标类。当目标类更新时候,代理类转向调用更新的类。由于加了代理层,实际系统的调用都变成代理类调用。因此此方式不适合生产系统,仅用于调试 | 不能 |
这些方法各有优缺点,比如动态脚本只能热发布限定的业务逻辑,如果非脚本部分需要修改则没有办法。 这些方法除了DceVM能几乎不受限制的(包括对依赖的jar,比如fastjson)进行热不发,但在生产上还未得到充分验证。没有得到大厂验证原因有两个,1是不符合发布流程,2是没有厂商和运维承担热发布失败的责任
总的来说,热发布这块,运维觉得是程序员的事情,程序员觉得是运维事情,很难做到!需要有魄力
