概述

微服务是一种将软件应用程序开发为独立设置的小模块的方法,其中每个服务运行独特的进程。它通过定义明确的机制进行通信以达到目的。

2011 年 5 月,威尼斯附近的软件工程师使用“微服务”这个术语来表达他们中许多人正在探索的通用编程风格。James Lewis 在 2012 年 3 月的案例研究中提出了一些想法,并将其命名为“微服务”。

微服务是许多行业想要采用的一种。Netflix、亚马逊等公司在其产品中采用了微服务的概念。

在本文中,我们将学习如何使用设计模式、原则和最佳实践来设计微服务架构。我们将使用正确的架构设计模式和技术。

通过本文您将了解如何在微服务分布式架构上设计系统以实现高可用性、高可扩展性、低延迟和网络故障恢复能力,从而处理数百万个请求。

In this article, we’re going to learn how to Design Microservices Architecture with using Design Patterns, Principles and the Best Practices. We will using the right architecture design patterns and techniques.

By the end of the article, you will Learn how to handle millions of request with designing system for high availability, high scalability, low latency, and resilience to network failures on microservices distributed architectures.

本文带领您进行一段软件架构设计的旅程,逐步将架构单体发展为事件驱动的微服务.我们将从设计处理少量请求的电子商务整体架构开始软件架构的基础知识。

之后逐步演变成可处理数百万个请求的架构

  • 分层架构

  • SOA

  • 微服务

  • 最后是事件驱动的微服务架构

After that step by step evolves the architecture with

  • Layered Architecture

  • SOA

  • Microservices

  • and lastly Event Driven Microservices Architectures

with designing together that handle millions of requests.

在本文中,我们将学习如何使用设计模式、原则最佳实践来设计微服务架构。我们将从设计单体事件驱动的微服务开始,并一起使用正确的架构设计模式和技术。

In this course, we’re going to learn how to Design Microservices Architecture with using Design Patterns, Principles and the Best Practices. We will start with designing Monolithic to Event-Driven Microservices step by step and together using the right architecture design patterns and techniques.

设计模式、原则

在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns – Elements of Reusable Object-Oriented Software(中文译名:设计模式 – 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。

四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。

  • 对接口编程而不是对实现编程。

  • 优先使用对象组合而不是继承。

设计模式的使用

设计模式在软件开发中的两个主要用途。

开发人员的共同平台

设计模式提供了一个标准的术语系统,且具体到特定的情景。例如,单例设计模式意味着使用单个对象,这样所有熟悉单例设计模式的开发人员都能使用单个对象,并且可以通过这种方式告诉对方,程序使用的是单例模式。

最佳的实践

设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。

设计模式的类型

根据设计模式的参考书 Design Patterns – Elements of Reusable Object-Oriented Software(中文译名:设计模式 – 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。当然,我们还会讨论另一类设计模式:J2EE 设计模式。

序号模式 & 描述包括
1创建型模式
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
  • 工厂模式(Factory Pattern)

  • 抽象工厂模式(Abstract Factory Pattern)

  • 单例模式(Singleton Pattern)

  • 建造者模式(Builder Pattern)

  • 原型模式(Prototype Pattern)

2结构型模式
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。
  • 适配器模式(Adapter Pattern)

  • 桥接模式(Bridge Pattern)

  • 过滤器模式(Filter、Criteria Pattern)

  • 组合模式(Composite Pattern)

  • 装饰器模式(Decorator Pattern)

  • 外观模式(Facade Pattern)

  • 享元模式(Flyweight Pattern)

  • 代理模式(Proxy Pattern)

3行为型模式
这些设计模式特别关注对象之间的通信。
  • 责任链模式(Chain of Responsibility Pattern)

  • 命令模式(Command Pattern)

  • 解释器模式(Interpreter Pattern)

  • 迭代器模式(Iterator Pattern)

  • 中介者模式(Mediator Pattern)

  • 备忘录模式(Memento Pattern)

  • 观察者模式(Observer Pattern)

  • 状态模式(State Pattern)

  • 空对象模式(Null Object Pattern)

  • 策略模式(Strategy Pattern)

  • 模板模式(Template Pattern)

  • 访问者模式(Visitor Pattern)

4J2EE 模式
这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。
  • MVC 模式(MVC Pattern)

  • 业务代表模式(Business Delegate Pattern)

  • 组合实体模式(Composite Entity Pattern)

  • 数据访问对象模式(Data Access Object Pattern)

  • 前端控制器模式(Front Controller Pattern)

  • 拦截过滤器模式(Intercepting Filter Pattern)

  • 服务定位器模式(Service Locator Pattern)

  • 传输对象模式(Transfer Object Pattern)

下面用一个图片来整体描述一下设计模式之间的关系:

设计模式的六大原则

1、开闭原则(Open Close Principle)

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则是面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3、依赖倒转原则(Dependence Inversion Principle)

这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

5、迪米特法则,又称最少知道原则(Demeter Principle)

最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

分层架构

最简单和最常见的架构风格之一是分层架构。代码按技术领域划分为离散层。这清楚地表明了代码所属的位置。

                                将代码库典型地分解为层

一个典型的规则是每一层都是封闭的,这意味着它只能被它旁边的层访问,这有助于防止耦合。每一层都可以作为一个整体部署在一起,也可以单独部署。通常,表示层(UI)和数据库将分别部署到代码的其余部分。

现代软件架构风格

每个软件项目都是不同的,但这并不意味着我们没有可以挑选的趋势。除了经典的分层架构之外,还有一另外些代表软件架构模式.

大泥球(Big Ball of Mud)

当您不选择架构时,您最终会得到 “Big Ball of Mud” 架构。泥泞的“大球”是指从一个没有计划如何构建他们的解决方案的团队中出现的非结构化的意大利面条式代码库。

Big Ball of Mud 的名字来源于无组织的耦合和调用模式的网络,这些模式代表了没有清晰架构的项目.

管道架构

流水线架构以两种类型的单元为中心;管道和过滤器:

过滤器是独立的无状态计算单元。他们应该专注于完成一项特定任务。过滤器可以生成、测试、转换或使用数据。

管道是过滤器之间的通信通道。它们是一种方式,用于从过滤器构建管道。

微内核架构(插件架构)

微内核架构基于构建核心系统的想法,该系统包含系统完成其核心目的所需的最少功能。然后通过独立插件提供附加功能。想想 VS Code:基本应用程序非常有限,但通过添加插件,您可以使应用程序非常强大,并为您和您的项目量身定制。

通常,插件彼此隔离,因此彼此分离。他们也有独立的存储。插件可以是具有核心系统的单体的一部分,也可以单独部署。如果与插件的通信是通过某种标准化形式的消息(如 REST)完成的,则无需要求所有内容都使用相同的语言编写。

基于服务的架构

在此体系结构中,功能由基于域的服务划分。该服务可以共享数据库和用户界面,但彼此独立运行。

服务可以相互独立部署。可以为需求较高的服务提供更多资源或进行复制。还可能有一个 API 代理将请求从 UI 路由到正确的服务。

事件驱动架构

事件驱动系统对用户界面或内部发生的事件做出“反应”。这种系统是由事件处理器构建的;小的独立计算单元。通过系统的事件流可以以两种不同的方式发生。

在代理拓扑下,没有对事件处理的集中控制。每个处理器都可以广播自己的事件以触发另一个处理器形成事件链。不需要管理特定事件处理器或执行步骤之间的连接。

在中介拓扑下有一些中央控制。事件调解器控制调用哪些处理器以及事件进入系统时的顺序。可能有多个事件中介以并行或分层方式工作。

微服务架构

微服务系统由许多可独立部署的、以领域为中心的服务构建而成。“微”来自于每个服务应该只专注于完成一项任务的事实。微服务通常使用 REST 之类的东西(可能通过 API 网关)进行通信,用不同的语言编写并具有独立的存储。

微服务通常是独立部署的。这是一个“云原生”架构,它使用弹性来提供性能和可用性。

Clean Architecture

  • 域层:实体+用例+网关协议

  • 数据层:网关实现+ API(网络)+数据库

  • 表示层:视图模型+视图+导航器+场景用例

实体

实体封装了企业范围内的关键业务规则。实体可以是带有方法的对象,也可以是一组数据结构和函数。只要实体可以被企业中的许多不同应用程序使用,都没有关系。-清洁架构:软件结构和设计手工艺指南(Robert C. Martin)

非功能性系统设计

可扩展性和可靠性是衡量您的应用程序对最终用户的服务程度的衡量标准。如果我们的电子商务应用程序可以在没有明显停机的情况下为数百万用户提供服务,那么我们可以说该系统具有高度可扩展性和可靠性。可扩展性可用性可能是设计良好架构的主要因素。

Scalability and reliability are measures of how well your application can be served to end-users. If our e-commerce application can serve millions of users without noticeable downtime, then we can say the system is highly scalable and reliable. Scalability and availability are probably the major factors for designing good architecture.

可扩展性 = 电子商务应用程序应该能够为数百万用户提供服务

可用性 = 电子商务应用程序应该 24/7 全天候可用
可维护性 = 电子商务应用程序应该开发数年
效率 = 电子商务应用程序应该响应可接受的延迟,例如 RT < 2 秒.

Scalability = e-commerce application should able to serve millions of users

Availability = e-commerce application should available 24/7
Maintainability = e-commerce application should develop several years
Efficiency = e-commerce application should response acceptable latency like < 2 sec — short response latency

单体架构

经过数十年的软件开发,有许多方法和模式演变而来,它们都有自己的好处和挑战。因此,我们将从了解构建电子商务应用程序的现有方法开始,然后发展并转移到云。

为了理解云原生微服务,我们需要了解什么是单体应用程序,以及我们是如何从单体转向微服务的。

如果项目的所有功能都存在于单个代码库中,
则该应用程序称为单体应用程序。在单体模式中,用户界面、业务代码和数据库调用等所有内容都包含在同一个代码库中。

所有应用程序关注点都包含在一个大型部署中。
即使是单体应用程序也可以在不同的层(如表示层、业务层和数据层)中进行设计,然后将该代码库部署为单个 jar/war 文件。

单体方法有几个优点,我们将在接下来的视频中讨论它们。但让我在这里说一些主要的优点和缺点。

由于它是单个代码库,因此很容易拉取并开始项目。
由于项目结构在 1 个项目中,并且易于调试跨不同模块的业务交互。不幸的是,单体架构有很多缺点,我们可以这么说;

  • 随着时间的推移,它的代码量变得太大,这就是它很难管理的原因。

  • 难以在同一代码库中并行工作。

  • 难以在遗留的大型单体应用程序上实现新功能

  • 任何更改都需要部署整个应用程序的新版本。

等等.

Unfortunately, the monolith architecture has lots of disadvantages, we can say that;

  • It becomes too large in code size with time thats why its really difficult to manage.

  • Difficult to work in parallel in the same code base.

  • Hard to implement new features on legacy big monolithic applications

  • Any change, requires deploying a new version of the entire application.

and so on..

As you can see that we understand Monolithic Architecture.

何时使用单体架构

即使是单体架构也有很多缺点,如果您正在构建小型应用程序,那么单体架构仍然是您可以应用于项目的最佳架构之一。因为,在许多方面,单体应用程序都很简单。

它们很简单:
构建
测试
部署
故障排除
垂直扩展(放大)

非常简单快捷。

相对于需要熟练的开发人员来识别和开发服务的微服务,开发起来很简单。由于只部署了一个 jar/war 文件,因此更易于部署。

They’re straightforward to:
Build
Test
Deploy
Troubleshoot
Scale vertically (scale up)

is very easy and fast.

It is simple to develop relative to microservices where skilled developers are required in order to identify and develop the services. It is Easier to deploy as only a single jar/war file is deployed.

设计单体架构

在本节中,我们将逐步设计具有单体架构的电子商务应用程序。
我们将根据需求一一迭代架构设计。

我们应该始终从写下 FR(功能要求)和 NFR(非功能要求)开始。

功能要求

  • 列出产品

  • 按品牌和类别过滤产品

  • 将产品放入购物车

  • 申请折扣券并查看购物车中所有商品的总费用

  • 结帐购物车并创建订单

  • 列出我的旧订单和订单商品历史

非功能性要求

  • 可扩展性

  • 增加并发用户

此外,最好在我们的图片中添加原则以便始终记住它们。

原则

  • KISS

  • YAGNI

我们将在设计架构时考虑这些原则。

Functional Requirements

  • List products

  • Filter products as per brand and categories

  • Put products into the shopping cart

  • Apply coupon for discounts and see the total cost all for all of the items in shopping cart

  • Checkout the shopping cart and create an order

  • List my old orders and order items history

Non-Functional Requirements

  • Scalability

  • Increase Concurrent User

Also, its good to add principles in our picture in order to remember them always.

Principles

  • KISS

  • YAGNI

We are going to consider these principles when design our architecture.

微服务架构

来自 Martin Fowlers 微服务文章:

微服务架构风格是一种将单个应用程序开发为一组小型服务的方法,每个服务都在自己的进程中运行并与轻量级机制(通常是 HTTP 或 gRPC API)进行通信。

From Martin Fowlers Microservices article;

The microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP or gRPC API.

(https://martinfowler.com/articles/microservices.html)

所以我们可以说,微服务架构是一种云原生架构方法,其中应用程序由许多松散耦合且可独立部署的较小组件组成。

微服务是可以协同工作并且可以自主/独立部署的小型企业服务。

上图为微服务架构风格。
除了微服务本身之外,微服务架构中还有各种组件。
我们从使用身份提供程序与服务器交互的客户端开始,身份提供程序管理身份信息并在分布式网络中提供身份验证服务。为了确保这种交互,我们需要一个客户端的入口点,即API Gateway。它是来自客户端的单点联系,反过来,它会返回来自底层微服务的响应,有时还会返回来自多个微服务的聚合响应。在我们的架构中,我们有四个服务使用管理来维护服务的节点。为了跟踪服务、服务地址和端点,我们使用服务发现。
我们有CDN,它是为静态资源提供服务的内容交付网络。例如,分布式网络中的页面和网页内容,静态内容是像页面和网页内容一样的静态资源。

API 网关位于客户端和服务之间。它充当反向代理,将客户端请求路由到服务。它还可以执行各种跨功能任务,例如身份验证、SSL 终止和速率限制。如果不部署网关,客户端必须直接向前端服务发送请求。

这在客户端和服务器之间创建了耦合。客户必须知道每项服务是如何分解的。这些使客户维护和重构服务变得更加困难。

微服务
——拥有自己的技术栈,包括数据库和数据管理模型;
— 通过 REST API、事件流和消息代理的组合相互通信;
— 按业务能力组织,分隔服务的线通常称为有界上下文。

Microservices

— have their own technology stack, included the database and data management model;
— communicate to each other over a combination of REST APIs, event streaming, and message brokers;
— are organized by business capability, with the line separating services often referred to as a bounded context.
we will also see how we can decouple microservices with bounded context in the upcoming sections.

在接下来的部分中,我们还将了解如何将微服务与有界上下文解耦。

微服务特征

微服务是小型、独立且松散耦合的。一个小型开发团队可以编写和维护服务。每个服务都是一个单独的代码库,可以由一个小型开发团队管理。

服务可以独立部署。团队无需重新构建和重新部署整个应用程序即可更新现有服务。

服务负责保存自己的数据或外部状态。这与传统模型不同,在传统模型中,单独的数据层处理数据持久性。

Microservices are small, independent, and loosely coupled. A single small team of developers can write and maintain a service. Each service is a separate codebase, which can be managed by a small development team.

Services can be deployed independently. A team can update an existing service without rebuilding and redeploying the entire application.

Services are responsible for persisting their own data or external state. This differs from the traditional model, where a separate data layer handles data persistence.

微服务架构的好处

敏捷。
微服务最重要的特征之一是因为服务更小且可独立部署。

小而专注的团队。
微服务应该足够小,以至于单个功能团队可以构建、测试和部署它。

可扩展性。
微服务可以独立扩展,因此您可以扩展需要较少资源的子服务,而无需扩展整个应用程序。

Agility.
One of the most important characteristic of microservices is that because the services are smaller and independently deployable.

Small, focused teams.
A microservice should be small enough that a single feature team can build, test, and deploy it.

Scalability.
Microservices can be scaled independently, so you scale out sub-services that require less resources, without scaling out the entire application.

微服务的好处:

  1. 微服务是独立的,就像一个新项目,每个服务都可以用最适合服务需求的任何语言开发。

  2. 开发者只专注于某个特定的服务,所以代码库会很小,开发者会很了解自己的代码。任何错误的机会也会更少。

  3. 每当一个服务需要与另一个服务通信时,他们可以使用 EventBus 或 Polling:https。

  4. 没有集中的数据库。每个模块都有自己的数据库,因此存在数据分散化。您可以根据模块使用 NoSQL 或关系数据库。

  5. 它是灵活的:一个服务中的故障不会影响其他正在运行的模块。不像单体软件。

  6. 由于依赖性较小,因此易于增强。

  7. 轻松按需独立构建和部署,而不会中断其他服务的可用性。部署服务的模式有以下几种:每台主机多个服务实例,每台主机单个服务实例,每台虚拟机服务实例,每容器服务实例,我们将在下一篇文章中深入回顾它们。

  8. 自由选择技术

Benefits of Microservices are:

  1. Microservices is independent and is like a new project, each service can be developed in any language that is best fitted for the requirement of the service.

  2. The developer is only concentrated on a particular service, so the code base will be very small, and the developer will know his code well. Also the chances of any mistake would be less.

  3. Whenever one service needs to talk to another service, they can do it by using EventBus or Polling: https.

  4. There is no centralized database. Each module has its own database so, there is data decentralization. You can use NoSQL or relational database depending on the module.

  5. It is flexible: failure in one service will not impact the other running modules. Unlike monolithic software.

  6. Easy to enhance as there is less dependency.

  7. Ease to build & deploy independently on demand without disrupting other services availability. There are following patterns for deploying services: Multiple service instances per host, Single service instance per host, Service instance per VM, Service instance per Container, We will review them deeply in next articles.

  8. Freedom to choose technology

来自:https://www.skybin.co/microservices/technology/2017/11/15/what-is-microservices-and-its-benefits-skybin-skybin.html

微服务架构的挑战

复杂。
微服务应用程序有很多服务需要协同工作并且应该创造价值。由于有很多服务,这意味着比单体应用程序有更多的移动部件。

网络问题和延迟。
因此,由于微服务很小并且与服务间通信进行通信,我们应该管理网络问题。

数据的完整性。
微服务有自己的数据持久化。因此,数据一致性可能是一个挑战。


Complexity.

Microservices application has lots of services need to work together and should create a value. Since there are lots of services, that means there is more moving parts than the monolithic application.

Network problems and latency.
So since microservice are small and communicate with inter-service communication, we should manage network problems.

Data integrity.
Microservice has its own data persistence. So data consistency can be a challenge.

设计微服务架构

在本节中,我们将逐步设计微服务架构。根据需求一一迭代拱设计。

微服务通信

迁移到基于微服务的应用程序时,最大的挑战之一是改变通信机制。因为微服务是分布式的,微服务之间通过网络级别的服务间通信进行通信。每个微服务都有自己的实例和进程。因此,服务必须使用服务间通信协议(如 HTTP、gRPC 或消息代理 AMQP 协议)进行交互。由于微服务是独立开发和部署的服务的复杂结构,因此我们在考虑通信类型并将其管理到设计阶段时应该小心。

微服务通信设计模式——API网关模式

如果您想设计和构建具有多个客户端应用程序的复杂的大型基于微服务的应用程序,建议使用 API 网关模式。该模式提供了一个反向代理来将请求重定向或路由到您的内部微服务端点。API 网关为客户端应用程序提供单个端点,并在内部将请求映射到内部微服务。我们应该在客户端和内部微服务之间使用 API 网关。

API 网关可以处理诸如授权之类的横切问题,因此无需编写每个微服务,授权可以在集中式 API 网关中处理并发送到内部微服务。api 网关还管理到内部微服务的路由,并能够在 1 个响应中聚合多个微服务请求。总之,API 网关位于客户端应用程序和内部微服务之间。它充当反向代理并将请求从客户端路由到后端服务。它还提供横切关注点,如身份验证、SSL 终止和缓存。

设计 API 网关 — 微服务通信设计模式

我们将通过添加 API 网关模式来迭代我们的电子商务架构。

Backends for Frontends 模式 BFF — 微服务通信设计模式

前端模式的后端基本上根据特定的前端应用程序分离 api 网关。所以我们有几个后端服务被前端应用程序使用,在它们之间我们放置 API 网关来处理路由和聚合操作。但这会导致单点故障,所以为了解决这个问题,BFF 提供了创建多个 API 网关并根据它们的边界对客户端应用程序进行分组并将它们拆分为不同的 API 网关。

单一且复杂的 API 网关可能存在风险,并成为您架构的瓶颈。较大的系统通常通过对客户端类型(如移动、Web 和桌面功能)进行分组来公开多个 API 网关。当您想要避免为多个接口自定义单个后端时,BFF 模式很有用。

所以我们应该根据用户界面创建几个 api 网关。这些 api 网关提供最匹配前端环境的需求,而无需担心影响其他前端应用程序。Backend for Frontends 模式为实现多个网关提供了方向。

为前端模式 BFF 设计后端 — 微服务通信设计模式

我们将根据后端模式 BFF 添加更多 API 网关模式来迭代我们的电子商务架构。

后端内部微服务如何相互通信

好的,我们已经在我们的微服务架构中创建了 API Gws。并表示所有这些同步请求都来自客户端,并通过 api gws 进入内部微服务。但是,如果客户端请求需要访问多个内部微服务怎么办?我们如何管理内部微服务通信?

在设计微服务应用程序时,我们应该注意后端内部微服务如何相互通信。

最佳实践是尽可能减少服务间通信。

但是,在某些情况下,由于客户要求或请求的操作需要访问多个内部服务,我们无法减少这些内部通信。

例如,查看图像并考虑用例:

  • 用户想要结帐购物车并创建订单

那么我们如何实现这个请求呢?
所以这些内部调用使每个微服务耦合,在我们的例子中 sc – Product 和 Pricing 微服务是相互依赖和耦合的。
如果其中一个微服务出现故障,它就无法向客户端返回数据,因此它没有任何容错能力。如果微服务的依赖和耦合增加,那么就会产生很多问题,并且会削弱微服务架构的力量。

如果客户端结帐购物车,这将启动一组操作。
因此,如果我们尝试使用请求/响应同步消息模式来执行这个订单用例,那么它看起来就像这个图像。

如您所见,一个客户端 http 请求有 6 个同步 http 请求。
因此很明显,增加延迟并对我们系统的性能、可扩展性和可用性产生负面影响。

如果我们有这个用例,如果第 5 步或第 6 步失败了怎么办,或者如果某个中间服务宕机了怎么办?
即使没有宕机,也可能是一些服务繁忙,无法及时响应,导致不可接受的高延迟。

那么这种需求的解决方案是什么?

我们可以应用 2 种方法来解决这个问题,
1. 将微服务通信更改为与消息代理系统的异步方式,我们将在下一节中看到这一点。
2. 使用聚合器模式在 1 个 api gw 中聚合一些查询操作。

聚合器模式——微服务通信设计模式

为了最小化服务到服务的通信,我们可以应用服务聚合器模式。基本上,服务聚合器设计模式是接收来自客户端或 api gw 的请求,然后分派多个内部后端微服务的请求,然后将结果组合并在 1 个响应结构中响应发起请求。

通过服务聚合器模式的实现,我们可以减少客户端和微服务之间的闲聊和通信开销

设计——服务聚合器模式——服务注册模式——微服务通信设计模式

在本节中,我们将通过添加服务聚合器模式 – 服务注册表模式 – 微服务通信设计模式来迭代我们的电子商务架构。

如您所见,我们已经为我们的电子商务架构应用了服务聚合器模式——服务注册模式。

微服务基于消息的异步通信

如果您的通信仅在几个微服务之间进行,则同步通信是很好的。但是当涉及到几个微服务需要相互调用并等待一些长时间的操作直到完成时,我们应该使用异步通信。

否则,微服务的依赖和耦合会造成瓶颈并造成架构的严重问题。如果你有多个微服务需要相互交互,如果你想在没有任何依赖或松耦合的情况下交互它们,那么我们应该在微服务架构中使用基于异步消息的通信。因为基于异步消息的通信提供了事件处理。所以事件可以放置微服务之间的通信。

我们称这种通信为事件驱动的通信。

发布-订阅设计模式

发布-订阅是一种消息传递模式,有消息的发送者称为发布者,有特定的接收者称为订阅者。

所以发布者不会将消息直接发送给订阅者。

而是对已发布的消息进行分类并将它们发送到消息代理系统,而不知道那里有哪些订阅者。类似地,订阅者表示感兴趣并且只接收感兴趣的消息,而不知道哪些发布者发送给他们。

设计——发布/订阅消息代理——微服务异步通信设计模式

在本节中,我们将通过添加 Pub/Sub 消息代理来迭代我们的电子商务架构,以提供微服务异步通信设计。

如您所见,我们已经应用了 Pub/Sub Message Broker — 微服务异步通信设计模式。如果我们调整技术堆栈,我们基本上从 Pub/Sub 消息代理的选项开始。您可以选择 2 个不错的选择;

1- Kafka
2- RabbitMQ

微服务数据管理

在单体架构中,查询不同的实体非常好,因为单个数据库保持数据管理也很简单。跨多个表查询数据很简单。对数据的任何更改都会一起更新或全部回滚。严格一致性的关系型数据库具有ACID事务保证,便于管理和查询数据。

但是在微服务架构中,当我们使用“多语言持久性”时,这意味着每个微服务都有不同的数据库,包括关系数据库和非 SQL 数据库,我们应该在执行用户交互时设置策略来管理这些数据。这意味着我们在处理微服务之间的数据交互时有几种模式和实践,我们将在本节中学习这些模式和原则。微服务是独立的,只执行特定的功能需求,对于我们在电子商务应用程序中的案例,我们有产品、购物篮、折扣、订购微服务需要相互交互以执行客户用例。这意味着他们需要经常相互整合。大多数这些集成是查询每个服务数据以进行聚合或执行逻辑。

CQRS 设计模式

CQRS 是微服务间查询的重要模式之一。我们可以使用 CQRS 设计模式来避免复杂的查询来摆脱低效的连接。CQRS 代表命令和查询责任分离。基本上,这种模式将数据库的读取和更新操作分开。

为了隔离命令和查询,其最佳实践是将读写数据库与 2 个数据库物理分离。通过这种方式,如果我们的应用程序是读密集型的,这意味着读多于写,我们可以定义自定义数据模式以优化查询。

物化视图模式是实现读取数据库的好例子。
因为通过这种方式,我们可以避免使用预定义的细粒度数据进行复杂的连接和映射以进行查询操作。通过这种隔离,我们甚至可以使用不同的数据库来读写数据库类型,比如使用no-sql文档数据库进行读取,使用关系数据库进行crud操作。

事件溯源模式

我们已经学习了 CQRS 模式,并且 CQRS 模式主要与 Event Sourcing 模式一起使用。当使用带有事件溯源模式的 CQRS 时,主要思想是将事件存储到写入数据库中,这将是真实事件数据库的来源。之后,CQRS 设计模式的读取数据库提供具有非规范化表的数据的物化视图。当然,这个物化视图读取数据库消耗来自写入数据库的事件并将它们转换为非规范化视图。

随着事件溯源模式的应用,它正在改变为将数据保存到数据库中的操作。事件溯源模式不是将数据的最新状态保存到数据库中,而是提供将所有事件按顺序排列的数据事件保存到数据库中。这个事件数据库称为事件存储。

它不是更新数据记录的状态,而是将每个更改附加到事件的顺序列表中。因此,事件存储成为数据的真实来源。之后,这些事件存储转换为遵循物化视图模式的读取数据库。此转换操作可以通过带有消息代理系统的发布事件的发布/订阅模式来处理。

设计架构——CQRS、事件溯源、最终一致性、物化视图

我们将通过应用 CQRS、事件溯源、最终一致性、物化视图来设计我们的电子商务架构。

因此,当用户创建或更新订单时,我将使用关系写入数据库,当用户查询订单或订单历史时,我将使用 no-sql 读取数据库,并在使用消息代理系统同步 2 个数据库时使它们保持一致应用发布/订阅模式。
现在我们可以考虑这些数据库的技术栈,我将使用 SQL Server 进行关系写入数据库,并将 Cassandra 用于无 SQL 读取数据库。当然,我们将使用 Kafka 将这 2 个数据库与 pub/sub Kafka 主题交换同步。
如您所见,我们已经完成了微服务数据库模式的设计。让我们深入了解微服务中的这些事件驱动架构。

事件驱动的微服务架构

基本上事件驱动的微服务架构是指通过事件消息与微服务进行通信。我们在微服务异步通信部分的发布/订阅模式和 Kafka 消息代理系统中看到了这一点。

我们说过,使用事件驱动的架构,我们可以进行异步行为和松散耦合的结构。例如,服务不是在需要数据时发送请求,而是通过事件使用它们。这将提供性能提升。

但在事件驱动的微服务架构上也有巨大的创新,例如使用实时消息传递平台、流处理、事件中心、实时处理、批处理、数据智能等。

因此,我们可以使这种事件驱动的方法更通用,并随着这种架构的发展而具有实时事件处理功能。

根据这种新的事件驱动微服务架构,每件事都是通过 Event-Hubs 进行通信。我们可以认为 Event-Hubs 是一个可以进行实时处理的大型事件存储数据库。

设计架构——事件驱动的微服务架构

我们将使用事件驱动的微服务架构来设计我们的电子商务应用程序。

现在让我们决定在这个架构中使用技术栈。当然,我们应该选择 Apache Kafka——作为事件中心和 Apache Spark,用于转换或响应数据流的实时和近实时流应用程序。

正如你所看到的,现在我们有了事件驱动微服务架构的反应式设计。

现在我们可以问同样的问题;

  • 多少并发请求可以容纳我们的设计?

借助这种最新的事件驱动微服务架构,它使用容器和编排器进行部署,可以以低延迟满足目标并发请求。

因为这种架构是完全松散耦合的,并且是为高可扩展性和高可用性而设计的。

如您所见,我们设计的电子商务微服务架构具有设计原则和模式的各个方面。现在,您可以准备好通过这些学习来设计自己的架构,并知道如何在您的设计中使用这些模式工具箱。

参考资料:

https://medium.com/design-microservices-architecture-with-patterns/monolithic-to-microservices-architecture-with-patterns-best-practices-a768272797b2

https://didourebai.medium.com/using-microservices-in-net-core-and-docker-container-c202785dd295

https://www.skybin.co/microservices/technology/2017/11/15/what-is-microservices-and-its-benefits-skybin-skybin.html