基于中台思想的物流系统设计(五):设计可扩展的产品服务平台

一、引言

在前面四篇文章中,咱们把物流中台的基础能力层构建了起来,接下来,咱们就能够在这些基础能力之上构建咱们的产品服务,从而支撑各条业务线。
基础能力层主要关注的是稳定可用的原子接口,所以在设计的时候重点关注了不少高并发高可用的技术。产品服务层主要是为了支撑不断创新的业务,所以在设计的时候须要关注业务流程的可扩展性。下面咱们会先从总体上设计出一套抽象模型,而后针对模型的各个模块深刻介绍。

一、总体设计

写过业务代码的同窗必定知道,咱们的系统每每是由service层、manager层和远程服务层组成。这三层中,service层定义了对外的接口,manager层处理各类业务逻辑,主要是数据校验、数据组装、调用其余应用的(dubbo服务,远程服务层是对dubbo服务的包装,比较简单。当业务不断膨胀的时候,咱们可能会遇到下面的状况:
一、service层的接口愈来愈多,类似的业务定义多套接口
二、manager代码愈来愈臃肿,各类if else嵌套,每次改一点都须要测试回归整块业务
三、远程服务,特别是查询服务,在一条业务流程中的多个地方被重复调用,从而致使总体响应时间降低

对于第一个问题,咱们须要仔细分析业务,而后抽象出通用的接口,好比建立物流单,业务上既能够建立快递订单,也能够建立仓储订单,咱们须要定义一个通用的下单接口,而不是针对快递和仓储分别设计两套订单接口。而后,咱们在入参和出参上进行可扩展的设计,好比使用继承、组合的方式,在保证入参模型基本不变的状况下能够支撑不一样的业务,这样一来,新业务接入的时候,就不须要更改接口,只须要扩展入参对象就行。

对于第二个问题,咱们把manager的业务逻辑抽象为三个步骤:校验、数据转换、执行。快递有快递的校验、数据转换、执行,仓储有仓储的校验、数据转换、执行,service调用manager的时经过策略模式路由。这样一来,各个业务都是不一样的代码流程,不存在修改一点会影响全局,测试只须要关注被修改的流程,新增的业务线只须要添加一条业务流程而后配置一下路由就能够了,也不会影响老业务。

针对第三个问题,咱们能够规定把全部的数据查询都放在manager的数据转换步骤,而后经过流程上下文去传递数据,这样就不会把查询服务扩散到整个流程了。

总结下上面的三个问题的解决方案,咱们能够抽象出下面的业务流程模型:


二、接口层设计

产品服务层的接口服务遵循request-response风格,每一个方法的入参都是一个request,出参都是response。request和response经过继承和组合进行扩展。

2.一、经过继承扩展

request每每能够经过继承进行不一样业务的扩展。以物流发货来讲,发货方式有快递发货和仓储发货之分,这两种发货方式的入参不太同样,这时候咱们能够把公共的参数抽出来,而后不一样的参数下沉。咱们会定义一个LogisticsServiceDTO对象,快递和仓储分别继承它,获得ExpressLogisticsServiceDTO和WarehouseLogisticsServiceDTO,而后各自定义参数,最后咱们就能够获得以下图所示的一个request对象:


之后若是还有其余新的发货方式出现,咱们只须要定义新的LogisticsServiceDTO就能够了,接口的基本结构几乎不须要改变。

2.二、经过组合扩展

response每每能够经过组合来扩展不一样的业务,好比用户物流单详情页,须要展现物流单信息、用户信息和地址信息,咱们能够定义一个OrderDetailResponse,这个对象组合了LogisticsOrderDTO、UserDTO、AddressDTO等对象。经过组合进行扩展的方式比较常见,在此就不展开讲了。


2.三、如何定义方法

根据咱们的经验,定义方法每每须要结合业务的生命周期,拿物流接口LogisticsService来举例,咱们能够定义createLogistics、consignLogistics、logisticsCallback这三个方法。
a)、createLogistics
createLogistics是建立物流订单方法,经过定义可扩展的request对象,能够支持快递、仓储、配送等等物流订单的建立
b)、consignLogistics
consignLogistics是发货方法,经过定义可扩展的request对象,能够支持快递、仓储、配送等等物流订单的发货
c)、logisticsCallback
logisticsCallback是物流回传方法,经过定义可扩展的request对象,能够支持仓接单、仓分拣、仓出库、配送揽收、配送派送、配送签收等等物流回传过程
三个方法基本上涵盖了绝大部分业务场景,若是出现新的业务场景,首先须要评估现有的方法是否支持业务流程,若是不支持,再新增方法,好比有些物流场景存在多段发货(典型的就是农村淘宝),这时候一个consignLogistics确定是不够的,这时候就须要扩展方法。在扩展方法的时候,一开始能够就为特殊的业务开特殊的接口,等后面业务愈来愈多后,将这些特殊接口统一整理一次整理成一个通用的接口,这个过程就是一个沉淀业务模式的过程,是没法经过提早设计设计出来的,必须通过业务的不断沉淀才能跑出来。


三、接口实现层设计

说完了接口层的设计,接下来就要说说接口的实现层怎么设计。按照总体设计的思路,咱们把业务切分红一条一条的流程,而后把每条流程切分红校验、数据转换、执行三个节点,而后经过入参来决策走哪条流程。所以,一个接口的实现层其实就是一个流程决策+流程节点执行的过程。
流程决策其实就是在一张映射表里得到须要执行的节点列表,这里获取的方法能够是普通的哈希映射,也能够经过复杂的规则引擎获取。拿到节点列表(通常是节点类名)后,就能够经过spring容器获取节点对象。全部的流程节点,都会继承同一个抽象节点对象,而后实现同一个方法:execute方法,所以,经过spring容器获取节点对象后,就能够经过反射执行节点。节点与节点之间每每须要传递数据,所以节点的execute方法须要传入一个context对象,A节点在执行后将数据传入context对象,B节点执行的时候经过这个context对象获取A的数据,这就打通了节点之间的数据通道。

将上面的抽象模型带入具体的业务,咱们能够获得下面的架构:


以建立物流单为例,全部的业务代码都按照业务分散在不一样的流程节点里,入口处经过策略路由选择流程,同一个流程规定了三个节点,三个节点之间经过流程上下文传递数据,三个节点通力合做完成不一样业务的物流单的建立过程。
若是从更宏观的视角来看,产品服务层和基础能力层组合起来就是下面的架构:


产品服务层对外提供service,每一个service都定义了高度聚合的业务方法,每一个业务方法经过策略路由和流程编排,把业务代码进行隔离,业务流程中的每一个节点,调用基础能力层的原子接口进行一系列业务操做。

四、总结

产品服务平台总的思路其实就是一条很是古老的原则:对扩展开放、对修改关闭。咱们经过继承和组合,让接口的出入参变得可扩展,经过策略模式和流程节点的组合,让新老业务代码隔离,进而提高了扩展性。固然,凡有利必有弊,产品服务平台在提高了可扩展性的同时,增长了必定的代码编写量,同时对分布式事务没有太好的办法。


更多文章欢迎访问 http://www.apexyun.com/spring

联系邮箱:public@space-explore.com架构

(未经赞成,请勿转载)并发

相关文章
相关标签/搜索