V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GayGayUp
V2EX  ›  Java

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

  •  
  •   GayGayUp · 3 天前 · 1597 次点击

    简单说一下背景:

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

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

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

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

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

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

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

    1. 定义一套接口

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

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

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

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

    上面提到的 Java 提供的 SPI 本身的设计并不直接支持动态加载和卸载服务提供者,因为它的实现基于静态的 META-INF/services 配置文件和 ServiceLoader 类的设计,这些都在应用程序启动时被加载,并且在运行时不提供动态更新的机制。需要借助于 OSGI 或者自定义类加载器. 然而现实当中看到过很多没处理好加载/卸载的例子, 导致内存泄漏.
    Sum0l
        17
    Sum0l  
       2 天前
    kubernetes 门槛还是有一点的,一套简化的 devOps 弄下来,挺费事,也只能减轻一部分维护负担。
    楼主的主要问题是微服务太多,难以管理、资源浪费,那么解决方向就是减少微服务数量。
    协议 agent 服务+主程序解耦,agent 可以考虑抽象分类,一类协议集合在一个 agent 中,agent 使用 SPI 实现热插拔(类加载而已,很普遍),然后用 Spring Cloud 等做下 LB ,监控告警也方便做。
    hangszhang
        18
    hangszhang  
       2 天前
    groovy
    hdfg159
        19
    hdfg159  
       2 天前 via iPhone
    直接上传 动态执行 groovy 脚本就行了
    night98
        20
    night98  
       2 天前
    建议根据通讯方式拆分成 5-6 个协议服务,然后在协议服务内部根据你的经验设计一整套的上下线及接口服务,这样后续的数据收集接入,只需要在相同协议类型的 springboot 项目下,按照 java 接口去实现一下数据的转换逻辑即可。你还可以在设计的整套方案里面加上一些监控之类的,再进一步的话就是统计啊一些什么之类的。你说的插件化没必要搞的那么麻烦,后续部署什么的也很麻烦,其实重点就是风险隔离和数据隔离,你既可以按照现有的部署模式(一个设备类型一个服务),也可以设计成代码都放一起,但是部署的时候根据参数动态的去启用禁用某些模块,也可以做成我刚开始说的那种,以几个大的项目为主,在里面包含小的模块,然后实现动态开关的方式。
    GayGayUp
        21
    GayGayUp  
    OP
       1 天前
    @night98 将相同协议类型当成一个服务也考虑过,最大的问题是没办法区分上报内容来源于什么设备;
    例如有两款设备都是 tcp 协议,上报内容分别为:FF0001 、FF0002 (0001 和 0002 为设备号),所以作为开发者,仅仅知道设备号,无法区分属于什么设备;
    GayGayUp
        22
    GayGayUp  
    OP
       1 天前
    @onikage 感谢,我研究下
    GayGayUp
        23
    GayGayUp  
    OP
       1 天前
    不一个一个 @了,我这里统一回复感谢回复的各位,我研究研究各位大神的方案
    night98
        24
    night98  
       1 天前
    @GayGayUp #21 我没太懂哈,你不同的设备你是怎么去分流接入的,不是按照端口号或者路径啥的去分流吗?为什么会不知道是什么类型的设备。还是说你接入的时候都是同一个入口?那也不对呀,按照你现在的方案分开部署,那也是要用一种方式去区分设备类型的,你不会是按照 ip 或者域名去区分设备类型的吧。比如 tcp 的协议设备,你一个服务可以起多个端口啊,根据配置动态监听就行啊。
    GayGayUp
        25
    GayGayUp  
    OP
       1 天前
    @night98 感谢提醒!你点到我了,的确可以这么做。这么简单的问题我咋想复杂了呢,无语。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   958 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 21:24 · PVG 05:24 · LAX 13:24 · JFK 16:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.