有什么办法在 Java 实现插件化?

220 天前
 GayGayUp

简单说一下背景:

我的项目是一个 IoT 数据收集平台,对接了非常多不同类型、不同厂家的设备,每种设备之间的通信方式(如 http/tcp/udp/mqtt 等)、协议编解码方式各不相同;

目前的状况是,IoT 数据收集平台(主程序)独立运行;每个类型的设备,都创建一个 springboot 服务(协议服务),实现不同的通信和编解码,协议服务通过 RocketMQ 发送消息,主程序消费消息,实现数据收集;

这样如果单个协议服务死了,也不会影响其他协议服务和主程序,优点是实现简单(当初就是为了快速搭建起来而这样做),缺点就是服务过多(目前协议服务已经有接近 60 个)、难以管理、对服务器资源占用也大;

看了一些开源的 IoT 平台,完善度比较高的:如 Jetlinks ,源码晦涩难懂,放弃了;

所以我想能不能用插件化实现:如使用 pf4j ,写一个简单的插件,里面写好一些编解码的操作,打包成 Jar 包后,对接进主程序,复用主程序的通信模块和数据上报模块。插件部署了就采集、卸载了就停止;

问: 我的这个想法可不可行? 技术上实现难度高不高? 如可行,有没一些开源的项目可供学习参考?

3008 次点击
所在节点    Java
28 条回复
weenhall5
220 天前
osgi
2han9wen71an
220 天前
osgi
Wvg9eBo3U0c8BLd2
220 天前
楼上说的 osgi 没用过。 但是 java 做插件化非常容易, 定义好统一的接口, 不同的模块都编译成 jar , 然后动态加载 jar 的 class , 用反射的方式去执行接口函数就好了。
matcloud
220 天前
Java SPI 了解下,以前给我们平台用这个技术实现过插件系统。
byteLoading
220 天前
通过 SPI 机制可以实现,原生支持,阿里的很多开源组件也都用到了,dubbo 、canal 之类的
https://cn.dubbo.apache.org/zh-cn/docsv2.7/dev/source/dubbo-spi/
https://juejin.cn/post/7054435670244196359
onikage
220 天前
osgi 感觉不如直接上 java-agnet 简单粗暴。
sagaxu
220 天前
osgi 就是为这个而生的
fj19
220 天前
"目前协议服务已经有接近 60 个"....,哪有那么多协议,说的是报文格式?建议了解一下物模型
huzekang
220 天前
可以了解下 SOFABoot
4ra1n
220 天前
我手撸过一个:

1. 定义一套接口

2. 核心模块根据这个接口做一些事,调用具体的方法

3. 核心模块启动前使用 URLClassLoader 加载插件目录的 jar 文件

4. 插件目录的 jar 插件需要有第一步这个接口的实现

注意插件 jar 不能自己写一模一样的接口,因为是 ClassLoader 的问题,不认为是同一个类
Verizon
220 天前
没明白 一个协议服务+不同的编解码器不就行了 如果协议之间有冲突再另外分配端口
LanLiang
220 天前
在 java 里面调用 javascript 或者 groovy 来做动态解析传感器数据.
LanLiang
220 天前
协议服务的话就看 SPI 机制
siweipancc
220 天前
你没研究过日志框架吗……
或者 Hibernate
Cbdy
219 天前
没必要,直接嵌入 JS 代码就可以了
int0x03
219 天前
如果问题的核心在如何管理和维护这么多服务.
简单一点, 就使用 docker 桌面, dashboard 上面可以停止或启动某个搜集服务.
复杂一点, 就自己搭建一个 kubernetes 集群.

上面提到的 Java 提供的 SPI 本身的设计并不直接支持动态加载和卸载服务提供者,因为它的实现基于静态的 META-INF/services 配置文件和 ServiceLoader 类的设计,这些都在应用程序启动时被加载,并且在运行时不提供动态更新的机制。需要借助于 OSGI 或者自定义类加载器. 然而现实当中看到过很多没处理好加载/卸载的例子, 导致内存泄漏.
Sum0l
219 天前
kubernetes 门槛还是有一点的,一套简化的 devOps 弄下来,挺费事,也只能减轻一部分维护负担。
楼主的主要问题是微服务太多,难以管理、资源浪费,那么解决方向就是减少微服务数量。
协议 agent 服务+主程序解耦,agent 可以考虑抽象分类,一类协议集合在一个 agent 中,agent 使用 SPI 实现热插拔(类加载而已,很普遍),然后用 Spring Cloud 等做下 LB ,监控告警也方便做。
hangszhang
219 天前
groovy
hdfg159
219 天前
直接上传 动态执行 groovy 脚本就行了
night98
219 天前
建议根据通讯方式拆分成 5-6 个协议服务,然后在协议服务内部根据你的经验设计一整套的上下线及接口服务,这样后续的数据收集接入,只需要在相同协议类型的 springboot 项目下,按照 java 接口去实现一下数据的转换逻辑即可。你还可以在设计的整套方案里面加上一些监控之类的,再进一步的话就是统计啊一些什么之类的。你说的插件化没必要搞的那么麻烦,后续部署什么的也很麻烦,其实重点就是风险隔离和数据隔离,你既可以按照现有的部署模式(一个设备类型一个服务),也可以设计成代码都放一起,但是部署的时候根据参数动态的去启用禁用某些模块,也可以做成我刚开始说的那种,以几个大的项目为主,在里面包含小的模块,然后实现动态开关的方式。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1101562

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX