随着业务的不断发展,软件系统不可避免的走向熵增:复杂度越来越高、研发效率越来越差、稳定性逐渐降低等。这时抽象核心能力,走向平台化的道路成为很多系统的首要选择。笔者结合自己的经验,总结了平台化建设的几种思路,希望对大家建设平台化有所帮助。
平台化有以下优点
平台提供类似容器的功能,业务方以Jar包形式嵌入到平台当中,类似于传统的多个war包部署在tomcat中。这种实现方式平台提供通用能力接口和业务扩展点,业务方实现业务扩展点来实现业务逻辑。一般有统一的入口(比如tomcat提供的域名+端口),根据租户标识来区分业务方(比如tomcat的serverPath),平台底层的存储及模型中也都有租户ID标识。
优势:
劣势:
处理业务隔离的常用方案:
平台也可以通过远程依赖的形式来整合业务的功能。这样能避免jar包冲突、业务功能受限等问题。此方案也会有一些限制,比如原jar包依赖的方式都是本地调用,现在都是远程调用,对性能、事务保证等都提出了新的挑战;需要保证接口的兼容性;平台与业务的交互由原来对象交互变成RPC接口,设计到编解码等;
这种方案适合平台与业务层交互较少、扩展点比较固定的场景,比如API渲染服务,平台提供渲染模板接口,业务方实现接口填充字段。
优势:
劣势:
上面讲到两种模式都是以平台为主,对上层来说都是感知的平台,适合交互接口比较固定的场景,对交互差异性大的业务不是很适合。中台式的思路是提供业务通用能力,业务方基于中台能力快速开发自己的业务,并独立提供服务或页面。
中台和平台的区别:
优势:
劣势:
DSL(Domain Specific Language)是针对某一领域,具有受限表达性的一种计算机程序设计语言。 DSL 具备强大的表现力,常用于聚焦指定的领域或问题。
在平台化建设中,DSL一般用来屏蔽平台复杂的业务逻辑,以DSL的形式对业务方暴露简洁能力接口。
比如非常有名的Gradle,就是一种DSL表达,具有比Maven更灵活的特性,关于如何构建DSL,请参考作者博客:使用Groovy构建DSL
Specification 模式用于解决「业务规则」相关的复杂性。
什么是业务规则呢?比如电商业务场景中需要判断:账户有效状态、是否是VIP、活动价有效期、账户余额等。在常规的代码开发中,有三种处理方式:
Specification模式认为校验逻辑都是“动作”,需要单独建模,且模型都是值对象,接口通用模式如下:
public interface Specification<T> {
boolean isMatch(T domainObject);
}
通过实现 Specification
接口,我们可以对不同的领域对象扩展不同的校验逻辑,而这些类都是可以复用的。
同时这些 Specification
可以作为基础元素进行任意的组合,组合更为复杂的校验规则与筛选逻辑。
当然Specification
不仅仅适用于过滤数据,它的核心是组装业务规则。例如 Spring Data JPA 提供了基于 JPA 的 Specification 模式的查询功能,使用起来非常方便,以下是一个示例:
public List<Student> getStudent(String studentNumber, String name) {
Specification<Student> specification = new Specification<Student>(){
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//用于暂时存放查询条件的集合
List<Predicate> predicatesList = new ArrayList<>();
//equal
if (!StringUtils.isEmpty(name)){
Predicate namePredicate = cb.equal(root.get("name"), name);
predicatesList.add(namePredicate);
}
//like
if (!StringUtils.isEmpty(nickName)){
Predicate nickNamePredicate = cb.like(root.get("nickName"), '%'+nickName+'%');
predicatesList.add(nickNamePredicate);
}
//最终将查询条件拼好然后return
Predicate[] predicates = new Predicate[predicatesList.size()];
return cb.and(predicatesList.toArray(predicates));
}
};
return repository.findAll(specification);
}
平台提供的通用能力如果不能直接满足业务的需求,需要提供扩展能力以适配业务模型来达到异构的目的。支持业务扩展模型一般有以下几种方式:
还有另外一个问题需要解决,平台作为通用能力,有平台自身的模型,如何将平台模型转换为业务模型?简单的做法是作为扩展点开放给业务方实现,不过作为业务方,应该关注的是业务模型,平台模型有自己的规则且平台为了通用化,模型都会非常复杂。
一个更完善的平台应该支持更灵活的异构模型支持,常用是方案是字段配置化:
平台除了平台通用模型的存储支持,还需要支持不能转换为平台模型业务模型存储。有以下几种方案:
平台化建设是一个非常复杂的工程,涉及的业务方、方案选择比较多,难点和投入成本也都差异较大,没有一套完美的方案能覆盖所有业务场景,本文提供了几种参考方案和设计模式,具体的方案还需要读者结合自己的业务场景来挑选最适合自己的方案。
作者简介:木小丰,美团Java技术专家,专注分享软件研发实践、架构思考。欢迎关注公共号:Java研发
本文链接:平台化建设思路浅谈