当前位置: 首页 > 后端技术 > Java

平台建设思路浅谈

时间:2023-04-02 00:23:07 Java

随着业务的不断发展,软件系统不可避免地趋于熵增:复杂度越来越高,研发效率越来越差,稳定性逐渐下降。这时候,抽象出核心能力,走向平台化,就成了很多系统的首要选择。笔者根据自己的经验,总结了几个搭建平台的思路,希望对大家搭建平台有所帮助。平台化有以下优势:复用性强:核心逻辑复用,业务功能只构建在平台之上的业务层,降低构建成本;研发效率高:平台服务作为通用的能力基础设施,业务只需要关注需求,不用关心在平台底层实现复杂的能力;降低复杂性:平台职责边界和模块划分合理,对外开发的接口也直观简洁;稳定性:平台服务的稳定性是重中之重,一般都有专门的团队维护,稳定性强于一般业务系统;平台搭建的几种方式1、嵌入式平台提供类容器的功能,业务端以Jar包的形式嵌入到平台中,类似于传统的tomcat部署多个war包。该实现方法平台提供通用的能力接口和业务扩展点,业务方实现业务扩展点实现业务逻辑。一般有统一的入口(比如tomcat提供的域名+端口),根据租户ID(比如tomcat的serverPath)来区分业务方,平台的底层存储和模型也有tenantID标识符。优势:运维:平台统一运维,减少业务方的工作量;对外接口:统一的对外接口,减少调用方的工作量;缺点:业务方功能受限:一般无法做重量级任务,平台是基于扩展点的方法提供给业务方进行扩展,其他能力应该受到限制;jar包冲突和类冲突:平台自身依赖较多,业务端jar包依赖也较多。如果发生冲突,整个平台将不可用,下面将介绍几种避免方法;业务隔离性差:不同的业务方可能会相互影响;业务隔离的常用解决方案:每个业务方提供一个集群;使用类加载器隔离jar包,但仍然可能无法解决jar包冲突的问题;业务方提供fatjar,更改所有依赖包的包路径,如MavenShadePlugin插件;2.接口依赖平台也可以通过远程依赖来集成业务功能。这样可以避免jar包冲突、业务功能受限等问题。这个解决方案也会有一些限制。比如原来的jar包依赖本地调用,现在都是远程调用,对性能和事务保障提出了新的挑战;需要保证接口兼容性;平台与业务的交互,从原来的对象交互到RPC接口,从设计到编解码等;该方案适用于平台与业务层交互较少,扩展点相对固定的场景,比如API渲染服务,平台提供渲染模板接口,业务方实现接口填写字段。优点:隔离:平台和业务完全隔离;业务方方便集成其他业务:平台扩展点只是业务方的一种能力,可以在现有服务上提供;缺点:接口变更复杂:如果要变更接口,所有业务方都需要迭代;交互复杂:都是通过RPC进行交互,需要将一些扩展字段编解码成String传输;平台端:如果业务端的服务端出现异常,需要平台端提供限流、降级、自下而上的能力;3、中型和桌面型。以上两种模式都是基于平台的。对于上层来说,都是感知平台。它们适用于交互界面相对固定的场景,但不太适合交互差异较大的业务。中台的思路是提供通用的业务能力,业务方可以基于中台能力快速开发自己的业务,独立提供服务或页面。平台与平台的区别:角度不同:平台侧重于去重和集成;为其他产品提供更好的服务;优点:能力专注??:只需要提供核心能力支持,不关心与用户的交互;更易复用:平台不依赖于业务的扩展点,只是业务方对平台的单向依赖;缺点:个性化能力弱:因为没有扩展点,只提供通用能力;平台建设的常见模式1.DSL领域特定语言DSL(DomainSpecificLanguage)是一种针对某一领域的有限表达的计算机程序设计语言。DSL富有表现力,通常用于关注特定领域或问题。在平台建设中,一般使用DSL来屏蔽平台复杂的业务逻辑,将简单的能力接口以DSL的形式暴露给业务方。比如非常有名的Gradle就是一个DSL表达式,比Maven具有更灵活的特性。关于如何构建DSL,请参考作者的博客:使用Groovy构建DSL2,Specification模式Specification模式用于解决与“业务规则”相关的复杂性。什么是商业规则?比如在电商业务场景中,需要判断:账户的有效状态,是否是VIP,活动价格的有效期,账户余额。在常规的代码开发中,有3种处理方式:在业务流程代码中逐例编写;缺点是会导致可重用性和可维护性较差;新建静态类,如OrderValidator、TimeValidator等,缺点是不足以处理组合逻辑(与,或);在模型类中进行checking时,缺点是类中会混入越来越多的非领域逻辑,过多的逻辑会掩盖业务的核心业务规则;规范模式认为验证逻辑都是“动作”,需要单独建模,模型都是值对象。接口的一般模式如下:publicinterfaceSpecification{booleanisMatch(TdomainObject);}通过实现Specification接口,我们可以为不同的领域对象扩展不同的验证逻辑,并且这些类是可重用的。同时,这些Specifications可以作为基本元素组合起来,组合更复杂的验证规则和过滤逻辑。当然,Specification不仅仅适用于过滤数据,其核心是组装业务规则。比如SpringDataJPA提供了基于JPASpecification模式的查询功能,使用起来非常方便。下面是一个例子:publicListgetStudent(StringstudentNumber,Stringname){Specificationspecification=newSpecification(){@OverridepublicPredicatetoPredicate(Rootroot,CriteriaQueryquery,CriteriaBuildercb){//临时存放查询条件的集合ListpredicatesList=newArrayList<>();//等于if(!StringUtils.isEmpty(name)){PredicatenamePredicate=cb.equal(root.get("name"),name);predicatesList.add(namePredicate);}//likeif(!StringUtils.isEmpty(nickName)){PredicatenickNamePredicate=cb.like(root.get("nickName"),'%'+nickName+'%');predicatesList.add(nickNamePredicate);}//最后把查询条件放在一起返回Predicate[]predicates=newPredicate[predicatesList.size()];返回cb.and(predicatesList.toArray(predicates));}};返回repository.findAll(specification);}3。如果异构平台提供的通用能力不能直接满足业务的需求,就需要提供扩展能力来适应业务模型,从而达到异构的目的。支持业务扩展模型一般有以下几种方式:StringextMapextClass:一般用于嵌入jar。还有一个问题需要解决。作为通用能力,该平台有自己的模型。如何将平台模式转化为商业模式?简单的方法就是作为扩展点开放给业务方。但是,作为业务方,应该注意业务模型。平台模型有其自身的规律,要通用化的平台模型会非常复杂。一个更完整的平台应该支持更灵活的异构模型支持。常见的解决方案是字段配置:在平台上申请一个模型定义,一般包括类型、长度、限制规则等(比如必须是正整数);业务端配置字段与平台模型的映射关系,如果需要动态能力,可以提供Groovy或Aviator等脚本支持;转换为业务模型:根据用户配置自动转换业务模型返回给用户;转换为平台模型:需要在参数中输入元数据类名,平台会根据配置规则验证有效性;如果需要自动转换,需要在配置服务中支持双向映射。商业模式存储。有以下解决方案:宽表:使用列式存储引擎,可以方便地创建和修改列。缺点是常用的列式存储引擎一般不能提供很好的事务支持;列转换:数据表只有id、key、value这三列,在查询和存储时在repository层进行转换。缺点是不能join,不支持修改列;适用于不太复杂的业务场景;元数据:完全接管数据库操作,根据不同的字段格式自动存储不同的列,一个完整的元数据平台还支持分库分表、扩缩容、数据迁移等能力,构建成本最高;综上所述,平台建设是一个非常复杂的工程,涉及到的业务方和选项多,难点和投资成本也有较大差异。没有完美的解决方案可以覆盖所有业务场景。本文提供了几种参考解决方案和设计模式。对于具体的解决方案,读者需要结合自身的业务场景,选择最适合自己的解决方案。.作者简介:穆晓峰,美团Java技术专家,专注于分享软件开发实践和架构思维。欢迎关注公众号:Java研发文章链接:浅谈平台搭建思路