每个微服务都可以独立缩放。 你可以仅横向扩展需要更多处理能力才能满足所需性能级别和服务级别协议的服务,而不是将整个应用程序作为单个单元进行缩放。 精细缩放可使你更好地控制系统,并且有助于降低总体成本,因为是缩放部分系统(而不是所有内容)。
Microsoft .NET 平台是一个很好的选择。 它免费且开放源代码,有许多可简化微服务开发的内置功能。 .NET 是跨平台的。 可以在 Windows、macOS 和大多数 Linux 风格上生成和运行应用程序。
微服务体系结构将系统从进程内迁移到进程外网络通信。 在分布式体系结构中,当服务 B 未响应来自服务 A 的网络调用时,会发生什么情况? 或者,当服务 C 暂时不可用,而调用它的其他服务被阻止时,会发生什么情况?
. 20,000 英尺处的 Dapr。
在图的首行中,请注意 Dapr 如何为常用开发平台提供
特定于语言的 SDK
。 Dapr v1 包括对 .NET、Go、Node.js、Python、PHP、Java 和 JavaScript 的支持。
虽然特定于语言的 SDK 增强了开发人员的体验,但 Dapr 与平台无关。 在后台,Dapr 的编程模型通过标准 HTTP/gRPC 通信协议公开功能。 任何编程平台都可以通过其本机 HTTP 和 gRPC API 调用 Dapr。
图中心的蓝色框表示 Dapr 构建基块。 每个都公开应用程序可以使用的分布式应用程序功能的预生成管道代码。
组件行表示应用程序可以使用的一大组预定义基础结构组件。 可将组件视为不必编写的基础结构代码。
最下面一行突出了 Dapr 的可移植性以及它可以运行的各种环境。
Microsoft 提供了一本免费电子书
面向 .NET 开发人员的 Dapr
,用于学习 Dapr。
展望未来,Dapr 有可能对云原生应用程序开发产生深远影响。
在任何云原生对话中,听到提及术语“容器”是很自然的事情。 在
云原生模式
一书中,作者 Cornelia Davis 观察到“容器是云原生软件的极佳推动者。”云原生计算基金会在其
云原生轨迹图
(企业云原生之旅启程指南)中将微服务容器化作为第一步。
容器化微服务非常简单直接。 代码、其依赖项和运行时会打包到称为
容器映像
的二进制文件中。 映像存储在容器注册表中,该注册表用作映像的存储库或库。 注册表可以位于开发计算机上、数据中心内或公有云中。 Docker 自己通过
Docker 中心
维护公共注册表。 Azure 云采用专用
容器注册表
,用于存储与将运行容器映像的云应用程序接近的容器映像。
当应用程序启动或缩放时,将容器映像转换为正在运行的容器实例。 实例在安装了
容器运行时
引擎的任何计算机上运行。 可以根据需要创建容器化服务的任意多个实例。
图 1-6 显示三个不同的微服务,各自处于自己的容器中,全都在单一主机上运行。
图 1-6. 在一个容器主机上运行多个容器
请注意每个容器如何维护其自己的依赖项集和运行时,它们可以彼此不同。 在这里,我们看到 Product 微服务的不同版本在同一主机上运行。 每个容器都共享底层主机操作系统、内存和处理器的一部分,但彼此隔离。
请注意,容器模型很好地支持了
十二要素应用程序
中的“依赖项”原则。
要素 #2 指定“每个微服务都隔离并打包其自己的依赖项,以在不影响整个系统的情况下进行更改。”
容器同时支持 Linux 和 Windows 工作负载。 Azure 云公开接受这两者。 有趣的是,是 Linux(而不是 Windows Server)成为 Azure 中更常用的操作系统。
虽然存在多个容器供应商,但
Docker
占据了最大的市场份额。 该公司一直在推动软件容器运动。 它已成为打包、部署和运行云原生应用程序的事实上的标准。
为什么要使用容器?
容器提供了可移植性,可保证环境间的一致性。 通过将所有内容封装到单个包中,可将微服务及其依赖项与底层基础结构隔离。
你可以在承载 Docker 运行时引擎的任何环境中部署容器。 容器化工作负载还消除了通过框架、软件库和运行时引擎预配置每个环境的支出。
通过共享底层操作系统和主机资源,容器的占用比完整虚拟机小得多。 较小的大小增加了给定主机一次可以运行的密度或微服务数。
容器业务流程
虽然 Docker 等工具会创建映像并运行容器,但你还需要工具来管理它们。 容器管理使用称为“容器业务流程协调程序”的特殊软件程序来完成。 当大规模操作许多正在运行的独立容器时,业务流程至关重要。
图 1-7 显示容器业务流程协调程序自动执行的管理任务。
图 1-7. 容器业务流程协调程序执行的任务
下表介绍了常见的业务流程任务。
请注意容器业务流程协调程序如何支持
十二要素应用程序
中的“可处置性”和“并发”原则。
要素 #9 指定“服务实例应是可处置的,支持快速启动以增加可伸缩性机会,以及支持正常关闭以使系统保持正确状态。”Docker 容器以及业务流程协调程序本质上满足此要求。
要素 #8 指定“服务跨大量小型相同进程(副本)横向扩展,而不是在功能最强大的可用计算机上纵向扩展单个大型实例。”
尽管存在多个容器业务流程协调程序,但
Kubernetes
已成为云原生世界事实上的标准。 它是一种可移植、可扩展的开放源代码平台,可用于管理容器化工作负载。
你可以承载自己的 Kubernetes 实例,但随后需要负责预配和管理其资源,这可能十分复杂。 Azure 云功能采用 Kubernetes 作为一种托管服务。
Azure Kubernetes 服务 (AKS)
和
Azure Red Hat OpenShift (ARO)
都使你能够以托管服务的形式充分利用 Kubernetes 的特性和强大功能,而无需安装和维护它。
缩放云原生应用程序
中详细介绍了容器业务流程。
云原生系统依赖于许多不同的辅助资源,如数据存储、消息中转站、监视和标识服务。 这些服务称为
支持服务
。
图 1-8 显示云原生系统使用的许多常见支持服务。
图 1-8. 常见支持服务
你可以承载自己的支持服务,但随后你需要负责对这些资源进行许可、预配和管理。
云提供商提供丰富的 托管支持服务。只需使用服务,而无需拥有服务。 云提供商大规模地运营资源,并负责性能、安全性和维护。 监视、冗余性和可用性内置在服务中。 提供商保证服务级别性能并完全支持其托管服务 - 开启票证,他们会解决问题。
云原生系统支持云供应商提供的托管支持服务。 在时间和劳动力方面的节省可能会十分巨大。 承载自己的服务和遇到问题的运营风险会迅速变得十分昂贵。
最佳做法是将支持服务视为附加资源,动态绑定到将配置信息(URL 和凭据)存储在外部配置中的微服务。 本章前面讨论的
十二要素应用程序
中详细说明了此指导。
要素 #4 指定支持服务“应通过可寻址 URL 进行公开。 这样做可使资源与应用程序分离,使其可以互换。”
要素 #3 指定“配置信息通过代码之外的配置管理工具移出微服务和实现外部化。”
借助此模式,支持服务可以进行附加和拆离,而无需更改代码。 可以将微服务从 QA 提升到暂存环境。 将微服务配置更新为指向暂存中的支持服务,并通过环境变量将设置注入到容器中。
云供应商提供了 API,使你能够与其专有支持服务进行通信。 这些库封装了专有管道和复杂性。 但是,直接与这些 API 进行通信会将你的代码紧密耦合到该特定支持服务。 隔离供应商 API 的实现细节是一种被广泛接受的做法。 引入中间层或中间 API,将泛型操作公开给你的服务代码并将供应商代码包装在其中。 这种松散耦合使你可以将一个支持服务交换为另一个,或是将代码移到不同的云环境,而无需更改主线服务代码。 前面讨论的 Dapr 通过
预生成构建基块
集来遵循此模型。
最后一点,支持服务还促进本章前面所讨论的
十二要素应用程序
中的“无状态”原则。
要素 #6 指定“每个微服务应在其自己的进程中执行,与其他正在运行的服务隔离。 将所需状态外部化到支持服务,如分布式缓存或数据存储。”
云原生数据模式
和
云原生通信模式
中讨论了支持服务。
如你所见,云原生系统采用微服务、容器和新式系统设计来实现一定的速度和敏捷性。 但这只是其中的一部分。 如何预配这些系统所运行的云环境? 如何快速部署应用功能和更新? 如何完成整张图片?
进入广泛接受的
基础结构即代码
(IaC) 做法。
借助 IaC,你可以自动执行平台预配和应用程序部署。 实质上你是将软件工程做法(例如测试和版本控制)应用到 DevOps 做法。 基础结构和部署是自动执行的,具有一致性和可重复性。
自动完成基础结构
使用
Azure 资源管理器
、
Azure Bicep
、HashiCorp 提供的
Terraform
和
Azure CLI
等工具,你能够以声明方式对所需的云基础结构编写脚本。 资源名称、位置、容量和机密都是参数化和动态的。 脚本会进行版本控制,并作为项目的生成工件签入到源代码管理中。 你调用脚本以在系统环境(如 QA、暂存和生产)间预配一致且可重复的基础结构。
在底层,IaC 是幂等的,这意味着可以反复运行相同脚本,而不会产生副作用。 如果团队需要进行更改,则会编辑并重新运行脚本。 只有更新的资源才会受到影响。
在
什么是基础结构即代码
一文中,作者 Sam Guckenheimer 介绍了“实现 IaC 的团队能够快速、大规模地提供稳定的环境。 他们避免了手动配置环境,并通过代码来表示环境所需的状态,从而强制执行一致性。 采用 IaC 的基础结构部署是可重复的,可以防止因配置偏移或缺少依赖项而导致的运行时问题。 DevOps 团队可以结合使用一系列统一的做法和工具,迅速、大规模、可靠地提供应用程序及其支持的基础结构。”
自动执行部署
前面所讨论的
十二要素应用程序
会在将完成的代码转换为正在运行的应用程序时调用单独的步骤。
要素 #5 指定“每个版本都必须在生成、发布和运行阶段执行严格的分离。 各自都应使用唯一 ID 进行标记,并支持回滚功能。”
新式 CI/CD 系统有助于实现此原则。 它们提供单独的生成和交付步骤,可帮助确保提供一致且高质量的代码供用户随时使用。
图 1-9 显示整个部署过程中的分离。
图 1-9. CI/CD 管道中的部署步骤
在上图中,请特别注意任务的分离: