微服务、事件驱动架构和 Kafka

news2024/9/24 3:22:48

想象一下,有一个巨大的整体应用程序,其中许多复杂的功能紧密地联系在一起。可扩展性是一个很大的挑战,部署过程可能会变得非常繁琐,而且由于内部组件高度耦合,改变功能流程也不是那么容易。

也许很多人都熟悉这个概念,因为直到几年前这是构建应用程序的标准方法,而且现在生产中仍然有很多单体应用。

但与此同时,尤其是在云服务“爆炸”之后,构建产品的过程转向了微服务方法。具有明确范围的小型微服务,可以与其他服务进行通信以完成业务范围。

尽管它们有其缺点,如复杂的集成测试、更多的远程调用、更大的安全挑战等,但它们在这个行业中已经证明了自己的实力。由于微服务是解耦的,它们可以更容易地扩展,如果你想做出改变,你只需要改变一个组件,只要它们之间的契约得到尊重,其他的微服务不应受到那个改变的影响。

但是,当然,并不是所有事情都是甜蜜的。这种情况很快演变为有很多微服务,每一个都与其他人通信,像在单体中的意大利面代码那样“绑定”在一起。

所以,你现在有很多微服务,它们通过REST、Soap、消息队列或其他通信渠道相互通信。这确实更具扩展性。但这样开发更简单吗?更容易理解工作流程吗?

答案是不!事实上更难。为了理解一个单体的工作流程,你必须从一个方法跳到另一个方法,从一个类跳到另一个类。现在你必须从一个微服务跳到另一个微服务。要做一些更改,你必须确保微服务之间的向后兼容性。

对于测试,你现在必须进行一个异步的集成测试,由不同的微服务组成,它们彼此通信,并且最终部署在不同的实例上。这似乎并不更简单。那么转向微服务方法是一个错误吗?答案是不。我们只需要一个范式变化。

事件驱动架构 

为了克服这种问题,一些微服务应用采用了事件驱动架构。这是因为事件驱动架构具有一些适合微服务方法的特点。让我们来看看它们。

事件与业务流程相符 

从商业角度看,把工作流程描述为一系列事件更容易理解。商人不关心你的内部逻辑。他看到的是事件。

例如,假设我们有一个在线商店。你有一些实体,如:客户、订单、支付和产品。流程是这样的:一个客户订购一些产品,如果支付成功,产品应该交付给客户。如果你以非事件的方式实施这一点,你的工作流程可能是这样的:

  • 客户使用网页界面认证在线商店。

  • 客户通过Web界面与服务器建立HTTP会话。

  • 客户进行REST调用来订购一些产品。

  • 在服务器端,创建了一个订单对象,并将产品添加到其中。

  • 服务器向客户发送支付请求。

  • 如果支付成功,服务器确认订单,更新仓库,产品交付将开始。

这很好,但商人不关心REST协议、会话、认证等细节。他像事件流那样看待一切,这可能会触发其他事件:

  • 客户创建一个订单

  • 客户收到支付请求

  • 如果支付成功,库存将更新并交付订单

这更易于人类阅读,如果出现新的业务需求,更改流程也更容易。

事件与操作相匹配,微服务只关心事件,而不关心其他微服务。我们将有一个微服务,它将获取一个事件,进行一些操作,并可能发送另一个事件。

在我们的情况下,一个客户端应用程序将从客户那里获得一些输入,并触发一个创建订单事件。一些订单服务将接收此事件,它将创建一个订单,并将一个订单创建事件发送到支付服务。这个服务将向客户发送一个支付请求,并尝试验证支付。如果支付成功,它将发送一个支付成功事件到一个仓库服务,这个服务将更新库存并交付产品。

流程更简单,微服务是解耦的。如果你想添加另一个应该记录已创建订单的服务,更改非常小。你需要创建该服务并订阅它的创建订单事件。由于这将与其他服务解耦,原始工作流程不会受到任何修改,风险将是最小的。

事件驱动架构模式 

事件驱动架构有不同的风格。让我们看一下最常见的模式。

事件通知 

在这种设计模式中,事件旨在仅通知状态更改。它们不带任何状态,只是告诉某事已经发生。通常,发送者不期望任何响应。它不是用于来回通信的。事件通知意味着发送者和可能的接收者之间有明确的分隔。因此,它们之间的耦合度很低。任何人都可以接收通知,发送者只是不关心。

让我们看一下在线商店的例子,看看这种模式如何应用。如果客户完成支付,那么支付服务可以发送一个通知,告诉支付已经成功。它不期望任何反馈。其他服务如何处理这个通知,完全取决于它们。

当然,这可能带来一些劣势。如果许多服务正在监听这种通知,如果此通知是复杂逻辑的一部分,跟踪流程并看到发生了什么非常困难。可能需要在生产环境中检查流程才能实际复现问题。

但是,尽管有其劣势,考虑到组件之间的低耦合度和你可以轻松扩展的方式,事件通知模式非常有用。

事件承载状态转移 

顾名思义,在这个模式中,事件将包含整个状态而不仅仅是一个通知。客户端需要的所有信息都包含在那个事件中。客户端不需要为额外信息调用发送者。

如果我们看前面的例子,如果客户想买一些产品,他会选择它们并创建一个订单。然后,订单将发布到订单服务。订单事件包含完成订单所需的所有必要信息。客户详细信息,账单地址,产品,付款方式等。它不需要从客户那里获得任何其他细节。

显然,缺点是你从一个服务传递很多信息到另一个服务。

事件源 

另一种事件驱动模式是事件源。在这里,所有事件都被记录,系统的状态可以通过重播所有事件来重新创建。整个记录库成为真理的唯一来源。

一个非常熟悉的例子是像GIT这样的版本控制服务,其中当前状态是通过重播所有提交来创建的。当然,你可以进行一些优化。例如,GIT会保留一个快照并与提交一起,所以当你克隆一个项目时,你实际上不是从开始重播所有提交,你是从一个快照开始的。但是,记录列表是真理的唯一来源。

这可以带来多种好处,如:

  • 强大的审计功能。你可以看到每一个时间点发生了什么。

  • 你可以重新创建历史状态。

  • 通过返回到旧状态并应用不同的事件,你可以探索替代历史。

Kafka和事件驱动架构 

如今有许多技术可以用来从一个组件传递事件到另一个组件,如Aws Kinesis, Apache Flink, Rabbit Mq等等。

在这篇文章中,我想谈谈Apache Kafka,它可能是目前最受欢迎的流媒体服务,以及为什么它非常适合事件驱动架构。

传统上有两种消息传传递模型:

消息队列:其中消费者从队列中读取。

  • 优点:这种消息类型的优势是可扩展性。如果你需要更多的工人来处理事件,只需添加更多的消费者。

  • 缺点:一个事件只被一个消费者消费。如果你希望两个不同的消费者获得相同的事件,那是做不到的。

发布-订阅者:其中一个消费者订阅一个发布者以获取某种类型的事件。使用这种模型,更多的消费者可以获得相同的数据。但是,由于所有的消息都发给所有的消费者,你不能并行化工作。

  • 优点:事件分发给更多的消费者。

  • 缺点:它不是可扩展的。

Apache Kafka是一个分布式流平台,每天能够处理万亿次的事件。考虑到它的设计,它为你提供了队列消息和发布-订阅服务的双重优势。

它是如何工作的 

Kafka将事件存储在主题中。主题是数据的逻辑分割,如一个分类。例如:所有与客户请求相对应的事件可以保存在一个名为customer-requests的专用主题中,而所有与接收的付款相对应的事件可以保存在另一个名为payment-received的主题中。因此,如果你只想消费客户请求,那么你可以订阅customer-requests主题。这就像拥有多个消息队列,每个分类一个队列。

在内部,一个主题可以被分割成多个分区。分区是一个有序的、不可变的记录序列。

生产者

生产者将数据发布到主题中。此外,生产者还负责选择将数据放入哪个主题分区。默认情况下,Kafka会计算密钥的哈希码并使用它来选择分区。

消费者 

消费者订阅一个主题,然后它将开始从该主题接收数据。消费者可以在消费者组中定义(只是一个标签)。但是,使用这个消费者组对于扩展负载来说是一个关键点。消费者组与kafka主题之间的关系就像一个发布-订阅服务,其中订阅者是整个消费者组。

因此,一个主题的所有数据都会分发给订阅了该特定主题的所有消费者组。现在,我们拥有了一个发布-订阅服务的所有优点,所有数据都分发给所有订阅者。

可扩展性 

在这种情况下,我们如何扩展?就像我之前说的,主题中的数据被分割成多个分区,而消费者组由不同的消费者组成(它们可以是不同机器上的不同进程)。

Kafka确保每个消费者组只有一个消费者会消费一个分区。一个消费者可以从零、一个或多个分区中消费数据。

现在,在一个消费者组内部,我们有一个消息队列,消费者进入一个队列并获取一个元素。这就是我们获得可扩展性的方式。需要更多的工作人员吗?增加消费者和分区的数量。理想情况下,它将是一对一的映射。

这就是Kafka如何结合消息队列和发布订阅者的双重优势,消除了它们的劣势。数据可以分发给更多的消费者,而不牺牲可扩展性。所有这一切都是通过分区和消费者组的概念获得的。

其他优点 

消息排序 

Kafka不保证主题中数据的顺序,但它确保每个分区的数据顺序,而且,由于每个消费者组只有一个消费者消费一个分区,你有保证这些事件以正确的顺序被消费。这与消息队列形成对比,在消息队列中,即使事件按顺序保存,由于许多消费者同时获取数据,你不能保证处理顺序。

数据分发 

Kafka集群可以由多个服务器组成,每个服务器处理一部分分区。但是,此外,分区可以复制到多个服务器。

每个分区都有一个负责填充和处理该分区的读取请求的领导者。但是,由于分区是复制的,如果领导者死亡,其他的跟随者将成为新的领导者,因此不会丢失数据。

因此,这种分布保证了对于一个复制因子为N的主题,一个Kafka集群将容忍N-1次故障而不会丢失任何数据。

存储 

在Kafka中,消费者与生产者是解耦的。生产者发布数据,消费者来控制他们想要消费什么数据,通过指定消息偏移量,以及多久消费一次。因此,Kafka成为一个存储服务。数据在集群中保留一段配置的保留时间,不管数据是否被某些消费者读取。

此外,由于分区是为了故障转移而复制的,数据是隐式复制的。所以,就像我之前说的,对于一个复制因子为N的主题,Kafka保证在最多N-1次故障中不会丢失数据。

结论 

如今,特别是在“云服务的爆炸”之后,我们越来越感到迁移到微服务的需要,而不是构建单体应用。可以单独开发、使用不同的编程语言、由不同的团队开发,并根据其特定需求单独扩展的小型解耦微服务。当然,为了实现业务范围,你需要将多个微服务绑定在一起。

有很多方法可以做到这一点,但是,正如我们所看到的,事件驱动架构具有一些特点,使其非常适合将服务绑定在一起。

一个事件驱动的设计伴随着一个共同的事件通道的需求。在那里有很多不同的解决方案,Kafka也许是最受欢迎的一个。Kafka结合了发布-订阅服务和消息队列的双重优势,成为一个非常高效且可扩展的平台,每天可以传送数百万(甚至数万亿)的事件。

作者:Ioan Tinca

更多内容请关注公号【云原生数据库

squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1131561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安科瑞无线测温产品在某风电场项目的超温事故预警及分析-安科瑞 蒋静

摘 要:作为保证系统安全运行的重要设备的高压开关柜装置,其内部导电连接处过热会导致电气设备的损坏,更严重的是可能还会发生火灾等严重事故。因此,电力系统中电器设备安全运行的一个重要课题就是对高压开关柜实施在线监测。本文主要研究的是针对高压开关柜接点的无…

JoySSL证书买二送一买三送二特别活动

数字安全对于网站运营和用户信任至关重要。JoySSL作为一家知名的SSL证书品牌,为了回馈广大用户,推出了买二送一和买三送二的特别活动。 超值优惠:买二送一、买三送二 JoySSL的买二送一和买三送二活动非常有吸引力。在买二送一的活动中&#…

互联网医院|互联网医院建设三级等保不可缺

等级保护全称“网络安全等级保护”,指对国家重要信息、法人和其他组织及公民的专有信息以及公开信息和存储、传输、处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的信息安全产品实行按等级管理,对信息系统中发生的信息安全事件…

Spring Cloud Config

Spring Cloud Config 服务端:一个集中化配置中心,可以是一个独立的服务,也可以注册到服务治理中心,它可以集中管理各个 微服务的配置; 作用原理是从某个地方读取(本地/云端)提供给其客户端作为配置; 客户端:作为一个服务端,通过读取Config的服务端来获取自己的配置文件; 服务…

java实现颜色拾色器并打包成exe文件

我们先来看看效果 一.源码 废话不多说,直接上代码: import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class ColorPicker extends JFrame {private JButton colorButton;pri…

曼哈顿距离

曼哈顿距离 以7*7为例 在d<n/2时&#xff1a;打印的图案为菱形 例题&#xff1a; 输入奇数n&#xff0c;显示n行星塔。若输入5&#xff0c;则显示 #include<stdio.h> #include<math.h> int main() {int n, i, j, x, y;scanf("%d", &n);x y n …

『C语言进阶』动态内存管理

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f516;系列专栏&#xff1a; C语言、Linux、Cpolar ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言一、动态内存函数的介绍1.1 malloc和free函数1.2 calloc函数1.3 realloc函数 二、常见的动态内存错误2.1 …

记一次vue3实现TRSP大华相机拉流的经历

一、背景 业务场景&#xff0c;大华IP相机安装在A城市某建筑场所&#xff0c;工控机是内网通过4G流量卡上网&#xff0c;工控机通过相机采集数据后做故障识别并上传故障信息到地面服务器&#xff0c;地面服务器在B城市。 现需要在地面服务器提供的WEB界面上实现IP相机实时拉流…

计算机毕设 opencv 图像识别 指纹识别 - python

文章目录 0 前言1 课题背景2 效果展示3 具体实现3.1 图像对比过滤3.2 图像二值化3.3 图像侵蚀细化3.4 图像增强3.5 特征点检测 4 OpenCV5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往…

Python基础教程:列表推导式详解

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 我们经常需要这样处理一个列表&#xff1a; 把一个列表里面的每个元素&#xff0c; 经过相同的处理 &#xff0c;生成另一个列表。 比如&#xff1a; 一个列表…

量子计算与量子密码(入门级)

量子计算与量子密码 写在最前面一些可能带来的有趣的知识和潜在的收获 1、Introduction导言四个特性不确定性&#xff08;自由意志论&#xff09;Indeterminism不确定性Uncertainty叠加原理(线性)superposition (linearity)纠缠entanglement 虚数的常见基本运算欧拉公式&#x…

操作教程|如何注册成为Moonbeam社区代表参与治理

社区代表是高度参与社区治理的社区成员&#xff0c;其主要职责是将社区成员委托给他们的投票权参与社区投票&#xff0c;并确保链上治理稳健发展和活跃参与度。本文将向您展示如何快速注册成为社区代表。 首先&#xff0c;前往Moonbeam委托网站&#xff0c;点击网页右上角的“…

有财务自由的思维,才能实现财务自由!

前两天在洋哥、竹子姐以及渡心总等大佬的带领下&#xff0c;第一次体验了穷爸爸富爸爸的作者研发的现金流游戏&#xff0c;收获颇丰&#xff01; 游戏规则说明 心灵创富 现金流游戏分为三步&#xff1a; 一局游戏&#xff0c;时间两个小时&#xff1b;总结分享时刻&#xff…

NSSCTF做题第9页(2)

[SWPUCTF 2022 新生赛]ez_1zpop <?php error_reporting(0); class dxg { function fmm() { return "nonono"; } } class lt { public $impohi; public $md51weclome; public $md52to NSS; function __construct() { $this-&…

buuctf_练[羊城杯2020]easyphp

[羊城杯2020]easyphp 文章目录 [羊城杯2020]easyphp掌握知识解题思路关键paylaod 掌握知识 ​ .htaccess文件的利用&#xff0c;把自己指定当做 php文件处理&#xff1b;preg_match正则匹配的了解&#xff0c;stristr函数的绕过&#xff1b;file_put_contents文件写入操作的了…

Kubernetes速成课程:掌握容器编排的精髓

微服务演进方向 • 面向分布式设计(Distribution):容器、微服务、API 驱动的开发; • 面向配置设计(Configuration):⼀个镜像&#xff0c;多个环境配置; • 面向韧性设计(Resistancy):故障容忍和自愈; • 面向弹性设计(Elasticity):弹性扩展和对环境变化(负载)做出响应; •…

初识Java篇

1.介绍Java语言 1.1Java是什么 Java是一种优秀的程序设计语言&#xff0c;它具有令人赏心悦目的语法和易于理解的语义。 不仅如此&#xff0c;Java还是一个有一系列计算机软件和规范形成的技术体系&#xff0c;这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境&am…

JS:将秒数转化为时分秒的形式

要求 将秒数转化为时分秒的形式,比如12&#xff1a;34&#xff1a;09代表12小时34分钟9秒注意&#xff1a; &#xff08;1&#xff09;如果只有一位数&#xff0c;前面要用0补齐&#xff0c;比如9秒要用09表示 &#xff08;2&#xff09;如果对应单位上的数字为0&#xff0c;要…

提升用户体验的利器:揭秘Spring框架中国际化的奇妙魔力

国际化 简单来说&#xff0c;国际化就是让应用&#xff08;app、web&#xff09;适应不同的语言和地区的需要&#xff0c;比如根据地区选择页面展示语言。 i18ninternationalization&#xff0c;首末字符i和n&#xff0c;18为中间的字符数 原理 基于传入语言or地区标识进行判…

【面试经典150 | 链表】两数相加

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;模拟 其他语言python3 写在最后 Tag 【单向链表】【数组】 题目来源 2. 两数相加 题目解读 对两个链表对应位置进行相加&#xff0c;最后返回结果链表的头结点。 解题思路 很多同学对链表操作不是很熟悉&#xff0c…