您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
技术中台架构升级项目之Batrix如何使用SPI支持业务扩展
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
技术中台架构升级项目之Batrix如何使用SPI支持业务扩展
自猿其说Tech
2022-11-28
IP归属:未知
17720浏览
# 1 简介 在技术中台架构升级项目中,业务BP的个性化扩展需求有两种实现方式: - API(Application Programming Interface):由业务BP定义Interface标准、开发逻辑实现,在自己的系统中维护,交由中台系统进行远程调用,实现跨应用程序的业务交互,满足扩展业务逻辑的计算。API的形式使业务解耦,相互隔离,能提升系统稳定性。在Batrix框架中有自定义能力支持API形式的业务扩展,本文不做详细介绍。 - SPI(Service Provider Interface):由中台提供系统定义Interface,基于能力能支持的扩展逻辑定义好接口。由业务BP实现Interface,进行个性化扩展业务逻辑计算。SPI的形式对修改封闭、对扩展开放,业务逻辑相对可控。 # 2 Batrix的SPI使用 在Batrix框架中,针对SPI的扩展实现,有三种形式:1、本地扩展点加载。2、本地扩展点动态加载。3、远程扩展点加载,不同的形式适用于个性化逻辑的不同复杂程度。 ## 2.1 本地扩展点加载 SPI的jar包加载形式,业务BP继承Interface接口实现个性化逻辑后,发布实现类的Jar包出来。由中台系统进行Maven引用,补充Spring xml等相关配置信息后,扩展逻辑部分和中台能力在同一台主机内运行。 1. 定义接口: 中台基于标准能力识别可扩展的业务范围,定义扩展点接口类。接口类继承BIDomainAbilityExtension做定义,BIDomainAbilityExtension为Batrix框架支持的扩展点基础接口类。 ```java /** * 特殊校验接口 */ public interface ProductSpecialCheckService extends BIDomainAbilityExtension { /** * 特殊校验方法 * @param requestProfile * @param productSpecialCheckRequest * @return */ ProductSpecialCheckResponse check(RequestProfile requestProfile, ProductSpecialCheckRequest productSpecialCheckRequest); } ``` 1. 实现接口: 继承扩展点接口类,实现个性化业务逻辑,注册成SpringBean,提供代码间相互调用。 ```java /** *特殊校验个性化逻辑实现 */ @Service public class ProductSpecialCheckExt implements ProductSpecialCheckService { @Override public ProductSpecialCheckResponse check(RequestProfile requestProfile, ProductSpecialCheckRequest productSpecialCheckRequest) { //个性化逻辑 System.out.println("我是业务逻辑"); return new ProductSpecialCheckResponse(); } } ``` 1. 引用加载: 将实现的接口类推送Jar包到仓库,由中台系统进行Maven引用,如果如需要做额外的xml配置,则直接在系统中进行配置。 这种SPI的加载方式适用于个性化逻辑简单,变动频率可控、风险可控的需求,不会对原有功能的稳定性或组织成本有较大提升。 ## 2.2 本地扩展点动态加载 SPI的Jar包动态加载形式,在本地加载形式的基础上,支持个性化逻辑的动态更新部署,不依赖于中台系统的上线。 个性化能力内部支持更为复杂、接近原生的代码开发,中台系统不用在工程项目中做太多配置,只需要在Batrix管理端进行流程编排发布,就可以实现SPI的方法调用。 SPI逻辑的运行期和中台系统在同一容器中。 - 实现SPI接口后,在实现类内开发代码逻辑,支持原生基于Spring的开发方式。 - 配置batrix_biz.xml文件,扩展点配置文件的入口类,等同于applicationContext.xml文件的作用。 ![](//img1.jcloudcs.com/developer.jdcloud.com/99c0cbe5-3daf-4ffb-8707-50d8d0d1432e20221118102536.png) - 将开发好的工程Jar推送到Maven上,基于test、uat、release等不同运行环境,运行参数不同,上传不同版本,Batrix框架提供上传打包工具,实现多版本上传。线上环境仅支持加载运行release版本,非线上环境支持snapshot版本。 - 为避免主进程包和扩展能力包、扩展能力包和扩展能力包之间产生冲突,Batrix框架做了ClassLoader的隔离加载。支持跨Jar包类之间的相互调用又避免了相互冲突影响。 - 在管理端配置扩展点实现为远程调用,即可实现动态加载。 ![](//img1.jcloudcs.com/developer.jdcloud.com/b8b3bd2c-cafb-433e-b74d-1563bf26530920221118102607.png) 这种加载方式适用于逻辑相对清晰,变动较为频繁的扩展业务。简化主进程工程的依赖配置,降低藕合,加速对接速度。ClassLoader隔离,使主进程包和扩展包能够交互又避免相互影响,提升系统稳定性。前中台的部署解耦,加速业务上线效率。 ## 2.3 远程扩展点调用 Jsf形式的远程服务接口调用,区别于日常的SPI的Jsf接口实现,Batrix支持继承中台的扩展Interface接口,由业务BP自行注册Jsf接口进行开发、管理,不仅使Jsf接口的运行期实现隔离,还支持Jsf接口的管理权限隔离,降低运营风险,提升稳定性。 1. 基于中台定义好的SPI接口ProductSpecialCheckService,继承实现自己JSF接口类: ```java package com.jd.merchant.web.product.ws; import cn.jdl.pms.extension.remote.api.ProductSpecialCheckService; public interface KysProductSpecialCheckServiceWs extends ProductSpecialCheckService{ } ``` 1. 实现接口KysProductSpecialCheckServiceWs,并发布JSF服务: ```java package com.jd.merchant.web.product.ws; import cn.jdl.pms.extension.remote.api.specialcheck.ProductSpecialCheckRequest; import cn.jdl.pms.extension.remote.api.specialcheck.ProductSpecialCheckResponse; import cn.jdl.pms.extension.remote.api.specialcheck.RequestProfile; public class KysProductSpecialCheckService implements KysProductSpecialCheckServiceWs { @Override public ProductSpecialCheckResponse check(RequestProfile requestProfile, ProductSpecialCheckRequest productSpecialCheckRequest) { System.out.println("我是业务逻辑"); return null; } } ``` 3.基于自己发布JSF接口进行运维管理: ![](//img1.jcloudcs.com/developer.jdcloud.com/937b661d-a679-4e39-9a4d-13498f6c8c4920221118103312.png) 4.在对应的流程编排中,配置对应能力远程扩展点进行调用: ![](//img1.jcloudcs.com/developer.jdcloud.com/c56b20ad-c949-402b-bf01-06979f9bf4c520221118103352.png) 远程扩展点调用适用于扩展业务逻辑复杂,变更较为频繁的业务。通过Batrix框架提升SPI的对接效率,减少中台系统配置工作,使业务扩展点对接更为灵活。扩展服务和核心服务部署解耦,独立上线,降低相互依赖,增加系统整体稳定性。 # 3 Batrix扩展点原理讲解 ## 3.1 本地扩展点加载模式 该模式近似于原生代码开发,区别在于扩展点类文件为业务需求部门承接开发,交由中台系统本地调用运行,另外需要在中台系统中进行相关xml依赖文件配置。原理等同于原生开发,不做过多讲解。 ## 3.2 本地扩展点动态加载模式 Batrix框架为更有效的为业务服务,提升业务对接效率,支持了能力共享模式。该模式支持可复用的能力进行动态加载,支持扩展点动态加载。 通过对JVM的ClassLoader进行隔离,保障动态加载包的独立依赖,避免动态加载Jar最大的冲突问题。 ![](//img1.jcloudcs.com/developer.jdcloud.com/2de203fc-7065-4bfd-8d64-e938ec6a21b620221118103701.png) - JDKClassLoader:负责基础的java类加载读取。 - BizInternalClassLoader:业务内置的加载器,负责加载各个jar包共用的class类部分,主要是结构、协议接口部分。 - ThreadClassLoader:当前线程所使用的的ClassLoader,加载jar时初始化,每个业务jar包独立使用。 - 判断是否优先读取内置加载器:通过配置,控制对公共类的加载逻辑,解决业务间内部通信问题。 通过使用和Spring相同的读取模式,最大限度的支持动态jar包的工程开发,业务开发效率更高,对开发人员更友好。 该模式在运行上依然保持核心能力和扩展逻辑运行在同一JVM中,通过动态加载将上线部署相互解耦,提升业务上线效率,使扩展点逻辑更灵活的应对业务需求的变化,提升业务竞争力。 ## 3.3 远程扩展点加载模式 远程扩展点为Batrix提供的一种JSF形式的扩展实现调用方式,由框架建立JsfConsumer链接,避免主工程引用过多的外部依赖Jar产生冲突,对接更灵活。 通过神行管理端配置扩展能力,针对扩展点配置远程调用实现: ![](//img1.jcloudcs.com/developer.jdcloud.com/e5277367-5b66-45fe-82df-2277689a1c2e20221118103805.png) Batrix框架通过识别扩展点的接口类信息和远程扩展点服务名,进行JsfConsumer创建并提供业务代码调用。 通过分析JSF实现原理发现,consumer端本质上就是基于接口的Interface类创建了JavaProxy代理类,通过代理类把方法调用转化成为网络调用,实现远程API服务调用。部分原理如下: ```java public class ConsumerConfig<T> extends AbstractConsumerConfig<T> implements Serializable { @Override public synchronized T refer() throws InitErrorException { .......... try { this.client = ClientFactory.getClient(<ConsumerConfig>this); } catch (NoRouterException e) { throw new InitErrorException(e.getMessage(), e); } this.proxyInvoker = (Invoker)new ClientProxyInvoker(<ConsumerConfig>this); ProtocolFactory.check(Constants.ProtocolType.valueOf(getProtocol()), Constants.CodecType.valueOf(getSerialization())); this.proxyIns = (T)ProxyFactory.buildProxy(getProxy(), getProxyClass(), this.proxyInvoker); ....... return proxyIns; } ``` 框架支持在不引用外部接口Jar的前提下,使用配置好的远程扩展点服务名和本地接口类信息,内部构建出来远程服务的Jsf服务接口,通过构建的接口类创建Jsf泛化调用的Consumer链接,然后本地调用转化为本地接口类进行调用,实现不引用外部Jar包能够支持进行远程调用的逻辑。部分原理如下: ```java //BP继承实现的SPI接口类 String extensionServiceApi = ""; //中台定义的SPI接口 String baseExtensionSpiName = ""; MemoryClassLoader memoryClassLoader = new MemoryClassLoader(); ClassPool mPool = ClassPool.getDefault(); CtClass cc = mPool.getOrNull(extensionServiceApi); if(cc==null){ cc = mPool.makeInterface(extensionServiceApi); cc.setInterfaces(new CtClass[]{mPool.makeClass(baseExtensionSpiName)}); } memoryClassLoader.addMemoryCalssMap(extensionServiceApi, cc.toClass()); Thread.currentThread().setContextClassLoader(memoryClassLoader); ``` 通过SPI的远程扩展点调用模式,将主业务能力和扩展逻辑部分彻底解耦。由中台部门开发规划核心逻辑和可扩展功能部分,由前台BP开发个性化扩展点,双方仅依赖于中台的一个扩展点接口类Jar包,其他全部解耦,最大限度的避免内部冲突。部门间系统边界清晰,各自运维,自行上线,加速业务对接速度,提升整体稳定性。 # 4 结语 不管是API还是SPI,都是对业务逻辑开发的一种延续,不同的形式解决不同的问题。区别不仅体现在系统工程层面,更体现在组织间的合作模式上。 Batrix致力于优化链接,基于可复用的中台能力,优化业务对接效率。在SPI上通过三种不同的加载模式,适用于各种不同的业务场景。为技术中台架构升级项目运行个性化扩展逻辑提供了底层技术支持,提升人效。 ------------ **自猿其说Tech-JDL京东物流技术与数据智能部 作者:史建刚**
原创文章,需联系作者,授权转载
上一篇:浅谈基于Web的跨平台桌面应用开发
下一篇:【敏捷研发系列】前端DevOps流水线实践
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149963
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号