【Java】如何根据应用场景选择合适的消息中间件?

一、问题解析

21.1 消息中间件的应用场景

消息中间件的应用场景主要有两个:异步解耦与削峰填谷。

我们首先通过电商平台用户注册送积分、送优惠券这个场景来理解异步解耦合。如果不使用消息中间件,电商平台送积分的实现也许是下图这个样子:

我们简单看一下这个流程。

  1. 用户在网站前端注册页面填写相关信息,然后调用账号中心服务,注册账号。
  2. 账户中心首先执行用户注册逻辑处理(例如判断用户是否已注册、是否符合注册条件等),然后写入到数据库。
  3. 注册成功后,需要调用积分中心(赠送积分接口)给用户送积分。
  4. 送完积分后,再调用优惠券相关接口,为用户赠送优惠券。
  5. 成功送完积分、优惠券后,向用户返回“注册成功”

从架构角度看,上面这个实现方法有一个非常严重的问题,那就是可扩展性低。

例如,如果要在春节期间调整活动策略,在发送积分的同时,还需要额外发送新春大礼包,开发人员为了实现这一功能,就不得不修改用户注册流程,并重新部署用户注册模块。

从功能维度来看,这次需求的变更集中在活动相关的内容。用户注册本身的逻辑并未发生变化,但由于用户注册逻辑与活动模块存在耦合,两个模块必须一起调整和发布,这就对系统稳定性造成了影响。

另外,调用积分、优惠券两个远程 RPC 请求让用户注册主流程变长,在高并发场景下,用户注册这一环容易成为系统瓶颈。

要解决上面这两个明显的设计缺陷,常用的方案是引入消息中间件,让用户注册主流程和商家活动异步解耦合。改造后的时序图如下:

账户中心完成用户注册相关逻辑后,会向 MQ 发送一条消息到 MQ 服务器,然后就直接给用户返回“注册成功”。赠送优惠券、积分等与活动相关的需求我们可以异步执行,这样,无论后续互动逻辑发生什么变化,账户中心都不需要发布新版本。

引入送积分服务(MQ 消费者应用)和送优惠券服务(MQ 消费者应用)会订阅消息,并根据消息调用积分中心、优惠券中心的服务。如果后续活动发生变化,例如取消送积分活动但开始赠送新春大礼包,那我们只需停止送积分服务应用,增加送新春大礼包的消费者应用,就可以真正做到对新增开放,对修改关闭。

消息中间件的另外一个常用场景是削峰填谷。我们来看一个外卖骑手送餐的场景。它的设计架构图如下:

我们分别说明一下“创建订单流程”和“查询订单信息”两个流程,探究一下这个方案的精髓。

先来看创建订单流程。

  1. 用户在 App 中下单,App 会调用网关相关接口创建订单,网关接收到请求后,并不是直接调用内部商户订单中心来创建订单接口,而是先发送一条消息到 MQ。
  2. 商户接单模块(Consumer)订阅 MQ 中的消息,处理消息的时候调用内部商户订单中心创建订单接口,创建一条真正的订单数据到数据库。
  3. 创建订单后,商户订单中心将再发送一条消息到 MQ 服务器。然后骑手分配模块(Consumer)订阅消息,调用派单服务相关接口,引导骑手进行外卖配送。
  4. 同时,数据同步组件(Canal)将数据库中的数据准实时同步到 Es 服务器。

为什么网关不直接调用外部的创建订单接口,而是将数据先写入到 MQ 中呢?

我们不妨设想一下,商户订单中心支持的最大并发为 1w/tps。如果某一个业务高峰期,从网关进入的流量突然飙升到 1.5w/tps,而且持续了 10 分钟,商户订单系统会直接崩溃,造成服务不可用等严重故障!

那该如何解决呢?

有人可能会说,我们可以使用限流机制保护商户订单系统。例如,我们只允许 9000TPS 的流量从网关进入到商户订单中心,直接拒绝多余的流量,让客户端重试。这确实可以解决问题,但会带来经济损失和糟糕的用户体验。

这个时候我们有一个更加友好的解决方案:引入消息中间件。

引入消息中间件的目的是让它来扛住海量流量,流量先进入到消息队列中,然后消费端下游系统可以慢慢消费消息中间件中的数据,这样能有效保护下游系统不被瞬时的流量击破。这种方案可能带来的最坏结果就是,消费这些消息会存在延迟。但这些订单都可以成功创建,真正的交易行为已经产生了。接下来要做的就是根据实际情况扩容或者缩容,尽快将积压的数据处理掉。

不过我们这个时候引入消息中间件,其实潜台词是它们的性能必须满足下面几个基本要求:高吞吐量、低延迟,还要具体消息堆积能力。

我们再看一下订单查询流程:

  1. 用户在 App 端发起订单查询,App 会调用网关的订单查询接口,网关再将请求转发到内部的订单查询服务;
  2. 订单查询服务不是在 MySQL 数据库,而是直接查询 Es 中的数据。

这里一个设计的亮点是,引入了数据同步组件 Canal,将 MySQL 数据库中的数据实时同步到了 Es。这样查询订单时只查 Es 就可以了,实现了订单写入与订单查询在异构数据源的读写分离

21.2 消息中间件的技术选型

在这节课的最后,我们来看看如何选择消息中间件。

目前消息中间件领域主要的中间件包括 RocketMQ、Kafka 和 RabbitMQ,我们先来看一下这张功能对比图:

结合上面这张图,我们再对比分析一下。

首先,我认为功能级别不具备一票否决权

例如,RabbitMQ 支持优先级队列,而 RocketMQ、Kafka 不支持,那么如果我们的项目中有优先级队列的使用诉求,我们就必须将 Kafka、RocketMQ 排除掉,选择使用 RabbitMQ 吗?我是不建议这样做的,任何涉及到功能的短板,都可以通过其他方式实现。

但我也并不是说功能特性就一点都不重要。这一点我在后面讨论 RocketMQ 与 Kafka 的选型时会再次谈到。

其次,我认为在选型时要特别注意中间件的性能和扩展性。

因为随着业务不断地发展,性能问题会越来越突出,而且性能问题都具有隐蔽性,一旦发生,破坏性大,影响程度深,让人防不胜防。

例如,RabbitMQ 的消息堆积能力不强,一旦消费端无法及时将消息处理掉,会极大影响消息服务器发送消息的性能。这一点是非常致命的,因为引入消息中间件的目的就是抵挡住洪峰流量,如果消息中间件因为积压问题影响了消息的发送,那是万万不可取的。

因此,从性能的角度来看,RocketMQ 和 Kafka 比 RabbitMQ 的表现更好。

另外一个重要的因素也不得不加以考虑,那就是中间件使用的编程语言。

在使用中间件时一般都会遇到很多问题,一个非常行之有效的方法就是深入研究源码。这时候,如果中间件的编写语言和团队技术栈不匹配,将会极大地增加深入研究这款中间件的难度。如果团队对中间件的掌控能力很弱,自然很难保持中间件的稳定运行。

在进行具体的选型时,我们可以结合自己团队的实际情况。

  • 如果公司或团队的技术栈以 Golang 为主,建议选择 RabbitMQ,RabbitMQ 在性能上的缺陷可以通过搭建多套集群加以规避。
  • 如果公司或团队的技术栈以 Java 为主,我建议使用 Kafka 或 RocketMQ。RocketMQ 和 Kafka 都是性能优秀的中间件,在这两者之间进行选择时可以更多地关注功能特性。RocketMQ 提供了消息重试、消息过滤、消息轨迹、消息检索等功能特性,特别是 RocketMQ 的消息检索功能,因此 RocketMQ 很适合核心业务场景。而 kafka 更加擅长于日志、大数据计算、流式计算等场景。
  • 二、粉丝福利

  • 我根据我从小白到架构师多年的学习经验整理出来了一份80W字面试解析文档、简历模板、学习路线图、java必看学习书籍 、 需要的小伙伴斯我一下,或者评论区扣“求分享”

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI】文心一言的使用分享

在数字化时代,人工智能(AI)技术的飞速发展正在改变我们的生活。文心一言,作为这一浪潮中的佼佼者,以其卓越的自然语言处理能力和广泛的应用场景,给我带来了前所未有的使用体验。在这篇分享中,我…

新能源车用驱动器 电机电驱

硕博电子的电机电驱是以一体化动力总成为设计理念,整合电控、电机核心模块,推出的电机电控一体化动力总成。电机电控动力总成采用矢量控制算法和CAN总线通信技术,体积小、效率高、免维护、电磁兼容性强、方便调试,提高了系统的可靠…

复旦大学首本大模型中文书太厉害啦!【大模型书籍推荐】

前言 在信息爆炸的时代,自然语言处理(NLP)技术如同璀璨的星辰,照亮了我们与机器沟通的道路。而今,复旦大学自然语言处理实验室的教授团队,如同航海家般,为我们带来了一本指引大语言模型领域前行…

【原创教程】三菱Q与MERLIN II LS激光打标机控制说明

一、控制流程说明 1.硬件连接→2.软件通讯连接→3.编写远程控制PLC程序→4.编写通讯命令。 二、硬件连接1.用RJ45口普通网线将PLC和打标机连接。 三、软件通讯连接 1.打标机侧工控机-更改操作权限-点击菜单栏Setup,在下拉菜单中,点击Level,在下一级菜单点击Supervisor(左下…

【工程实践】gradio调用模型与展示

前言 模型在云端部署好之后,衍生出Flask、Fastapi的接口,可以借助gradio调用接口展示在前端。 1.gradio代码 import gradio as gr import requests import json #调用部署的云服务接口 def greet(question):prefix_url http://0.0.0.0/get_classificat…

【Nginx系列】基于请求头的分发

文章目录 一、HTTP请求头和响应头二、基于请求头的分发2.1、基于host分发2.2、基于域名的分发测试:2.3、基于开发语言分发2.4、基于浏览器分发2.5、基于源IP分发 🌈你好呀!我是 山顶风景独好 🎈欢迎踏入我的博客世界,能…

代码签名证书一年的价格是多少?如何申请

代码签名证书的价格因品牌、类型及所提供的服务等因素而有所不同,价格通常在数千元至万余元人民币之间不等。 不同类型代码签名证书价格差异 个人代码签名证书:个人代码签名证书是最基础的类型,适用于个体开发者,其价格较为经济…

【Java】解决Java报错:ArithmeticException during Division

文章目录 引言一、ArithmeticException的定义与概述1. 什么是ArithmeticException?2. ArithmeticException的常见触发场景3. 示例代码 二、解决方案1. 检查除数是否为零2. 使用异常处理3. 使用浮点数除法4. 使用自定义方法进行安全除法 三、最佳实践1. 始终检查除数…

香草看涨期权是什么意思?

香草看涨期权是什么意思? 香草期权,听起来或许有些异国风情,但实际上,它是金融市场中一种极为基础和普遍的交易工具。所谓的“香草”,在金融术语中其实是比喻一种平凡、普通但不可或缺的特质,正如我们日常…

基于PHP+MySQL组合开发的小程序源码系统 附带完整的安装代码包以及搭建教程

系统概述 本小程序源码系统采用PHP作为服务器端脚本语言,MySQL作为数据存储引擎,充分利用两者在Web开发领域的成熟性和灵活性。PHP以其简单、直接的语法和广泛的社区支持,成为快速开发Web应用的首选语言之一;而MySQL作为关系型数…

直到第三次才遇见懂行人,教育信息化深耕者如何选对CRM

如今,与诸多顶尖双一流大学交流时,BDRJ公司的销售们底气十足。作为一家在教育圈内知名度颇高的数字内容智能服务提供商,BDRJ深耕国内教育行业内容管理领域二十余年,是国内双软认证企业,中国高等教育学会教育信息化分会…

计算机组成原理(四)

在同一时刻只能有一对设备使用总线,会发生总线的争用 面向CPU的双总线 如果外部设备和主存之间发生信息传输,因为媒介是CPU,一样会打断CPU执行程序的任务 以存储器为中心 但是存储总线和系统总线依然不能同时使用,都是分时使用 …

20240612每日前端-------vue3实现聊天室(一)

先上效果图 讲讲布局设计 聊天室大致分三块: 左边导航右边聊天界面主界面 单独调整一下样式:外层friend-box先调整布局为flex,这样方便进行自适应布局,增加背景色为白色,设置边框圆角使得外观更加美观,使…

【Python入门与进阶】Jupyter Notebook配置与优化

目录 1.Jupyter Notebook简介 2.Jupyter Notebook的安装 2.1 命令行安装 2.2 可视化界面安装 3.Jupyter Notebook的使用 3.1 启动 Jupyter Notebook 3.2 Jupyter Notebook 界面介绍 3.3 创建新的 Notebook 3.4 编写和运行代码单元 3.5 使用 Markdown 编写文档 3.6 保…

[大模型]GLM-4-9B-Chat WebDemo 部署

环境准备 在autodl平台中租一个4090等24G显存的显卡机器,如下图所示镜像选择PyTorch–>2.1.0–>3.10(ubuntu22.04)–>12.1 接下来打开刚刚租用服务器的JupyterLab, 图像 并且打开其中的终端开始环境配置、模型下载和运行演示。 pip换源和安装…

Django+Vue.js怎么实现搜索功能

一.前言 类似这样的搜索功能 二.前端代码 <div class"form-container"><div class"form-group"><label for"departure-city">出发城市</label><select v-model"departureCity" id"departure-city&q…

SM3国密算法:优秀的密码散列函数

随着信息技术的飞速发展&#xff0c;信息安全已成为全球关注的焦点。密码学作为保障信息安全的核心技术&#xff0c;其重要性不言而喻。中国在密码学领域也取得了显著的成就&#xff0c;其中SM3国密算法就是中国自主设计并推广使用的密码学标准之一。 一、SM3算法概述 SM3算法…

H2database 未授权访问 vulhub

参考&#xff1a;H2database-未授权访问漏洞复现_h2 database connection-CSDN博客 1.工具 虚拟机&#xff1a;kalidocker java包&#xff1a;Release JNDI-Injection-Exploit v1.0 welk1n/JNDI-Injection-Exploit GitHub 这个包可能会报木马&#xff0c;如果发现没下载下…

pytest中一个场景测试的demo

注意点1&#xff1a; allure.severity 是一个装饰器&#xff0c;用于设置测试用例的严重性级别。 allure.severity_level.CRITICAL 是Allure提供的严重性级别之一&#xff0c;表示这个测试用例极为重要。allure.severity_level.BLOCKER&#xff1a;阻塞级别的问题&#xff0c…

element-ui将组件默认语言改为中文

在main.js中加入以下代码即可 // 引入 Element Plus 及其样式 import ElementPlus from element-plus import element-plus/dist/index.css// 引入中文语言包 import zhCn from element-plus/es/locale/lang/zh-cn// 使用 Element Plus 并设置语言为中文 app.use(ElementPlus,…