1.2 服务建模方法
如同系统架构设计首先需要进行业务建模一样,微服务架构的设计同样从服务建模开始。一般而言,软件行业建模工作的目的在于将业务需求转变为一种能够直接用于软件实现的载体,以UML(Unified Modeling Language,统一建模语言)为代表的建模语言是这种载体的具体表现形式。在微服务架构中,服务建模的目的同样是为了便于开发人员开展后续的服务设计和实现工作。本节讨论微服务建模的切入点,包括服务的模型、服务的边界和服务的数据。
1.2.1 服务的模型
服务模型提供服务的概念模型,并给出服务的统一表现形式。服务的概念模型来自两个维度:一个是服务标准,即什么样的服务才是一个好的服务;另一个是服务级别,即不同的服务应该具备不同的重要性。
关于服务标准,SOA体系中的很多设计理念同样适合于微服务架构,包括服务无状态(Service Statelessness)、服务可重用(Service Reusability)、服务可发现(Service Discoverability)、服务自治(Service Autonomy)和服务松耦合(Service Loose Coupling)等在内的设计原则都是服务设计上的核心标准。
关于服务级别,可以从发生具体事故时服务对用户体验的影响、所造成的经济损失等角度对服务进行具体分级。在服务分级上,一种常见的分级方法是将系统服务分成3个不同的等级:一级服务具备完善的容错降级机制及对低级别服务的熔断措施、定期压测、配置高级别的监控报警流程等;二级服务多采用异步方式进行系统交互,容忍暂时数据不一致性;三级服务则可随时降级整个服务。
服务需要具备统一的表现形式,也就是需要具备契约化的约束条件,而这种契约化的约束条件一般可以通过文档的方式进行展现。对于每一个服务而言都应该提供一份契约文档,并发布到统一的管理平台以方便服务相关人员进行查看和更新。服务契约(Service Contract)化要求至少对服务的几个基本方面作出说明,包括具体接口的API接入技术说明;服务能力的描述(如服务所属的业务模块、所能提供的业务功能以及具体的应用场景);提供这些能力所约定的一些限制条件说明(这些限制条件多数与业务场景有关,现实中以下这种情况并不少见,即同一个接口定义以及其所代表的业务能力在不同的场景中会出现不同的表现形式);支持的最新版本和历史版本的说明(这点对于微服务而言是必备的要素)。显然,将服务契约化有助于在开发人员之间形成统一语言,减少多余且可能反复的口头沟通,降低协作成本。
1.2.2 服务的边界
在明确了服务分类和服务模型之后,接下去的工作就是识别服务,识别服务的切入点在于识别服务与服务之间的边界(Boundary)。明确服务边界是下一节中将要介绍的服务拆分与集成的前提。
在微服务架构中,识别服务边界的方法可以参考领域驱动设计思想。在领域驱动设计中,有两个主要的设计维度,即设计的策略维度和设计的技术维度。其中,设计的策略维度更关注如何设计领域模型以及对领域模型的划分,其目的在于清楚划分不同的系统与业务关注点。策略维度是一个面向业务、具备较高层次的设计维度,更偏重于业务架构的梳理以及考虑如何把业务架构和技术架构相结合的问题。策略维度的通用语言(Ubiquitous Language)、子域(Sub-Domain)、界限上下文(Boundary Context)等概念为识别服务边界提供了一整套方法论。设计的技术维度包含聚合(Aggregate)、领域事件(Domain Event)等组件,有助于组织服务内部以及服务与服务之间进行交互的方式。关于领域驱动设计的更多内容可以参考相关资料。
在通过使用领域和界限上下文进行服务边界划分的过程中,也存在一些服务边界划分的原则。常见的边界划分原则包括服务关联度原则、业务能力职责单一原则、读写分离原则以及组织关系原则。
1.2.3 服务的数据
通过确定服务边界,服务在逻辑上就变成了一个个独立的个体,但是我们还要小心一个并不容易进行独立处理的因素,那就是数据。绝大多数服务都会依赖数据,而很多数据可能也会被一批服务所依赖。
规范化数据模型是传统关系型数据库设计的核心,即通过三大范式实现数据的有效存储,并为开发人员提供一整套对数据的操作方式。规范化数据模型有利有弊,它虽然为如何管理关系型数据提供了最佳设计理念,但同时也限制了数据查询的灵活性和高效性,特别是当查询涉及很多关联(Join)场景时,会导致查询性能严重低下。规范化数据模型的另一个问题在于中心化思想,即把数据统一存储在一个中央数据库中。当大量数据存在于同一数据库时容易造成数据库访问瓶颈,从而影响数据访问性能,并为系统可用性埋下隐患。
针对规范化数据模型存在的以上问题,微服务架构中数据管理的基本思路就是数据去中心化。数据去中心化场景包括跨表查询场景、跨库查询场景以及技术耦合场景。在对数据去中心化进行不断尝试的过程中,采用“代码分离→重复数据库模式→迁移数据读写操作→抽取服务化接口”等步骤构成了完整的数据去中心化流程。关于各种数据去中心化场景、应对方式以及去中心化工作流程的详细描述,可以参考笔者所著的《微服务设计原理与架构》一书。