1.2 微服务架构
微服务架构这个术语在最近几年的软件开发方法论中渐成热门,它把一种特定的软件应用设计方法描述为能够独立部署的服务套件。目前对于微服务架构还缺乏统一的标准化定义,但其在业务建模、服务集成、数据去中心化等方面上的抽象和提炼已得到普遍认可。在讨论微服务架构之前,我们先介绍一下微服务的概念。
1.2.1 微服务的概念
顾名思义,微服务区别于其他服务体系的关键在于它的“微”特性。“微”是“小”的同义词,所以容易让人联想到微服务都是小型的服务,这是微服务的第一个特性。然而,目前业界并没有给出一个关于微服务大小的具体划分规则和标准,本节首先会针对微服务的“微”特性展开讨论。另外,微服务之间只有通过相互的协作和交互才能构成完整的服务体系,而这种协作和交互机制也是微服务区别其他服务体系的另一个主要方面。
1.微服务的大小
通常我们可以使用代码行数、开发时间来给微服务的大小添加一些约束条件,即满足一定代码行数或开发时间之内的服务才能称为微服务。这些当然都是可衡量的量化标准,但针对具体业务场景往往不能简单通过这些指标就能得到合理的微服务划分结果。
我们认为微服务应该足够小,小到专注于某一个具体业务功能,也就是说首先应该保证每个微服务是具有业务独立性的工作单元。在考虑微服务时,我们需要根据业务边界来确定服务的边界,这样就可以把该业务相关的内容都集中在微服务内部,从而体现了服务的高内聚性。
同时,服务的大小还跟团队的规模和工作方式有较大关系。如果一个系统大到不能够由一个独立团队进行开发和维护,那么将其拆分成适合这个团队开发能力的服务无疑是合理的做法。而如果这个团队本身的规模已经大到需要进行进一步分工和协作,那么先把团队进行拆分,再根据团队拆分的结果进行服务拆分也是一项最佳实践。
然而,我们还需要认识到服务过小可能带来的问题。服务越小,其独立性和高内聚性能够带来优势,但是也会导致服务数量太多,增加管理这些服务的成本。
2.微服务的交互
微服务代表一种具体的业务功能,具有高度的内聚性并运行于独立的进程中。因此,微服务之间的交互是网络环境下分布式的交互模式。
微服务之间通过远程调用或消息传递的方式进行相互集成,能够提供松耦合的架构体系,每个微服务都可以在不影响其他微服务的前提下进行独立的修改、发布和部署。对于微服务而言,我们应该明确其对业务的抽象程度以及对外暴露这种抽象程度的方式。通常,服务接口(Interface)是每一个服务都会提供的访问入口,这些接口应该确保实现上的技术无关性。
同时,在技术实现上,我们也需要确保微服务之间采用轻量级的通信方式进行交互,因为类似采用长连接方式进行通信的过程会导致服务之间不能很好地解耦,一旦出现问题,耦合性会触发异常,在各个微服务之间进行扩散,从而导致整个服务体系不可用。这是我们在采用微服务时所需要极力避免的场景。对于轻量级通信机制而言,通常建议采用HTTP协议让服务之间的通信变得标准化和无状态化。
微服务的大小和服务之间的交互方式构成了基本的微服务体系结构,分别代表了微服务高内聚、低耦合的基本特性。在本书后续章节中,我们会集中讨论服务的边界划分原则和方法、服务管理的要求和实践以及微服务之间集成的各种技术体系。
微服务是一种服务体系,关于如何构建这种服务体系,在设计和实现上需要特定的方法论,而微服务架构就是用来构建微服务的架构模式,为我们提供了具体的方法论以及相关的工程实践。
1.2.2 微服务架构基础
微服务架构是一种架构模式,区别于其他系统架构的构建方式和技术方案,微服务架构具有其固有特点,这些特点也为我们在使用微服务架构进行系统设计的过程提供了主要的切入点。
1.微服务架构特点
马丁·福勒(Martin Fowler)指出[1],微服务架构具有以下特点。
(1)服务组件化
组件(Component)是一种可独立替换和升级的软件单元。在我们日常开发过程中可能会设计和使用很多组件。这些组件可能服务于系统内部,也可能存在于系统所运行的进程之外。而服务就是一种进程外组件,服务之间利用诸如远程过程调用(Remote Procedure Call, RPC)的通信机制完成交互。服务组件化的主要目的是服务可以独立部署。如果你的应用程序是由很多组件组成,并且这些组件运行在同一个进程中,那么对任何一个组件的改变都将导致必须重新部署整个应用程序。但是,如果你把应用程序拆分成很多服务,显然通常情况下,你只需要重新部署那个改变的服务。在微服务架构中,每个服务运行在其独立的进程中,服务与服务之间采用轻量级通信机制互相沟通。
(2)按业务能力组织服务
当寻找把一个大的应用程序进行拆分的方法时,研发过程通常都会围绕产品团队、UED团队、APP 前端团队和服务器端团队而展开。这些团队也就是通常所说的职能团队(Function Team)。当使用这种标准对团队进行划分时,任何一个需求变更,无论大小,都将导致跨团队协作,从而增加沟通和协作成本。而微服务架构下的划分方法有所不同,它倾向围绕业务功能的组织来分割服务。这些服务面向具体业务结构,而不是面向某项技术能力。因此,团队是跨职能的(Cross-Functional)的特征团队(Feature Team),包含用户体验、项目管理和技术研发等开发过程所要求的所有技能。每个服务都围绕着业务进行构建,并且能够被独立部署到生产/类生产环境。
(3)去中心化
服务集中治理的一种好处是在单一平台上进行标准化,但采用微服务的团队更喜欢不同的标准。把整体式框架中的组件拆分成不同的服务,我们在构建这些服务时就会有更多的选择。对具体的一个服务而言,应该根据业务上下文,选择合适的语言、工具进行构建。
另一方面,微服务架构也崇尚对数据进行分散管理。当整体式的应用使用单一逻辑数据库进行数据持久化时,通常选择在应用的范围内使用一个数据库。然后,微服务让每个服务管理自己的数据库,无论是相同数据库的不同实例,或者是不同的数据库系统。
(4)基础设施自动化
许多使用微服务架构的产品或者系统,它们的团队拥有丰富的持续集成(Continue Integration)和持续交付(Continuous Delivery)的经验。团队使用微服务架构构建软件需要更广泛的依赖基础设施自动化技术。
微服务同样需要考虑服务容错性设计等分布式系统所需要考虑的问题,我们对以上特点进行总结和提炼,认为微服务具备业务独立、进程隔离、团队自主、技术无关轻量级通信和交付独立性等“微”特性。
2.微服务架构设计的切入点
微服务架构设计的首要的切入点在于服务建模,尽可能明确领域的边界。我们可以充分利用领域驱动设计(Domain Driven Design,DDD)方法,通过识别领域/子域中的模块和服务、判断这些模块和服务是否独立、考虑提升某些模块和服务的层次并建立充血领域模型,从而明确各个界限上下文(Boundary Context)之间的边界。
微服务架构设计第二个切入点就是服务之间的集成方式,即需要保证集成方式的技术无关性,不要选择对服务具体实现有技术性限制的集成技术。采用技术无关的集成接口,充分融合技术多样性,意味着我们在特定场景下不应该使用类似 Alibaba Dubbo(http://dubbo.io/)这种采用私有协议、重量级的通信框架,而应该尽可能使用类如RESTful的轻量级通信方式进行服务集成,确保服务易于使用,消费方可以使用多种技术实现集成。
微服务架构设计的第三个切入点在于服务的部署,独立部署单个服务而不需要修改其他服务。同时,由于服务数量大,修改和发布的频率也可能很高,接口变化管理上通常采用逐步迁移的方案。而在接口的发布上,常见的API网关(Gateway)等模式也会得到广泛应用。
1.2.3 微服务架构与现有架构体系对比
微服务其实并不是凭空产生,而是有其历史的渊源。在微服务概念被正式提出之前,我们经常会使用面向服务架构(Service Oriented Architecture,SOA)来构建分布式服务系统。SOA 只是提出了一种架构设计思想,但没有给出标准的参考实现。而早期企业软件开发上也摸索了一套实践方式,即企业服务总线(Enterprise Service Bus,ESB)。本节通过与SOA和ESB这两种架构模式的对比来更加深入地分析微服务架构。
1.微服务架构与SOA
在山姆·纽曼(Sam Newman)的《Building Microservices》[3]一书中,作者认为微服务架构是SOA的一种实践方式,正如 XP(Extreme Programming,极限编程)或 Scrum 是敏捷软件开发的实践方式。在介绍两者之间的区别和联系之前,我们先来看一下SOA的特点。
SOA中,粗粒度的服务接口分级、松耦合的服务调用关系、标准化的服务接口、精确定义的服务契约、服务接口设计管理、支持各种消息模式等是服务的主要特征。SOA从分层上看,存在三个主要的边界,在面向用户的门户(Portal)层与提供业务功能的服务层之间,还存在一个层次用于服务之间的集成(Integration)和编排(Orchestration)。显然,各个服务通过集成和编排能够组合成更为丰富的业务功能和体系,而集成和编排能够实现的前提正是依赖于服务自身所具备的这些特征。图1-7所示的是一种典型的基于SOA的服务交互方式。
图1-7 SOA的服务交互方式
在服务实现上,因为需要考虑到服务之间的集成和编排,采用SOA时需要引入一些复杂的技术体系。以在SOA中被广泛使用的Web Service为例,复杂的交互协议使得采用SOA时需要付出巨大的代价。SOA 本身崇尚简单和互操作性,但随着事务、安全性等一系列扩展功能的出现,Web Service变成了一个庞大的WS-*协议栈,反而阻碍了服务之间的交互。
微服务架构与SOA无疑是有关联的,两者都是将业务系统拆分成各个服务并通过合适的技术完成服务的集成。微服务架构与SOA的最主要区别在于架构面向的目标。SOA通常面向的目标是企业级应用,通过 SOA 我们寄希望于将多个系统整合到一起,从而消除信息孤岛。而微服务架构则更多地关注于一个独立系统的架构,可以认为是传统模块化技术的一种替代方案。
微服务架构在服务之间同样需要实现集成,但在集成方式上强调使用轻量级的通信技术,同时去除服务编排功能。一个微服务可以调用其他微服务并在服务内部实现编排操作。这样编排操作作为微服务的内嵌功能不会暴露在集成层,从而降低服务之间的通信成本。另一方面,微服务之间的集成模式也与SOA中完全不同。由于微服务是面向业务、具备领域特性的独立服务,我们可以在用户操作层面直接进行服务集成。微服务之间的交互关系如图 1-8 所示,我们可以看到微服务可以直接面向用户,且微服务之间也可以直接进行交互,服务与服务之间没有SOA中的集中式编排机制。
图1-8 微服务架构的服务交互方式
当然,并不是说,微服务架构不能使用统一的集成和编排机制。在需要对很多服务进行统一的权限管理、日志记录、请求管理等场景时,我们也可以在这些微服务的访问入口上添加统一的拦截。在微服务架构中,我们通常使用API网关(Gateway)实现拦截处理。关于API网关的讨论我们将放在本书第4章。
由于SOA和微服务架构比较容易混淆,我们再从应用范围、灵活性、组织性和部署等方面对两者做一个对比总结。
(1)应用范围
在应用范围上,SOA是一种企业级的、面向大范围和统一化的服务化架构,而微服务架构通常用于某一个项目或产品,并不强调大而全的服务集成需求。
(2)灵活性
SOA 通过服务编排机制实现灵活性,而微服务架构的灵活性则来自于快速的开发和部署以及服务之间的独立性。
(3)组织性
通常,SOA 中的服务由不同组织中的职能团队实现,而微服务则更强调跨职能团队机制,同一项目或产品中具备各个职能的人员或团队,共同实现微服务。
(4)部署
在SOA中,部分服务仍然以单块系统的方式进行部署,而独立进程部署是微服务架构的基本特征,所有的服务都能独立部署。
2.微服务架构与ESB
消息总线(Message Bus)思想的理论基础是消息驱动的编程方法和计算机硬件总线概念。系统组件之间通过总线来进行通信,可以支持组件的分布式存储和并发运行。总线是系统的连接件,负责消息的分派、传递和过滤,并返回处理结果。总线思想在软件设计过程中应用广泛,并形成了一整套完整的企业服务总线(Enterprise Service Bus,ESB)技术体系。图1-9展示了一种典型的服务总线应用场景。我们可以看到在ESB中,系统组件并不严格区分客户端和服务器端,组件之间也不是通过消息通道进行直接交互,而是挂接在消息总线上,向总线登记自己所感兴趣的消息类型。通过这种方式,图1-9所示的企业级应用、遗留系统、核心业务服务以及其他第三方系统都可以通过总线串联起来。同时,ESB 所提供的资源适配和转换机制也能完成异构系统之间的无缝集成。
图1-9 ESB架构
在消息总线中,消息是组件之间唯一的通信方式。根据需要,消息总线对消息具备丰富的预处理功能,包括消息路由(Routing)、消息转换(Transformation)和消息过滤(Filtering)。这些预处理功能消除了数据传递在时间、空间和技术上的耦合,并提供了高度扩展性,但同时也为系统的设计和实现带来了不可避免的复杂度。
微服务架构对于ESB的改变在于强化端点(Endpoint)及弱化通道,抛弃了ESB过度复杂的业务规则编排、消息路由等功能,并引入了哑管道(Dumb Pipe)的设计理念。这里的终端是指服务本身,而哑管道是通信机制。在微服务架构中,服务作为智能端点(Smart Endpoint),所有的业务逻辑在服务内部处理,而服务间的通信尽可能的轻量化,可以是同步的远程过程调用(RPC),也可以是异步的消息传递系统,它们只作为消息通道,在传输过程中不会附加额外的业务规则。从这点上讲,微服务架构表现得更像管道-过滤器(Pipe-Filter)模式中的过滤器一样,接受请求、处理业务逻辑并返回响应。