系统架构的演进:同步通讯到异步通讯的过渡

news2024/9/17 7:40:24

系统架构的演进:同步通讯到异步通讯的过渡

  • 一 . 同步通讯 VS 异步通讯
    • 1.1 同步调用方案
      • ① 耦合度高
      • ② 性能下降
      • ③ 资源浪费
      • ④ 级联失败
    • 1.2 异步调用方案
      • ① 同步解耦
      • ② 性能提升 , 吞吐量增加
      • ③ 服务没有强依赖 , 不必考虑级联失败问题
      • ④ 流量削峰
    • 1.3 小结
  • 二 . 三大 MQ 的对比

在现代软件开发中,通讯方式的选择对于系统的性能和可扩展性至关重要。我们将对比同步通讯与异步通讯的不同之处,以及它们在实际应用中的优缺点。通过一个电商系统的例子,我们将揭示同步调用可能导致的耦合度高、性能下降、资源浪费和级联失败等问题。同时,我们将探索异步调用如何通过事件驱动和消息队列(Broker)来解决这些问题,实现服务解耦、性能提升和流量削峰。

此外,我们还对市面上流行的四种消息队列技术—— RabbitMQ、ActiveMQ、RocketMQ 和 Kafka 进行全面的比较。我们将从它们的开发语言、支持的协议、可用性、吞吐量、消息延迟和可靠性等多个维度进行分析,了解每种技术的特长和适用场景。
在这里插入图片描述

一 . 同步通讯 VS 异步通讯

同步通讯就类似于打视频电话 , 一旦建立连接 , 二者就建立了同步联系 . 虽然同步通讯的时效性较高 , 但是同一时间点只能有一个人跟我进行对话 .

而异步通讯就类似于发微信消息 , 同一时间点我可以跟许多人聊天 , 但是它的时效性并不是太好 , 接收方不一定就能立刻看到消息 , 可能需要等待一段时间才能看到消息 .

1.1 同步调用方案

我们可以通过一个电商系统来反射出同步通讯和异步通讯的问题

画板

① 耦合度高

那产品经理想要增加一个短信功能

画板

那由于订单服务、仓储系统、短信系统都需要支付服务来进行调用 , 这就需要修改支付服务的代码 , 就导致整个系统出现了耦合 .

② 性能下降

那这样的模型 , 还会导致性能下降 , 假设我们每个服务所耗费的时间我们都标注在下面了

画板

那由于整个系统是同步调用的 , 只有等待订单服务执行完毕 , 支付服务才能继续调用通知仓储系统 .

因此 , 整个流程执行下来 , 需要 50ms + 150ms + 150ms + 150ms = 500 ms , 这也就意味着 1s 只能处理 2 个订单 , 非常耗时 .

③ 资源浪费

那调用链中的每个服务 , 都需要等待前一个服务结束才能执行下一个服务 , 在等待的过程中也会浪费许多资源 .

④ 级联失败

假设仓储系统承受了巨大的压力 , 最后扛不住了 . 那支付服务调用仓储系统 , 就会调用失败 , 就会阻塞到这里 .

那之后越来越多的请求调用支付服务 , 然后再去调用仓储服务 , 那这些请求都会被阻塞掉 , 最后都会执行失败 .

慢慢的就会导致支付服务也承受不住压力崩溃掉 , 导致整个系统出现了故障 , 最终就会导致用户的体验感大大降低 .

1.2 异步调用方案

异步调用最常见的就是事件驱动模式 .

当用户进行支付的时候 , 就会调用支付服务 . 支付成功之后 , 就需要订单服务、仓储系统、短信系统各自执行自己的业务 .

画板

那事件驱动模式肯定不可能跟之前一样 , 由支付服务调用这三个服务 .

那他的做法是在中间添加一个 Broker (事件代理者)

画板

那什么叫事件代理呢 ?

那对于我们这个业务来说 , 一旦有用户支付成功 , 就是一个事件 , 那这个事件就会交给 Broker 来去管理 .

那订单服务、仓储系统、短信系统就会跟 Broker 询问用户是否支付成功 , 这就叫做事件订阅 .

画板

那在这个模型中 , 支付服务发布了支付成功事件之后 , 就结束了他的任务 , 就可以返回结果给用户了 .

那支付服务把通知订单服务、仓储系统、短信系统的工作交给了 Broker 来去实现 , 它就不再自己去通知这三个服务了 .

那这种方式相比于同步调用 , 存在哪些优势呢 ?

① 同步解耦

假如我们的产品经理又想要添加优惠券功能 , 那就不需要修改支付服务的代码了 , 因为支付服务只负责发布支付成功的事件 , 我们只需要让新功能来去从 Broker 中订阅事件即可 .

画板

这样就解决了服务和服务之间的耦合了 .

那后续如果产品经理觉得短信通知太费钱了 , 我们也不需要删除代码 , 只需要让短信系统取消订阅事件即可

画板

② 性能提升 , 吞吐量增加

在之前 , 我们是需要支付服务依次调用其他所有服务 . 而现在不一样了 , 支付服务只负责发布支付成功事件 , 那这样的话支付服务就可以立即返回给用户支付成功信息 , 而其他的订单服务、通知仓储系统等等本身就是与用户无关的业务 , 所以不需要将这些业务算进我们的运行时间中 .

画板

那这样的话 , 总共才需要 50ms+10ms = 60ms , 性能大大提升 , 吞吐量也提高了

③ 服务没有强依赖 , 不必考虑级联失败问题

如果通知仓储系统挂了 , 也跟支付服务没有多大关系 , 支付服务只负责发布支付成功事件 , 这样的话就不必关心级联失败的问题了 .

④ 流量削峰

假设同一个时间点 , 只能处理一个请求 , 那此时过来了许多请求 , 就可以将请求放入到 Broker 中 , 然后订单服务、仓储系统 … 慢慢执行就可以了

画板

1.3 小结

同步调用的优点 : 时效性较强 , 可以立即得到结果

同步调用存在的问题 :

  1. 耦合度高
  2. 性能下降
  3. 有额外的资源消耗
  4. 存在级联失败问题

异步通信的优点 :

  1. 耦合度低
  2. 吞吐量提升
  3. 故障隔离
  4. 流量削峰

异步通信的缺点 :

  1. 非常依赖 Broker 的可靠性、安全性、吞吐能力
  2. 架构变的更加复杂 , 不方便追踪管理

二 . 三大 MQ 的对比

MQ (MessageQueue) , 也叫做消息队列 , 字面意思指的就是存放消息的队列 , 也就是事件驱动架构中的 Broker

这里的消息指的就是我们上面说的事件

我们来看一下市面上比较常见的四种 MQ 的技术对比 :

RabbitMQActiveMQRocketMQKafka
公司/社区RabbitApache阿里Apache
开发语言Erlang
(并发能力强 , 性能极其好)
JavaJavaScala & Java
协议支持AMQP、XMPP、SMTP、STOMPOpenWire、STOMP、REST、XMPP、AMQP自定义协议自定义协议
可用性一般
单机吞吐量
(性能承载能力)
一般非常高
消息延迟微秒级毫秒级毫秒级毫秒以内
消息可靠性
(消息会不会丢)
一般一般

追求可用性 (当需要处理数据时 , 资源处于可用状态的程度) : Kafka、RocketMQ、RabbitMQ

追求可靠性 : RabbitMQ、RocketMQ

追求吞吐能力 (十万级别的) : RocketMQ、Kafka

追求消息低延迟 : RabbitMQ、Kafka

那综上所述 , 每个方案都有优缺点 , 并没有十分完美的技术 . 我们按照自己业务的要求选择合适的消息队列即可 .


到此为止 , MQ 的简单介绍就介绍到这里了 , 如果对你有帮助的话 , 还请一键三连~
希望得到你的鼓励
在这里插入图片描述

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

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

相关文章

【C++】STL学习——stack和queue的讲解(了解适配器)

目录 stack介绍queue介绍适配器stack的模拟实现queue模拟实现deque(了解) stack介绍 stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行 元素的插入与提取操作。stack是作为容器适配器被…

Java | Leetcode Java题解之第393题UTF-8编码验证

题目&#xff1a; 题解&#xff1a; class Solution {static final int MASK1 1 << 7;static final int MASK2 (1 << 7) (1 << 6);public boolean validUtf8(int[] data) {int m data.length;int index 0;while (index < m) {int num data[index];…

算法练习题18——leetcode240搜索二维矩阵||(二分)

题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 代码 class Solution {public boolean searchMatrix(int[][] matrix, int target) {for(int[…

双指针(6)_单调性_查找总价格为目标值的两个商品

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 双指针(6)_单调性_查找总价格为目标值的两个商品 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#…

DuPL: Dual Student with Trustworthy Progressive Learning for Robust WSSS

摘要 近年来&#xff0c;具有图像级标签的单阶段弱监督语义分割(WSSS)因其简化了其繁琐的多阶段语义分割而获得了越来越多的关注。由于类激活图(Class Activation Map, CAM)固有的模糊性&#xff0c;我们观察到一级管道经常会遇到由错误的CAM伪标签引起的确认偏差&#xff0c;…

基于SpringBoot的图书馆座位预约系统+小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

继电器的使用

本文为大家讲一下继电器的常规使用. 添加 在菜单中选择 “绘制–无源元件–添加继电器(relay)” 以添加继电器. 或者用 shiftr(大写) 这个快捷键 继电器由一个线圈和该线圈所控制的铁质弹性开关(衔铁)组成. 原理 它的原理如下: 上面的铁质弹性开关, 默认情况下在弹力作用下…

java基础概念22-抽象类

一、抽象类的引入 1-1、封装 问题&#xff1a;javabean越来越多。重复的内容越多——继承 1-2、继承 二、抽象类、抽象方法 一个方法抽取到父类中&#xff0c;不确定方法体——抽象方法 定义了抽象方法的类——抽象类。 在Java中&#xff0c;抽象类是一种特殊的类&#xff0c…

博士生锻炼记录:2024.9.8

读博三年来感觉身体状况大不如前&#xff0c;虽然博士生的主要任务就是做课题和发文章&#xff0c;但是身体健康也是不容忽视的一环&#xff0c;一个好的身体是做好任何事情的基础&#xff0c;我们应该在不影响身体健康的前提下努力做课题。 这周初去参加了一个体成分测量的活…

Python编码系列—Python项目管理:掌握高效工具与实践

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

YOLOv9改进策略【Neck】| 使用CARAFE轻量级通用上采样算子

一、本文介绍 本文记录的是利用CARAFE上采样对YOLOv9的颈部网络进行改进的方法研究。YOLOv9采用传统的最近邻插值的方法&#xff0c;仅考虑子像素邻域&#xff0c;无法捕获密集预测任务所需的丰富语义信息&#xff0c;从而影响模型在密集预测任务中的性能。CARAFE通过在大感受…

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包&#xff0c; 通常我们会使用nohup直接启动&#xff0c;但是还是需要手动停止然后再次启动&#xff0c; 那如何更优雅的在服务器上启动jar包呢&#xff0c;让我…

设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)

文章目录 1、工厂模式概述1&#xff09;特点&#xff1a;2&#xff09;主要角色&#xff1a;3&#xff09;工作流程&#xff1a;4&#xff09;优点5&#xff09;缺点6&#xff09;适用场景 2、简单工厂模式(静态工厂模式)1) 在简单工厂模式中&#xff0c;有三个主要角色&#x…

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

浏览器插件利器--allWebPluginV2.0.0.20-alpha版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

小琳AI课堂:深入学习BERT

大家好&#xff0c;这里是小琳AI课堂。今天我们来聊聊BERT&#xff0c;这个在自然语言处理&#xff08;NLP&#xff09;领域掀起革命风潮的模型。 出现背景 在BERT之前&#xff0c;NLP领域主要依赖RNN或CNN模型&#xff0c;这些模型大多只能单向处理文本&#xff0c;从左到右…

【全网首创】大模型LLM-RAG知识库问答项目实战课

在大数据和人工智能迅猛发展的今天&#xff0c;大模型和知识库的结合成为了理论探索和实际应用的重要方向。LLM-RAG项目课程正是围绕这一热点展开&#xff0c;旨在通过系统性的教学&#xff0c;帮助学员掌握从项目部署、模块开发到实际应用的完整流程。课程共有43课时&#xff…

SprinBoot+Vue公交智能化系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

高可用架构模式

架构里比较重要的是高性能、高可用、高扩展性。上次是高性能&#xff0c;这次是高可用。 对一般的项目而言&#xff0c;高可用主要用公司提供的基建&#xff0c;如多机房部署、主从等。但有些项目确实需要思考更多高可用的事项&#xff0c;如资源不足的情况下要做好限流或者降…

gdb中使用python脚本

1、入门案例 首先有1个a.cpp&#xff0c;代码如下&#xff1a; #include <map> #include <set> #include <iostream> #include <string>using namespace std;struct MyStruct {std::string mName;std::map<int, std::string> mField1;std::set…