在本书中,我们通过构建一个精简但又完整的系统来展示微服务架构相关的设计理念和常见实现技术。该案例系统称为订单系统(SpringOrder),试图对互联网应用中最常见的订单业务做抽象。现实环境中订单业务非常复杂,而该案例的目的在于演示从业务领域分析到系统架构设计再到系统实现的整个过程,不是重点介绍具体业务逻辑,所以在业务领域建模上做了高度抽象。
按照实施微服务架构的基本思路,服务建模是案例分析的第一步。服务建模包括服务拆分和集成策略的确定。
SpringOrder系统包含的业务场景比较简单,即用户浏览商品,然后在商品列表中选择想购买的商品并提交订单。而在提交订单的过程中,我们需要对商品和用户账户信息进行验证。从业务领域的角度进行分析,我们可以把该系统分成三个子域。
❑ 商品(Product)子域:商品管理,用户可以查询商品以便获取商品详细信息,同时基于商品提交订单;系统管理员可以添加、删除、修改商品信息。
❑ 订单(Order)子域:订单管理,用户可以提交订单并查询自己所提交订单的当前状态。
❑ 用户账户(Account)子域:用户管理,我们可以通过注册操作成为系统用户,同时也可以修改或删除用户信息;需要提供账户有效性验证的入口。
从子域的分类上讲,用户账户子域比较明确,显然应该作为一种通用子域。而订单是Spring-Order系统的核心业务,所以订单子域应该是核心子域。至于商品子域,在这里比较倾向于归为支撑子域。而针对子域之间的上下游关系,订单子域需要同时依赖商品子域和用户账户子域,商品子域和用户账户子域之间不存在交互关系。三个子域之间的交互关系如图1-10所示。
图1-10 SpringOrder子域之间的交互关系
为了简单起见,我们对每一个子域都提取一个微服务。这样,我们可以把SpringOrder系统简单划分成三个微服务,即product-service、order-service和account-service,图1-11展示了SpringOrder服务交互模型。在图1-11中,三个微服务之间需要基于REST API完成跨服务之间的交互。
如果我们引入UML(Unified Modeling Language,统一建模语言)中的时序图(Sequence Diagram)来进一步展示SpringOrder系统的完整交互过程,可以得到如图1-12所示的时序图。
图1-11 SpringOrder服务交互模型
图1-12 SpringOrder服务交互时序图
图1-11所示的三个微服务构成了SpringOrder的业务主体,而要构建一个完整的微服务系统,我们还需要引入其他很多业务类服务和基础设施类服务,这些服务从不同的角度为实现微服务架构提供支持。本书后面将要介绍的Spring Cloud Alibaba中的各项核心技术都会在该案例中得到体现。关于该案例的完整代码,见https://github.com/tianminzheng/spring-order。
当然,通过案例帮助你构建微服务系统是本书的一大目标,但不是唯一目标。作为扩展,笔者希望你通过对优秀开源框架的学习,掌握微服务核心组件背后的运行机制,从而深入理解分布式系统以及微服务架构的实现原理,以从容应对来自面试和就业的挑战。
由于不同团队和组织对于微服务系统的实现方法和过程可能都是不一样的,而业界关于如何实现微服务架构也存在一定的最佳实践,因此,在正式进入案例系统的讲解之前,我们需要约定系统的实现过程和技术组件,以便你快速掌握系统的构建策略。
1.初始化代码工程
在本书中,我们统一使用Maven作为代码工程的构建工具。Maven是一款主流的自动化构建工具,为系统提供了完整的构建生命周期和标准化构建过程。另外,Maven不仅仅是一个构建工具,它也能帮助开发团队构建中央仓库并实现代码组件之间的依赖管理。关于Maven工具的介绍不是本书的重点,你可以参考官方网站https://maven.apache.org/进行学习。
在使用Maven时,笔者推荐的一项最佳实践是构建一个用来管理依赖的专用代码工程,这样系统中的其余代码工程都可以基于这个依赖管理专用代码工程来获取所需要的组件,从而实现统一化的依赖管理机制。图1-13展示的就是在SpringOrder中引入的一个dependency代码工程。
从图1-13中可以看到,dependency代码工程中没有任何业务代码,只包含了一个POM文件,该POM文件中定义了SpringOrder项目构建所需的所有依赖包,例如最基础的Spring Boot、Spring Cloud和Spring Cloud Alibaba,如代码清单1-1所示。
图1-13 SpringOrder中的代码工程
代码清单1-1 Maven POM中基础依赖包定义代码
在图1-13中,我们还发现存在一个infrastructure-utility代码工程,该代码工程的定位就是为SpringOrder项目提供基础设施类的工具服务,包结构如图1-14所示。
图1-14 infrastructure-utility代码工程中的包结构
不难看出,infrastructure-utility内置了AOP(对应aop包)、缓存(对应cache包)、配置(对应config包)、异常处理(对应exception包)、唯一性Id(对应id包)等工具组件。随着SpringOrder项目的不断演进,我们会逐一介绍这些工具组件的使用场景和实现方法。
2.组件设计规范和约定
介绍完SpringOrder项目的整体代码工程,我们进入具体的业务服务,看看如何合理组织业务服务中的技术组件。
对于一个普通的业务服务而言,处理业务逻辑的核心流程还是基于经典的三层架构,即Web服务层→业务逻辑层→数据访问层,如图1-15所示。
在图1-15中,我们对三层架构中每一层的输入和输出做了约定,并引入了VO(Value Object,值对象)和领域对象(Entity,实体)的概念。这是组件之间进行数据传递的最基本实现策略,实现了数据结构的解耦。通过引入专门的数据转换工具,我们可以实现VO和Entity之间的有效转换。同时,我们在Web服务层和业务逻辑层之间还嵌入了AOP拦截机制。
明确了业务服务的技术组件,我们接下来分析它的代码包结构。这里也对包结构的命名做对应的约定,如图1-16所示。
图1-16中各个包结构的命名都是自解释的,唯一需要注意的是“integration”代码包。当某一个业务服务需要与其他服务进行交互时,我们会把实现服务与服务之间集成的代码放在该代码包中,它相当于充当了服务与服务之间的防腐层(Anti-Corruption Layer, ACL)。
图1-15 三层架构组件和交互流程
图1-16 order-service代码工程中的包结构