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

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

  •  
  •   GayGayUp · 17 天前 · 2000 次点击

    简单说一下背景:

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

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

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

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

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

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

    26 条回复    2025-01-16 15:24:09 +08:00
    weenhall5
        1
    weenhall5  
       17 天前
    osgi
    2han9wen71an
        2
    2han9wen71an  
       17 天前
    osgi
    lolita89201
        3
    lolita89201  
       17 天前
    楼上说的 osgi 没用过。 但是 java 做插件化非常容易, 定义好统一的接口, 不同的模块都编译成 jar , 然后动态加载 jar 的 class , 用反射的方式去执行接口函数就好了。
    matcloud
        4
    matcloud  
       17 天前
    Java SPI 了解下,以前给我们平台用这个技术实现过插件系统。
    byteLoading
        5
    byteLoading  
       17 天前   ❤️ 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  
       17 天前
    osgi 感觉不如直接上 java-agnet 简单粗暴。
    sagaxu
        7
    sagaxu  
       17 天前
    osgi 就是为这个而生的
    fj19
        8
    fj19  
       17 天前
    "目前协议服务已经有接近 60 个"....,哪有那么多协议,说的是报文格式?建议了解一下物模型
    huzekang
        9
    huzekang  
       17 天前
    可以了解下 SOFABoot
    4ra1n
        10
    4ra1n  
       17 天前
    我手撸过一个:

    1. 定义一套接口

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

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

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

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

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