微服务架构的十个设计形式区分是独享数据库、事情驱动、CQRS、Saga、BFF、API 网关、Strangler、断路器、外部化性能、消费端驱动的契约测试。
从软件开发早期(1960 年代)开局,应答大型软件系统中的复杂性不时是一项令人生畏的义务。多年来为了应答软件系统的复杂性,软件工程师和架构师们做了许多尝试:David Parnas 的模块化和封装 (1972), Edsger W. Dijkstra (1974)的关注点分别以及 SOA(1988)。
他们都是经常使用分而治之这项成熟的传统技术来应答大型系统的复杂性。自 2010 年开局,这些技术被证明无法继续应答 Web 级运行或许现代大型企业级运行的复杂性。因此架构师和工程师们开展出了一种全新的现代方式来处置这个疑问,就是微服务架构。它虽然间断了分而治之的思想,但却是以全新的方式来成功的。
软件设计形式是处置软件设计中经常出现疑问的通用、可复用的处置打算。设计形式让咱们可以分享通用词汇并经常使用经实战测验的打算,免得重复造轮子。我先便捷引见下微服务架构。
经过浏览这篇文章,你会学到:
最关键的微服务架构设计形式,包括其优缺陷、用例、高低文、技术栈示例及可用资源。
请留意,本清单中的大部分设计形式常出如今多种语境中,并且可以在非微服务架构中经常使用。而我将在微服务这个特定语境中引见它们。
1. 微服务架构
我在之前的博客《微服务架构概述及为什么要运行在下个名目》和《单体软件架构真的终结了吗?》中对微服务架构有十分详尽的引见。假设你感兴味,可以浏览这两篇博客来深化了解。
那究竟什么是微服务架构?有很多种定义方法。我的定义是这这样的:
微服务架构指的是将大型复杂系统按性能或许业务需求垂直切分红更小的子系统,这些子系统以独立部署的子进程存在,它们之间经过轻量级的、跨言语的同步(比如 REST,gRPC)或许异步(信息)网络调用启动通讯。
上方是基于微服务架构的商业 Web 运行的组件视图:
来自 Md Kamaruzzaman 的微服务架构
微服务架构的关键特色
微服务架构的好处
微服务架构的缺陷
何时经常使用微服务架构
2. 微服务架构的设计形式
独享数据库(Database per Microservice)
当一家公司将大型单体系统交流成一组微服务,首先要面临的最关键决策是关于数据库。单体架构会经常使用大型中央数据库。即使转移到微服务架构许多架构师仍偏差于坚持数据库不变。虽然有一些短期收益,但它却是反形式的,特意是在大规模系统中,微服务将在数据库层重大耦合,整个迁徙到微服务的指标都将面临失败(例如,团队授权、独立开发等疑问)。
更好的方法是为每个微服务提供自己的数据存储,这样服务之间在数据库层就不存在强耦合。这里我经常使用数据库这一术语来示意逻辑上的数据隔离,也就是说微服务可以共享物理数据库,但应该经常使用分开的数据结构、汇合或许表,这还将有助于确保微服务是依照畛域驱动设计的方法正确拆分的。
Md Kamaruzzaman 的微服务独享数据库
好处
缺陷
何时经常使用独享数据库
何时不宜经常使用独享数据库
可用技术示例
一切 SQL、 NoSQL 数据库都提供数据的逻辑分别(例如,独自的表、汇合、结构、数据库)。
事情源(Event Sourcing)
在微服务架构中,特意经常使用独享数据库时,微服务之间须要启动数据交流。关于弹性高可伸缩的和可容错的系统,它们应该经过交流事情启动异步通讯。在这种状况,您或许宿愿启动相似更新数据库并发送信息这样的原子操作,假设在大数据量的散布式场景经常使用相关数据库,您将无法经常使用两阶段锁协定(2PL),由于它无法伸缩。而 NoSQL 数据库由于大多不支持两阶段锁协定甚至无法成功散布式事务。
在这些场景,可以基于事情的架构经常使用事情源形式。在传统数据库中,间接存储的是业务虚体的“形态”,而在事情源中任何“形态”更新事情或其余关键事情都会被存储起来,而不是间接存储实体自身。这象征着业务虚体的一切更改将被保留为一系列无法变的事情。由于数据是作为一系列事情存储的,而非间接更新存储,所以各项服务可以经过重放事情存储中的事情来计算出所需的数据形态。
Md Kamaruzzaman 的事情源
好处
缺陷
何时经常使用事情源
何时不宜经常使用事情源
可用技术示例
事情存储:EventStoreDB、Apache Kafka、Confluent Cloud、AWS Kinesis、Azure Event Hub、GCP Pub/Sub、Azure Cosmos DB、MongoDB、Cassandra、Amazon DynamoDB
框架:Lagom、Akka、Spring、akkatecture、Axon、Eventuate
命令和查问职责分别(CQRS)
假设咱们经常使用事情源,那么从事情存储中读取数据就变得艰巨了。要从数据存储中失掉实体,咱们须要处置一切的实体事情。有时咱们对读写操作还会有不同的分歧性和吞吐量要求。
这种状况,咱们可以经常使用 CQRS 形式。在该形式中,系统的数据修正部分(命令)与数据读取部分(查问)是分别的。而 CQRS 形式有两种容易令人混杂的形式,区分是便捷的和初级的。
在其简单方式中,不同实体或 ORM 模型被用于读写操作,如下所示:
Md Kamaruzzaman 的 CQRS(便捷)
它有助于强化繁多职责准则和分别关注点,从而成功更繁复的设计。
在其初级方式中,会有不同的数据存储用于读写操作。初级的 CQRS 通常联合事情源形式。依据不同状况,会经常使用不同类型的写数据存储和读数据存储。写数据存储是“记载的系统”,也就是整个系统的**源头。
MdKamaruzzaman 的 CQRS(初级)
关于读频繁的运行程序或微服务架构,OLTP 数据库(任何提供 ACID 事务保障的相关或非相关数据库)或散布式信息系统都可以被用作写存储。关于写频繁的运行程序(写操作高可伸缩性和大吞吐量),须要经常使用写可水平伸缩的数据库(如世界托管的公共云数据库)。规范化的数据则保留在写数据存储中。
对搜查(例如 Apache Solr、Elasticsearch)或读操作(KV 数据库、文档数据库)启动优化的非相关数据库常被用作读存储。许多状况会在须要 SQL 查问的中央经常使用读可伸缩的相关数据库。非规范化和不凡优化过的数据则保留在读存储中。
数据是从写存储异步复制到读存储中的,所以读存储和写存储之间会有提前,但最终是分歧的。
好处
缺陷
何时经常使用 CQRS
何时不宜经常使用 CQRS
可用技术示例
写存储:EventStoreDB, Apache Kafka, Confluent Cloud, AWS Kinesis, Azure Event Hub, GCP Pub/Sub, Azure Cosmos DB, MongoDB, Cassandra. Amazon DynamoDB
读存储:Elastic Search, Solr, Cloud Spanner, Amazon Aurora, Azure Cosmos DB, Neo4j
框架:Lagom, Akka, Spring, akkatecture, Axon, Eventuate
假设微服务经常使用独享数据库,那么经过散布式事务治理分歧性是一个渺小的应战。你无法经常使用传统的两阶段提交协定,由于它要么无法伸缩(相关数据库),要么不被支持(少数非相关数据库)。
但您还是可以在微服务架构中经常使用 Saga 形式成功散布式事务。Saga 是 1987 年开发的一种新鲜形式,是相关数据库中关于小事务的一个代替概念。但这种形式的一种现代变种对散布式事务也十分有效。Saga 形式是一个本地事务序列,其每个事务在一个独自的微服务内更新数据存储并颁布一个事情或信息。Saga 中的首个事务是由外部恳求(事情或举措)初始化的,一旦本地事务成功(数据已保留在数据存储且信息或事情已颁布),那么颁布的信息或事情则会触发 Saga 中的下一个本地事务。
Md Kamaruzzaman 的 Saga
假设本地事务失败,Saga 将口头一系列补救事务来回滚前面本地事务的更改。
Saga 事务协调治理关键有两种方式:
好处
缺陷
何时经常使用 Saga
何时不宜经常使用 Saga
可用技术示例
Axon, Eventuate, Narayana
面向前端的后端 (BFF)
在现代商业运行开发,特意是微服务架构中,前后端运行是分别和独立的服务,它们经过 API 或 GraphQL 衔接。假设运行程序还有移动 App 客户端,那么 Web 端和移动客户端经常使用相反的后端微服务就会出现疑问。由于移动客户端和 Web 客户端有不同的屏幕尺寸、显示屏、性能、能耗和网络带宽,它们的 API 需求不同。
面向前端的后端形式实用于须要为不凡 UI 定制独自后端的场景。它还提供了其余好处,比如作为下游微服务的封装,从而缩小 UI 和下游微服务之间的频繁通讯。此外,在高安保要求的场景中,BFF 为部署在 DMZ 网络中的下游微服务提供了更高的安保性。
MdKamaruzzaman 的面向前端的后端
好处
缺陷
何时经常使用 BFF
何时不宜经常使用 BFF
可用技术示例
任何后端框架(Node.js,Spring,Django,Laravel,Flask,Play,…)都能支持。
API 网关
在微服务架构中,UI 通常衔接多个微服务。假设微服务是细粒度的(FaaS) ,那么客户端或许须要衔接十分多的微服务,这将变得冗杂和具备应战性。此外,这些服务包括它们的 API 还将不时退化。大型企业还宿愿能有其余横切关注点(SSL 中断、身份验证、授权、节流、日志记载等)。
一个处置这些疑问的可行方法是经常使用 API 网关。API 网关位于客户端 APP 和后端微服务之间充任facade,它可以是反向代理,将客户端恳求路由到适当的后端微服务。它还支持将客户端恳求扇出到多个微服务,而后将照应聚合后前往给客户端。它还支持必要的横切关注点。
Md Kamaruzzaman 的 API 网关
好处
缺陷
何时经常使用 API 网关
何时不宜经常使用 API 网关
可用技术示例
Amazon API 网关, Azure API 治理, Apigee, Kong, WSO2 API 治理器
假构想在运转中的名目中经常使用微服务架构,咱们须要将遗留的或现有的单体运行迁徙到微服务。将现有的大型在线单体运行程序迁徙到微服务是相当有应战性的,由于这或许破坏运行程序的可用性。
一个处置打算是经常使用 Strangler 形式。Strangler 形式象征着经过经常使用新的微服务逐渐交流特定性能,将单体运行程序增量地迁徙到微服务架构。此外,新性能只在微服务中参与,而不再参与到遗留的单体运行中。而后性能一个 Facade (API 网关)去路由遗留单体运行和微服务间的恳求。当某特性能从单体运行迁徙到微服务,Facade 就会阻拦客户端恳求并路由到新的微服务。一旦迁徙了一切的性能,遗留单体运行程序就会被“扼杀(Strangler)”,即退役。
Md Kamaruzzaman 的 Strangler
好处
缺陷
何时经常使用 Strangler
可用技术示例
API 网关后端运行框架。
断路器
在微服务架构中,微服务经过同步伐用其余服务来满足业务需求。服务调用会由于刹时缺点(网络衔接缓慢、超时或临时无法用) 造成失败,这种状况重试可以处置疑问。但是,假设出现了重大疑问(微服务齐全失败),那么微服务将常年间无法用,这时重试没无心义且糜费贵重的资源(线程被阻塞,CPU 周期被糜费)。此外,一个服务的缺点还会引发整个运行系统的级联缺点。这时极速失败是一种更好的方法。
在这种状况,可以经常使用断路器形式援救。一个微服务经过代理恳求另一个微服务,其上班原理相似于电气断路器,代理经过统计最近出现的缺点数量,并经常使用它来选择是继续恳求还是便捷的间接前往异常。
Md Kamaruzzaman 的断路器
断路器可以有以下三种形态:
好处
缺陷
何时经常使用断路器
何时不宜经常使用断路器
可用技术示例
API 网关,服务网格,各种断路器库(Hystrix, Reselience4J, Polly)。
外部化性能
每个业务运行都有许多用于各种基础设备的性能参数(例如,数据库、网络、衔接的服务地址、凭据、证书门路)。此内在企业运行程序通常部署在各种运转环境(Local、 Dev、 Prod)中,成功这些的一个方法是经过外部性能。这是一个致命蹩脚通常,它会造成重大的安保危险,由于消费凭证很容易受到破坏。此外,性能参数的任何更改都须要从新构建运行程序,这在在微服务架构中会愈加严格,由于咱们或许领有数百个服务。
更好的方法是将一切性能外部化,使得构建环节与运转环境分别,消费的性能文件只在运转时或经过环境变量经常使用,从而最小化了安保危险。
好处
缺陷
何时经常使用外部化性能
何时不宜经常使用外部化性能
可用技术示例
简直一切企业级的现代框架都支持外部化性能。
消费端驱动的契约测试
在微服务架构中,通常有许多有不同团队开发的微服务。这些微型服务协同上班来满足业务需求(例如,客户恳求),并相互启动同步或异步通讯。消费端微服务的集成测试具备应战性,通罕用 TestDouble 以取得更快、更低老本的测试运转。但是 TestDouble 通常并不能代表真正的微服务提供者,而且假设微服务提供者更改了它的 API 或 信息,那么 TestDouble 将无法确认这些。另一种选用是启动端到端测试,虽然它在消费之前是强迫性的,但却是软弱的、缓慢的、低廉的且不能代替集成测试(Test Pyramid)。
在这方面消费端驱动的契约测试可以协助咱们。在这里,担任消费端微服务的团队针对特定的服务端微服务,编写一套蕴含了其恳求和预期照应(同步)或信息(异步)的测试套件,这些测试套件称为显式的商定。关于微服务服务端,将其消费端一切商定的测试套件都参与到其智能化测试中。当特定服务端微服务的智能化测试口头时,它将一同运转自己的测试和商定的测试并启动验证。经过这种方式,契约测试可以智能的协助保养微服务通讯的完整性。
好处
缺陷
何时经常使用需求驱动的契约测试
何时不宜经常使用消费端驱动的契约测试
可用技术示例
Pact, Postman, Spring Cloud Contract
3. 总结
在现代大规模企业软件开发中,微服务架构能够协助开发裁减规模并带来很多常年收益。但是微服务架构并不是随处可用的银弹,假设运行在失误的运行程序类型,微服务架构将弊大于利。宿愿驳回微服务架构的开发团队应该遵照最佳通常,并经常使用一系列可重用的、久经锻炼的设计形式。
微服务架构中至关关键的设计形式是独享数据库。成功这种设计形式具备应战性,须要其余几种亲密相关的设计形式(事情驱动、 CQRS、 Saga)来支持。在具备多个客户端(Web、 Mobile、 Desktop、 Smart Devices)的典型业务运行程序中,客户端和微服务之间的通讯量或许是很大的,并且须要一致的安保控制,在这种状况面向前端的后端和 API 网关的设计十分有用。此外,断路器形式可以大大地协助应答这类运行程序的失误处置场景。迁徙遗留的单体运行到微服务是极具应战性的,而 Strangler 形式可以协助做到这点。消费端驱动的契约测试是微服务集成测试的基础形式。另外外部化性能是任何现代化运行程序开发中的一种必备形式。
这个系列并不片面,在实践状况中您或许须要其余的设计形式,但这个系列能为您提供一个关于微服务架构设计形式的极好引见。