一种用于可扩展的基于微服务的系统的模式语言

摘要

微服务是一种新兴的分布式架构风格,用于构建高度可扩展的 Web系统。尽管已提出了许多针对微服务的设计模式,其中 一些也涉及可扩展性,但这些日益增长的内容尚未被组织成一 个连贯且易于使用的模式语言。本文基于先前识别出的针对基 于微服务系统的现有模式的研究,选取与可扩展性相关的模式, 并将其按照三个著名的可扩展性维度(也称为X轴、Y轴和Z轴) 划分为三类:负载均衡、分解和分组。本文通过一个案例研究 来说明该模式语言的使用,该案例研究记录了一个实时公交位 置采集应用的架构。这种基于原则的模式语言为组织当前和未 来解决基于微服务系统可扩展性问题的模式提供了坚实的基础。

关键词
微服务, 模式语言, 可扩展性, 软件架构

1 引言

微服务最近已成为一种流行的架构风格,用于满足由 Netflix 和 Uber 等知名公司部署的大型 Web 应用程序的可扩展性需求。微服务的核心思想是,将各个应用程序作为一组通过消息交换进行通信的小型服务部署到云实例上 [22]。这些应用程序属于分布式系统,因为它们由位于联网计算机上的组件构成,并通过消息传递来协调其操作 [30]。基于微服务的系统与分布式系统之间的类比已被广泛讨论 [28][9][10][22],并且已经明确,这种架构所面临的挑战与分布式系统的挑战类似。

其中一个挑战是可扩展性,Weinstock 等人 [32] 将其定义为“处理增加的工作负载的能力”,这是所有分布式系统的共同特征。

从设计的角度来看,了解可扩展性问题的常见解决方案是很必要的。专业文献记录了越来越多用于构建基于微服务系统的技术,包括相当多的设计模式。然而,这些技术尚未被组织成针对特定质量属性(QA)或非功能性需求(NFR)的模式语言,这限制了它们在实际应用中的潜力。

本文解决了现有设计模式在组织基于微服务的系统可扩展性方面的问题。提出了一种可扩展性模式语言,用于构建高可扩展性基于微服务的系统,该语言整理了先前系统性研究[23]中识别、组织和分类的可扩展性模式。为了说明和评估该模式语言,本文描述了其在记录实时公交位置采集系统架构中的应用。因此,本研究的主要贡献如下:

  • 一份用于可扩展性的微服务架构模式的初步列表。
  • 一种基于可扩展性需求的、由可扩展性维度、模式类别、架构模式和架构分解组成的系统化模式分类法。
  • 一种用于构建高可扩展微服务系统的模式语言。

本文其余部分组织如下:第2节介绍基于微服务的系统、可扩展性以及微服务模式的主要概念;第3节引入一种模式语言,围绕三个可扩展性维度对现有微服务模式进行组织;第4节通过一个案例研究说明该模式语言的应用;第5节回顾相关工作;第6节进行总结并得出结论。

2 背景与先前工作

在本节中,我们将介绍本研究的两个最相关概念:基于微服务的系统和可扩展性。

2.1 基于微服务的系统

微服务架构风格是一种将软件应用作为一组独立可部署、小型、模块化服务进行开发的方法,每个服务都作为一个单一进程运行,并通过明确的轻量级机制进行通信,以实现业务目标 [22]。微服务可以彼此独立地替换系统中的服务,围绕业务能力进行组织,并使用智能端点 [16]。

微服务架构源于面向服务的架构(SOA)[11]。SOA 是一种软件架构模式,其中应用程序组件通过网络上的通信协议向其他组件提供服务,通信可以是简单的数据传递,也可以包括多个协调服务相互连接。这一描述表明,SOA 是分布式计算的范例,也是一种软件设计风格。

尽管在软件应用中使用SOA具有优势,但其在独立部署/开发、故障隔离以及可扩展性/可用性方面的不足,促使人们转向微服务。许多大型系统从由相互连接、相互依赖的组件构成的自包含mono-lithic应用(见图1-a)演变为大型服务集合(即传统SOA),并进一步演变为小型、自治、轻量级互联的服务集合(见图1-c)。

示意图0

市场需求的高速度要求应用程序本身(松耦合和高可扩展性)以及其构建方式(团队间松散依赖和快速部署)都需要做出改变。微服务能够同时解决这两个问题,因为小型服务可以由独立的开发团队进行构建和部署;这种相伴而生的自由度使团队能够专注于改进每个服务,从而提升业务价值。因此,在实践中,DevOps(开发与运维)和持续交付 [12] 与微服务架构高度契合。

2.2 基于微服务的系统中的可扩展性

可扩展性 [15]是一种系统属性,用于描述增长和管理高工作量及资源需求的能力。它涉及多个知识领域,在软件架构中,可扩展性是一种质量属性(QA),描述了流程、网络、软件或组织应对增长和增加需求的能力[1]。

艾博特和费舍尔 [1]将可扩展性与科技公司面临的三大问题联系起来:(1)系统停机可能代价高昂,(2)故障需要快速修复,以及(3)未能修复中断会导致更多时间用于修复故障,而更少时间用于新产品和功能的开发。他们提出了一个具有三个扩展维度的规模立方体:克隆实体或数据并将工作均匀分配给各个工作者(“层”,X −轴);按活动或数据均匀划分工作(“组件”,Y −轴);以及根据工作请求者划分工作(“分片”,Z −轴)。

Fowler [16]认为,在微服务生态系统中,每个微服务都需要能够扩展整个系统,而不会遭遇性能问题。我们注意到,三个轴与基于微服务的系统中的可扩展性问题相匹配,正如我们之前的研究[18]所发现的,可扩展性是微服务研究中的一个关键区分特征。规模立方体与微服务之间的类比[13]如图2所示。

示意图1

2.3 微服务架构模式

正如我们在第2.1节中所述,行业采用微服务方法的需求催生了关于软件架构的新知识。这些知识引发的一个重要方向是发现了用于微服务应用开发的新架构模式。

我们回顾了工业界和学术文献[18][23]中提出的微服务架构模式。在学术方面,我们从多个会议的论文集中找到了相关证据,包括物联网设计与实现;数据库、知识和数据应用进展; ICSA(国际软件架构会议);以及ECSA(欧洲软件架构会议)。在工业方面,我们调研了博客(例如,[26])和白皮书。(有关研究详情及发现的模式,请参见 https://goo.gl/vejRR8。)

最后,我们根据这些架构模式描述中提取的目的,将它们进行分组(参见图3中的分类法),以帮助实践者识别与解决当前特定问题相关的架构模式。

示意图2

3 可扩展性的模式语言

3.1 识别可扩展性模式

提出的分类法能够识别出用于解决微服务系统中特定问题的架构模式,例如编排、迁移和通信。然而,尽管该分类法适用于所有质量保证情况,但它并未提供针对可扩展性问题的具体建议。为此,我们提出一种模式语言,用于选择和组织仅与实现高可扩展性相关的架构模式。

相关架构模式的选择过程包含两个主要活动:

(1)阅读模式描述 研究团队的每位成员阅读了每个架构模式的文档,选出与可扩展性相关的模式,并进行展示,包括其相似性和差异性。随后,团队获得了一份包含38个可能的可扩展性架构模式的列表(参见表2中选择标准的满足百分比;得分为100%的已突出显示)。

(2) 按标准过滤模式 我们使用了四个标准,利用Bondi的指南 [6],来筛选候选模式,并获得一份最终的可扩展性架构模式列表。这些标准例证了应用程序中发现的可扩展性类型;它们是:

(a) 负载可扩展性:系统在轻载、中等或重负载下,能够优雅地运行,即 .e.,没有过度的延迟和无谓的资源消耗或资源争用,同时充分利用可用资源。

(b) 空间可扩展性:当系统所支持的项目数量增加时,其内存需求是否不会增长到不可接受的水平。如果特定应用或数据结构的内存需求随相关元素数量的增长至多呈亚线性增长,则称其为具有空间可扩展性。

(c) 时空可扩展性:当系统所包含的对象数量增加几个数量级时,系统是否仍能继续平稳运行。如果用于实现系统的数据结构和算法能够在系统规模适中或较大时都有利于平稳快速运行,则该系统可能具有时空可扩展性。

(d) 结构可扩展性:系统的实现或标准是否至少在选定的时间范围内不会阻碍其所包含对象数量的增长。

表3描述了每个选定的模式;按照惯例(并由[2]推荐),它包含上下文(应用该模式的情境)、问题(要解决的困境描述),以及解决方案(应遵循的策略)。

3.2 组织模式:一种可扩展性的模式语言

本节阐述了一种将第3.1节中选定的模式组织为高可扩展性基于微服务的系统的模式语言(见表1)的提议;该想法最初受到梅萨罗斯和多布尔[20]以及赵等人[33]早期提议的启发。

维度 模式类别 架构模式 架构分解
X‐轴扩展 负载均衡器模式 内部负载均衡器模式 通信组件
X‐轴扩展 负载均衡器模式 外部负载均衡器模式 通信组件
Y‐轴扩展 分解模式 分解单体模式 服务
Y‐轴扩展 分解模式 更改代码依赖模式 服务
Y‐轴扩展 分解模式 断路器模式 服务
Y‐轴扩展 分解模式 每个数据库服务模式 服务
Z‐轴扩展 分组模式 服务发现模式 服务发现组件
Z‐轴扩展 分组模式 部署集群模式 服务发现组件
Z‐轴扩展 分组模式 容器模式 服务发现组件

该模式语言围绕规模立方体构建,规模立方体在设计系统以及改进现有系统时提出了三个可扩展性轴。它将这些轴视为可扩展性维度,并包含三个模式类别,每个类别对实际已发布的模式进行分组,这些模式根据其文档中针对特定可扩展性维度的分类而归类。这些维度和模式类别包括:

  • X轴扩展 :此轴侧重于在负载均衡器后运行多个相同的应用程序副本,以提高其容量和可用性。–负载均衡器模式:一种高效且可重复的解决方案,用于将传入的网络流量分发到一组后端服务器,以支持必须同时处理来自用户或客户端的多个请求并快速、可靠地返回结果的应用程序。

  • Y轴扩展 :此轴侧重于沿名词或动词边界分离服务和数据,从而实现团队的分段以及代码和数据的所有权划分。–分解模式:将复杂应用程序分解为更易于分析、开发和/或维护的部分的策略。

  • Z轴扩展 :此轴侧重于对相关项进行分组。–分组模式:用于收集或组合相似项的常见解决方案。

最后,遵循赵等人 [33], 的做法,我们将每个模式类别与一个架构元素相关联。为了获得模式语言的架构组件,我们扩展了现有对基本 SOA 组件(接口、业务服务和服务存储库 [24][11])的分析,并将其应用于微服务。该分析产生了三个组件:通信、服务和服务发现,它们是基于微服务的系统架构 [22], 的核心,某种程度上类似于上述 SOA 组件。

3.3 使用模式语言

在实际项目中使用模式语言可以通过遍历模式结构来完成;这些步骤直观易行,可反复应用直至获得所需的系统(见图4)。

步骤(1)对应于可扩展性需求的识别。步骤(2)描述了基于微服务的系统,旨在帮助区分哪些架构模式足以满足可扩展性需求。步骤(3)、(4)和(5)对应于模式族选择过程;每个步骤解决模式语言中的一个特定可扩展性维度。一旦选择了适当的架构模式(步骤(6)),则返回步骤(3),直到判断已满足所需的可扩展性需求为止。满足条件由架构师的决策决定,并结合项目上下文进行判断。

(1) 识别并描述可扩展性需求
(2) 构建高层微服务架构描述
(3) 识别相关的 X 轴模式族
(a) 选择相关的负载均衡模式
(4) 确定相关的 Y‐轴模式族
(a) 选择相关的分解模式
(5) 确定相关的 Z‐轴模式族
(a) 选择相关的分组模式
(6) 返回步骤 (3),直到需要扩展微服务为止
满意

示意图3

4 案例研究:实时车辆定位捕捉

本节描述了所提出的模式语言在记录一家智利公共交通公司实际实时车辆定位采集系统架构设计中的应用。该系统包含三种类型的组件:(1)消息组件:负责分发和整合用于进一步处理的数据包,这些数据来自运行中的车辆。(2)缓存组件:由于需要实时呈现数据,因此有必要设置中间存储以优化对数据源的重复查询,该组件由此投入运行,以增强此过程。(3)数据分析组件:该组件负责处理大量数据,并提供实时信息以支持决策。系统的工作流程如下:

模式 上下文 问题 解决方案
分解单体系统 存在一个具有复杂领域的单体软件系统,该系统至少具备以下属性之一。由于系统的复杂性,源代码的可理解性较低。 如何将系统分解为更小的模块?这些模块应该有多大? 应使用领域驱动设计(DDD)来识别系统所运行的业务的子域。然后,每个子域可以构成一个限界上下文(BC),即一个可部署单元。
更改代码依赖 一个软件系统已分解为一组小型服务,以采用微服务架构风格。 何时适合将此代码级依赖更改为服务级依赖?何时不适合? 尽量使服务代码保持独立。当服务共享代码作为依赖时,存在较高的风险服务开发者因更改共享代码而导致另一个服务的构建过程失败的可能性。
服务发现 一个软件系统已分解为一组小型服务以采用微服务架构风格,并且这些服务中的每一项都在生产环境中部署了一个或多个实例。 服务如何动态地相互定位?边缘服务器或负载均衡器如何知道它可以将跟踪路由到的服务的实例列表吗? 设置一个服务发现,用于存储服务实例的地址。每个服务在启动时注册自身。
内部负载均衡器 一个软件系统已被分解为一组小型服务以使用微服务架构风格,并且已设置服务发现。 如何根据客户端的条件在服务的实例之间进行负载均衡?如何在不设置负载均衡器的情况下对服务进行负载均衡? 每个服务 ,作为客户端,应具有一个内部负载均衡器,用于获取列表从服务发现中获取所需服务的可用实例。
外部负载均衡器 一个软件系统已被分解为一组小型服务以使用微服务架构风格,并且已设置服务发现。 如何根据客户端的条件在服务的实例之间进行负载均衡?如何在不设置负载均衡器的情况下对服务进行负载均衡? 内部负载均衡器消除了设置外部负载均衡器的负担,并带来了可能性在服务的不同客户端中具有直接的负载均衡机制。
部署集群 一个软件系统已基于微服务架构风格构建,并且已建立并运行着一个持续集成流水线。 如何将服务的实例部署到集群中?如何编排部署和重新部署如何以最少的 effort 管理所有服务? 应当存在一个能够管理计算节点集群的系统。该管理系统应能够按需部署服务的容器镜像,并指定实例数量,部署到不同的节点上。
电路断路器 一个软件系统已被分解为一组小型服务,以采用微服务架构风格。 如何在调用最近不可用的服务时快速失败,而不是一直等到服务调用超时? 服务消费者在调用服务提供者时应使用断路器。当服务提供者如果可用,该组件将不执行任何操作。
容器 一个软件系统已被分解为一组小型服务以采用微服务架构样式,且已建立并运行持续集成流水线。 如何使开发和生产对同一段代码产生相同的结果?如何消除配置管理工具的复杂性或手动部署的困难? 断路器检查健康状态或记录失败调用的次数当达到某个阈值时,会触发行程。
数据库每项服务 基于微服务的系统的大多数服务需要将数据持久化到某种数据库中。 微服务应用程序中的数据库架构是什么? 在数据库级别添加新的行为和业务逻辑可能是降低复杂性的一种可行方法。从而降低相关风险,并在速度和可扩展性方面获得提升。

车辆向系统报告其定位,该信息由消息组件接收并处理,然后传递给数据分析组件。根据资源需求,数据可能会经过缓存组件。最终,处理后的数据将在Web平台上显示,并提供给最终用户。

步骤 1。识别并描述可扩展性需求。 该应用需要三个主要的与可扩展性相关的需求:(1)可用性,(2)可靠性,以及(3)性能。由于中央服务器和数据库必须“始终”可用以接收公交车位置数据,且车辆数量可能随时间增长,因此需要高可用性。当车辆数量增长时,仍需保证数据处理的完整性,因此需要可靠性。即使随着时间推移车辆数量和服务数量增加,也必须保持性能。

步骤 2。构建高层微服务架构描述。 实时公交位置采集系统提供对行驶中的公交车的连续定位捕捉。数据被发送到中央服务器并保存在数据库中(见图5)。该系统将根据随时间增加的车辆数量而扩展,基础设施也将进行调整以满足系统所述的与可扩展性相关的要求。

4 案例研究:实时车辆定位捕捉(续)

步骤 3. 识别X轴模式族。 我们确定了一种负载均衡器模式:内部负载均衡器模式。
原理 :该模式允许在中央服务器上采用一种负载均衡方法,旨在以微服务风格捕获和处理来自车辆的数据和信息,适用于在服务器上运行的服务。该模式满足了可用性和性能方面的非功能需求。

步骤 4. 识别Y轴模式族。 我们确定了一种分解模式:断路器模式。
原理 :该模式允许在使用小型服务的微服务架构风格中处理故障,通过设置故障检测的阈值来防止系统发生故障。该模式满足了可用性、可靠性和性能方面的非功能需求。

步骤 5. 识别 Z 轴模式族。 我们确定了一种分组模式:容器模式。
原理 :该模式通过在中央服务器上运行的容器,将软件系统分解为小型服务,并结合断路器模式,满足了可用性、可靠性和性能方面的非功能需求。

遵循本提案中描述的模式语言及其应用步骤,我们创建了一个适当的架构设计,采用微服务架构风格,专注于系统的可扩展性,并通过合适的模式满足其非功能需求。目前,该系统已上线并持续运行,不断采集和处理数据。

5 相关工作

已有一些关于微服务模式语言的前期工作。

理查森在其网站[26]以及随后出版的书籍中提出了一种构建微服务应用的模式语言;其重点是从单体系统构建基于微服务的系统的解决方案,并未涉及可扩展性(或其他质量保证)方面的特定问题。

塔比等人 [29] 对微服务的架构模式进行了系统性映射研究,并获得了一份微服务架构模式目录,但并未针对可扩展性(或任何其他质量保证)进行具体关注。

一些作者从其他角度描述了微服务的可扩展性。维拉米萨尔等人[31]提到,企业需要能够轻松扩展的应用程序,以提高敏捷性、降低复杂性,并更高效地在云中扩展其应用程序;但并未以模式(或模式语言)的形式进行知识归纳。

巴拉莱等人 [4]讨论了基于增量重构的可扩展应用程序,但也缺乏模式形式建议。

最后,博格纳等人 [5] 对面向服务架构模式在微服务架构中的应用进行了比较研究;可扩展性是用于对面向服务架构模式进行分类的维度之一,这有助于识别与可扩展性相关的模式,但并未将其与可扩展性维度关联起来。

所有这些研究都是分别探讨微服务架构模式和可扩展性。尽管它们在两个主题上的贡献都很有价值,但我们并未发现有研究系统地将这两个视角联系起来。

6 结论

本文针对识别架构模式以帮助架构师设计高可扩展性微服务应用的问题,从先前发布的模式列表中选取了与可扩展性相关的模式,并提出了一种围绕三个公认的可扩展性“轴”组织的模式语言:X − axis(“层”)、Y −axis(“组件”)、Z −axis(“分片”)。确定了每个轴对应的模式类别:负载均衡器模式、分解模式和分组模式。最后,将每个模式类别关联到微服务系统的一个特征元素。

所提出的模式语言的使用通过在智利公司的一个案例研究中进行了说明,该案例研究用于记录公交追踪应用的整体设计。

该模式语言的主要优势在于为基于微服务的应用程序的可扩展性决策提供了一个通用的架构词汇。这一方面具有双重作用:作为设计工具(帮助架构师识别相关模式),以及作为文档工具(提供表达设计的方式)。基于特定类型可扩展性的具体设计决策的原理得以清晰表达。

更多推荐