四、插件热插拔管理机制(H-Spi)
插件热插拔管理机制,简称:H-Spi。是框架提供的生产时用的另一种高级扩展方案。相对E-Spi,H-Spi 更侧重隔离、热插热拔、及管理性。
应用时,是以一个业务模块为单位进行开发,且封装为一个独立插件包。
1、特点说明
- 所有插件包独享 ClassLoader、AppContext、配置;完全隔离
- 可通过 Solon.app(), Solon.cfg(), Solon.context() 等...手动获取主程序或全局的资源
- 模块可以打包成一个独立的插件包(放在体外加载),也可以与主程序一起打包。“分”或“合”也是自由!
- 更新插件包,不需要重启主服务。热更新!
- 开发时,所有资源完全独立自控。且必须完成资源移除的任务
- 模块之间的通讯,尽量交由事件总线(EventBus)处理。且尽量用弱类型的事件数据(如Map,或 JsonString)。建议结合 "DamiBus" 一起使用,它能帮助解耦
- 主程序需要引入 "solon-hotplug" 依赖,对业务插件包进行管理
2、关于 ClassLoader 隔离
在 ClassLoader 隔离下,开发业务是比较麻烦的。注意:
- 父级 ClassLoader (一般,公共资源放这里)
- 子级,可以获取并使用它的类或资源
- 如果有东西注册,在插件 stop 事件里要注销掉
- 同级 ClassLoader
- 同级,无法相互使用类或资源
- 不要有显示类的交互
- 一般通过事件总线进行交互
- 交互的数据一般用父级 ClassLoader 的实体类
- 或者用弱类型的数据,如 json(像使用远程接口那样对待)
尽量让插件之间,相互比较独立,不需要什么交互(或少量使用事件总线交互)。
3、插件开发注意示例
- 插件在“启动”时添加到公共场所的资源或对象,必须在插件停止时须移除掉(为了能热更新):
public class Plugin1Impl implements Plugin {
AppContext context;
StaticRepository staticRepository;
@Override
public void start(AppContext context) {
this.context = context;
//添加自己的配置文件
context.cfg().loadAdd("demo1011.plugin1.yml");
//扫描自己的bean
context.beanScan(Plugin1Impl.class);
//添加自己的静态文件仓库(注册classloader)
staticRepository = new ClassPathStaticRepository(context.getClassLoader(), "plugin1_static");
StaticMappings.add("/html/", staticRepository);
}
@Override
public void stop() throws Throwable {
//移除http处理。//用前缀,方便移除
Solon.app().router().remove("/user");
//移除定时任务(如果有定时任务,选支持手动移除的方案)
JobManager.remove("job1");
//移除事件订阅
context.beanForeach(bw -> {
if (bw.raw() instanceof EventListener) {
EventBus.unsubscribe(bw.raw());
}
});
//移除静态文件仓库
StaticMappings.remove(staticRepository);
}
}
- 一些涉及 classloader 的相关细节,需要多多注意。比如后端模板的渲染:
public class BaseController implements Render {
//要考虑模板所在的classloader
static final FreemarkerRender viewRender = new FreemarkerRender(BaseController.class.getClassLoader());
@Override
public void render(Object data, Context ctx) throws Throwable {
if (data instanceof Throwable) {
throw (Throwable) data;
}
if (data instanceof ModelAndView) {
viewRender.render(data, ctx);
} else {
ctx.render(data);
}
}
}
- 更多细节,需要根据业务情况多多注意。
4、插件管理
插件有管理能力后,还可以仓库化,平台化。详见:《solon-hotplug》