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

5 天前
 GayGayUp

简单说一下背景:

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

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

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

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

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

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

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

1. 定义一套接口

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

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

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

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

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

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

https://www.v2ex.com/t/1101562

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

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

© 2021 V2EX