前言
首先我们明确下什么叫做热部署,热部署是在不重启java虚拟机的前提下,自动更新class的行为,从而更新整个运行时的逻辑。
在java开发领域,热部署一直是一个难以解决的问题,java虚拟机理论上只能实现方法体的修改热部署,对于整个类结构的更改,仍然需要重启虚拟机,对类重新加载才能完成更新操作。
OSGI
其实java业界有一些解决方案,比如osgi架构,这玩意时间比较长了,但一直没火起来。osgi架构的出现,可以让java系统变成模块化的形式,让模块重启成为可能。从一定程度上也算是个热部署的方案。可惜这玩意以前开发起来就觉得很反人类,配置文件一大堆不说,学习成本也很大。和spring结合起来,居然是一个模块一个spring上下文体系。并且如果模块之间有调用关系的话,重启相关的模块会让应用出现短暂的功能性休克,也就说,整个热启动过程不平滑。
这项技术现在估计很多小伙伴都没听说过,目前也渐渐的退出历史舞台,用的企业估计很少。
ASM
ASM是一款修改字节码的框架,同类型的框架还有Cglib。这些框架能加载一个class信息,用户可以按照自己的需求增强修改这些信息,最后输出成一个新的class。
具体实现过程,这里就不展开了。大家可以百度下,相关技术实现文章不少。
但单纯修改字节码一般要和其他技术结合起来,单靠这个也无法完成热更新,虽然ASM类的框架能够修改类,但是这些ASM的修改逻辑也是用java写的,这段代码也需要执行的。如果你把ASM的代码写在java里,也无法实现从外部
来热更新。
Javaagent&Attach API结合ASM
这就是上面一段说的ASM要结合其他技术才能实现热更新的方案,也是目前很多开源框架采用的方案。
比如大名鼎鼎的Arthas,就是利用javaagent通过Attach API运行时加载目标Java程序,最终利用Instrumention API或者ASM增强class,来实现代码跟踪,以及代码热修改的特性。
但笔者认为用Arthas来完成线上代码的热更新,只能用于一些很紧急的场景。不能替代日常业务逻辑修改。而且操作起来也挺复杂。
你需要先修改java代码,然后把java代码放到服务器上,在arthas里查找这个类的类加载器的hashcode,然后利用arthas提供的命令编译java代码输出成新的class文件,最用利用redefine
命令进行热更新。
试想下,如果大量逻辑的更改。这得有多麻烦。
所以更多的是利用arthas对线上应用进行诊断,追踪,热更改代码其实就是arthas众多功能中其中一个,并不是主要功能。
换一种思路
以上方案都是基于修改class本身,然后让JVM的类加载器重新加载来实现的。
那么有没有更好的方案呢?
其实java代码可以运行一些脚本的,jdk本身就支持调用脚本,从JDK 1.6开始,java就支持JSR223,可以用一致的形式在JVM上执行一些脚本语言,而且可实时编译,运行的效率和java不相上下的。
有的同学看到这里可能会拍砖了:利用脚本只能更改部分逻辑,不可能把所有的逻辑都用脚本写吧,你这篇文章探讨的不是“有没有可能所有的逻辑
都可热更新”么?
别急,首先我们来确定一个事情。你的java应用系统需不需要所有的
逻辑都是可以热更新的?很多代码都是大致固定不变的,比如util类,一些vo的定义也不大变更的,一些固定的业务也不需要热更新需求的。只有一些经常变更的决策部分,可能需要热更新。
那么我们只要把需要经常变的部分用脚本来定义不就可以了么。
业界有没有类似的开源框架呢?
还真有,而且是高star的热门开源项目,能够帮你做到用脚本进行热更新业务。
开源编排规则引擎
可能有小伙伴又要说了:你不是介绍java代码热部署么,怎么话题转到规则引擎上去了?
这里要说下,规则引擎的一大特性就是把决策部分逻辑剥离到外面,能够实现逻辑的变动快速热变更。
而这次介绍的规则引擎框架则更为强大,除了能剥离逻辑,还能解耦系统,让你的所有的逻辑块均可随意变更。理论上能实现所有
的逻辑都可变更,不是部分
哦。
这就是业界现在 很火的编排式规则引擎框架:LiteFlow
。
LiteFlow的理念很简单,就是把系统中的各个逻辑切分成一小块一小块的,称之为组件
,这些组件可以由java代码来写,也可以用脚本来写。然后一个完整业务就是把各个组件组搭一起,形成一个完整业务链。
这种模式的好处就是,不需要热更新的部分可以用java组件来写,需要经常变的部分可以用脚本来写。所有的组件均可混搭成为一个业务。如何编排这些组件,LiteFlow独创了ELF语法,拥有非常好上手的编排语法。程序员的话,十分钟就可以上手。上图粉色部分就是最简单的一种串联形式。
业务链路中组件可实时更换,也可实时增加,形成一个新的业务链。同时定义好的组件也可复用在其他的链路中。
LiteFlow的脚本方案也是利用JSR223来实现的,目前已经实现的脚本有三种:
为什么说利用LiteFlow编排引擎框架,你的所有逻辑都是可以变更的呢。因为你完全可以把所有的逻辑都用脚本组件来实现,LiteFlow提供了非常强大的脚本支持,完全和Java底层打通,你可以在脚本中import java的类,也可以调用java的类方法,甚至于可以在脚本中去定义方法,定义类,一切写法和java中完全一样。
更夸张的是,LiteFlow允许你在脚本中调用spring上下文的bean,你可以在脚本中调用DAO取数据,可以在脚本中发送rpc给其他微服务。只要你愿意,你可以一行java业务代码不写,完全把业务搬到脚本组件中去。
而且连逻辑块的顺序你也可以随意变动,因为LiteFlow的编排规则和脚本均可实现热变更。
LiteFlow为经常用的存储中间件也提供了原生支持:
LiteFlow支持所有的关系型数据库,另外zk,etcd,nacos均可支持,还提供了额外的扩展接口,供你自己扩展成其他的存储方式。
有想过么,你所有的逻辑和规则编排语法,都是存在于系统之外的。只要更改其脚本和逻辑,你所有节点的系统不需要做任何事,实时的进行热变更。
而这一切,LiteFlow做到了非常平滑,所谓平滑的意思是,不用担心在热变更的时候你的业务会受到任何的中断,也不会因为热变更造成正在执行的链路产生任何的异常。
LiteFlow编排能力有多强大呢,简单的几个关键字就可以编排出超乎想象的效果:
结语
在java的业务热部署领域,LiteFlow作为一款规则引擎,给出了一种新的解决思路。
除以上文中介绍的之外,LiteFlow框架还拥有众多的高级特性,从各个方位提升你系统的灵活性。
并且作为开源软件,LiteFlow拥有国内非常好的社区氛围和文化。
最后放出LiteFlow的官网和仓库地址,如果你觉得这款开源框架对你的业务有帮助,赶紧来了解一下吧
项目官网:
gitee托管仓库:
https://gitee.com/dromara/lit...
github托管仓库: