目录:
-
- [一、"消息服务" 概述 :](#一、"消息服务" 概述 :)
-
- [1.1 为什么要使用 "消息服务" ( 消息中间件 ) ?](#1.1 为什么要使用 "消息服务" ( 消息中间件 ) ?)
-
- [① 异步处理](#① 异步处理)
- [② 应用解耦](#② 应用解耦)
- [③ 流量削峰](#③ 流量削峰)
- [④ 分布式事务管理](#④ 分布式事务管理)
- [1.2 常用 "消息中间件" 介绍 :](#1.2 常用 "消息中间件" 介绍 :)
- [二、RabbitMQ 消息中间件](#二、RabbitMQ 消息中间件)
-
- [2.1 RabbitMQ "简介"](#2.1 RabbitMQ "简介")
- [2.2 RabbitMQ "工作模式介绍"](#2.2 RabbitMQ "工作模式介绍")
-
- [① Work queues 工作模式 ( "工作队列" 模式 ) - ( 适用于"较为繁重" , 可以进行 "拆分处理" 的 业务 )](#① Work queues 工作模式 ( "工作队列" 模式 ) - ( 适用于"较为繁重" , 可以进行 "拆分处理" 的 业务 ))
- [② Publish/Subscribe 工作模式 ( "发布订阅" 模式 ) - ( 适用于 "相同业务功能处理" 的 场合 )](#② Publish/Subscribe 工作模式 ( "发布订阅" 模式 ) - ( 适用于 "相同业务功能处理" 的 场合 ))
- [③ Routing 工作模式 ( "路由"模式 ) - ( 适用于 "不同类型消息"分类处理的 场合 )](#③ Routing 工作模式 ( "路由"模式 ) - ( 适用于 "不同类型消息"分类处理的 场合 ))
- [④ Topics工作模式 ( "通配符模式"模式 ) - ( 适用于 根据不同需求 "动态传递处理业务" 的场合 )](#④ Topics工作模式 ( "通配符模式"模式 ) - ( 适用于 根据不同需求 "动态传递处理业务" 的场合 ))
- [⑤ RPC工作模式 - ( 适用于 "分布式"架构的 "消息传递业务" / 适用于 "远程服务调用" 的业务场合 )](#⑤ RPC工作模式 - ( 适用于 "分布式"架构的 "消息传递业务" / 适用于 "远程服务调用" 的业务场合 ))
- [⑥ Headers工作模式](#⑥ Headers工作模式)
- [⑦ 总结](#⑦ 总结)
- [三、Erlang + RabbitMQ "安装"以及 "整合环境搭建" :](#三、Erlang + RabbitMQ "安装"以及 "整合环境搭建" :)
-
- [3.1 下载并安装 Erlang 和 RabbitMQ + RabbitMQ"可视化效果展示"](#3.1 下载并安装 Erlang 和 RabbitMQ + RabbitMQ"可视化效果展示")
- [3.2 Spring Boot "整合RabbitMQ" 环境搭建 :](#3.2 Spring Boot "整合RabbitMQ" 环境搭建 :)
-
- [① 创建Spring Boot 项目](#① 创建Spring Boot 项目)
- [② 配置文件中添加 "配置信息"](#② 配置文件中添加 "配置信息")
作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!
该文章参考学习教材 为:
《Spring Boot企业级开发教程》 黑马程序员 / 编著文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章
文章用于本人学习使用 , 同时希望能帮助大家。
欢迎大家点赞👍 收藏⭐ 关注💖哦!!!
(侵权可联系我,进行删除,如果雷同,纯属巧合)
- 在实际项目开发 中,有时候 需要与其他系统进行 集成完成相关业务功能 ,这种情况 最原始的做法 是 程序内部相互调用 ,除此之外 ,还可以使用 "消息服务中间件" 进行** 业务处理** ,使用消息服务中间件 处理业务能够提升系统 的 异步通信和 扩展解耦能力 。Spring Boot 对消息服务管理 提供了非常好的支持 。下面将针对 Spring Boot 消息服务 的 原理和 整合使用 进行详细讲解。
一、"消息服务" 概述 :
1.1 为什么要使用 "消息服务" ( 消息中间件 ) ?
在 多数应用尤其是 分布式系统中,** 消息服务是不可或缺的重要部分**,它使用 起来比较简单 同时解决了不少难题 ,例如 异步处理 、应用解耦 、流量削锋 、分布式事务管理等,使用消息服务 可以实现 一个高性能 、高可用 、高扩展的系统 。下面我们将通过实际开发中的** 若干场景来分析** 和说明 为什么要使用消息服务 ,以及使用消息服务的好处。
( 下面将通过 实际的场景来说明为什么要使用 "消息服务")
① 异步处理
- 场景说明 : 用户注册后 ,系统 需要 将信息写入数据库 ,并 发送 注册邮件和 注册短信通知。下面我们使用图示 的方式直观展示上述场景 的不同处理方式 ,如下图所示 :
在上图中 ,针对上述 注册业务 的 场景需求 ,处理方式有3种 ,如下所示 :
(1) 串行处理方式 : 用户发送注册请求后 ,服务器 会 先将注册信息写入数据库 ,依次发送注册邮件 和 短信消息 ,服务器只有
在"** 消息处理完毕** "后 才会将处理结果返回客户端 。这种 串行处理消息的 方式非常耗时,** 用户体验不友好**。(2) 并行处理方式 : 用户发送注册请求后 ,将注册信息写入数据库 ,同时发送注册邮件 和短信 ,最后返回给客户端 ,这种 并行处理的方式在一定程度上提高了后台业务处理 的效率 ,但如果遇到较为耗时 的业务处理 ,仍然显得不够完善。
(3) 消息服务处理方式 : 可以在 业务中嵌入消息服务 ( 消息中间件 )进行 业务处理,这种方式先将注册信息写入数据库,
在 极短的时间内** 将注册信息写入消息队列后** 即可 返回响应信息。此时前端业务不需要理会不相干 的后台业务处理,而发送注册邮件 和短信的业务 会 自动读取消息队列 中的 相关消息进行后续业务处理。
② 应用解耦
场景说明 : 用户下单后 ,订单服务需要** 通知库存服务** 。下面将使用图示 的方式直观展示上述需求的** 不同处理方式** ,如下图所示 :
在上图中 ,如果 使用 传统方式处理订单业务 ,用户下单后 ,订单服务会 直接调用库存服务接口 进行库存更新 ,这种方式 有一个很大的问题 是 : 一旦库存系统出现异常 ,订单服务 会 失败导致订单丢失。
如果 使用 消息服务模式 ( 消息中间件 ),订单服务的** 下订单消息会 快速写入消息队列** ,库存服务会** 监听并 读取到订单** ,从而修改库存 。相较于传统方式 ,消息服务模式显得更加** 高效** 、可靠。
③ 流量削峰
场景说明 : 秒杀活动是 流量削峰的一种** 应用场景** ,由于服务器处理资源能力有限 ,因此出现 峰值 时 很容易造成服务器宕机、** 用户无法访问的情况。为了 解决这个问题,通常会采用 消息队列 缓冲瞬时高峰流量** ,对请求 进行分层过滤,从而过滤掉一些请求 。如下图所示 :
针对上述秒杀业务的** 场景需求** ,如果专门增设服务器 来应对秒杀活动期间 的 请求瞬时高峰的话,在非秒杀活动期间 ,这些多余的服务器和配置 显得有些浪费 ;如果不进行有效处理的话 ,秒杀活动瞬时高峰流量请求 有可能压垮服务 ,因此,在秒杀活动 中加入 消息服务是较为理想的解决方案 。通过在应用前端 加入消息服务 ,先将所有请求写入 到消息队列,并限定一定的值 ,多余的请求直接返回秒杀失败 ,秒杀服务 会根据秒杀规则 从消息队列中读取并处理有限的秒杀请求。
④ 分布式事务管理
场景说明 : 在 分布式系统中,** 分布式事务是开发中必须要面对** 的技术难题 ,怎样保证分布式系统的 请求业务处理的** 数据一致性通常是要重点考虑的问题**。针对这种分布式事务管理 的情况 ,目前 较为可靠 的处理方式是基于消息队列 的 二次提交,在失败的情况 可以进行多次尝试 ,或者基于队列数据 进行回滚操作 。因此,在 分布式系统 中 加入消息服务 是一个 既能保证性能不变 ,又能保证业务一致性的方案 。
针对这种分布式事务处理的需求 ,下面将以 图示的方式** 展示使用消息服务的处理机制** ,如下图所示 :
针对上述分布式事务管理 的场景需求 ,如果使用传统方式 在订单系统中 写入订单支付成功信息 后,再 远程调用库存系统 进行库存更新 ,一旦库存系统异常 ,很有可能 导致库存更新失败 而 订单支付成功 的情况, 从而导致数据不一致。
针对这种分布式系统 的事务管理,通常会在 分布式系统之间加入** 消息服务进行 管理** 。在上图中,订单支付成功后 ,写入消息表 ;然后定时扫描消息表消息写入到消息队列中,** 库存系统会立即读取消息队列** 中的消息 进行库存更新 ,同时添加消息处理状态 ;接着,库存系统向 消息队列中 写入库存处理结果 ,订单系统会立即读取消息队列中的库存处理状态 。如果库存服务处理失败 ,订单服务还会重复扫描并发送消息表 中的消息 ,让 库存系统进行** 最终一致性的库存更新** 。如果处理成功 订单服务 直接删除消息表数据 ,并写入到历史消息表。
1.2 常用 "消息中间件" 介绍 :
消息队列中间件 ( 简称:消息中间件 ) 是指利用高效可靠 的 消息传递机制进行** 与平台无关的 数据交流** ,并基于 数据通信 来进行 分布式系统的集成。
常见的消息中间件有 : ActiveMQ、** RabbitMQ** 、Kafka 、RocketMQ 等。目前市面上的消息中间件各有侧重点 ,选择适合自己 、能够扬长避短 的无疑是最好的选择。
ActiveMQ ( 广泛应用于中小型企业 )
- ActiveMQ 是 Apache 公司出品的、采用 Java 语言编写的、完全基于 JMS 规范 ( java Message Service )的、面向消息的中间件,它为应用程序提供高效、可扩展的、稳定的、安全的企业级消息通信 。ActiveMQ 丰富的 API 和 多种集群构建模式 使得它成为业界老牌的消息中间件 ,广泛的**应用于中小型企业中。相较于后续出现的 RabbitMQ 、RocketMQ 、Kafka 等消息中间件来说, ActiveMQ 性能相对较弱**,在如今的 高并发 、大数据处理 的场景下 显得力不从心 ,经常会出现一些问题 , 例如 消息延迟 、堆积 、堵塞等 。
RabbitMQ ( 没有特别要求的场景下,常用"RabbitMQ中间件" )
- RabbitMQ 是使用 Erlang 语言开发 的 开源消息队列系统 ,基于 AMQP协议 ( Advanced Message Queuing Protocol ) 实现。AMQP 是为 应对大规模并发活动而 提供统一消息服务的 应用层标准高级消息队列协议,专门为** 面向消息的 中间件设计**,该协议** 更多用在企业系统内** ,对 数据一致性、稳定性 和 可靠性要求很高的 "场景" ,对 性能 和 吞吐量 的 要求还在其次 。正是 基于 AMQP协议 的 各种优势性能 ,使得 RabbitMQ 消息中间件在应用开发中越来越受欢迎。
Kafka ( "大数据业务" 可使用该中间件 )
- Kafka 是由 Apache 软件基金会 开发的一个 开源流处理平台 ,它是一种 高吞吐量 的 分布式发布订阅消息系统 ,采用 Scala 和 Java 语言编写,提供了快速 、可扩展 的、分布式 的、分区 的和可复制 的日志订阅服务 ,其主要特点是追求高吞吐量,适用于产生大量数据的互联网服务的数据
收集业务。
RocketMQ ( "大数据业务" 可使用该中间件 )
- RocketMQ 是 阿里巴巴公司开源产品 ,目前也是 Apache 公司 的顶级项目 ,使用 纯Java 开发 ,具有 高吞吐量 、高可用 、适合大规模分布式系统应用的特点。RocketMQ 的思路起源于 Kafka ,对消息的可靠传输 以及事务性 做了优化,目前在阿里巴巴中被广泛应用于 交易 、充值 、流计算消息推送 、日志流式处理场景 ,不过 维护上稍微麻烦。
实际开发中,选哪个中间件?
在 实际项目技术选型 时,
① 在 没有特别要求 的场景下,通常会选择使用 RabbitMQ作为** 消息中间件**,
② 如果 针对的是大数据业务,推荐使用 Kafka或者是 RocketMQ 作为** 消息中间件**。
二、RabbitMQ 消息中间件
2.1 RabbitMQ "简介"
RabbitMQ 是基于 AMQP 协议的** 轻量级** 、可靠 、可伸缩和** 可移植的 消息代理 ,Spring 使用RabbitMQ** 通过 AMQP 协议 进行 通信;在 Spring Boot 中对 RabbitMQ 进行了 集成管理 。在所有的消息服务 中,消息中间件都会作为一个** 第三方消息代理** ,接收发布者发布的消息 ,并推送给消息消费者 。不同消息中间件内部转换消息 的 细节不同。
RabbitMQ的 消息代理过程 如下图所示 :
(1) 消息发布者 ( Publisher ,简称P )向 RabbitMQ 代理 ( Broker ) 指定的 虚拟主机服务器 ( Virtual Host ) 发送消息 。
(2) 虚拟主机服务器内部的交换器 ( Exchange ,简称 X ) 接收消息 ,并将 消息传递并存储到与之 绑定 (Binding) 的 消息队列 (Queue )中。
(3) 消息消费者 ( Consumer ,简称 C )通过一定的** 网络连接** ( Connection )与 消息代理建立连接 ,同时为了 简化开支 ,在 连接内部使用了多路复用 的 信道( Channel ) 进行消息 的 最终消费。
2.2 RabbitMQ "工作模式介绍"
- RabbitMQ 消息中间件针对** 不同的服务需求** ,提供了 多种工作模式 。下面将对 RabbitMQ支持的** 工作模式和 工作原理进行简要说明**。
① Work queues 工作模式 ( "工作队列" 模式 ) - ( 适用于"较为繁重" , 可以进行 "拆分处理" 的 业务 )
参考 RabbitMQ 官方文档 ,Work queues 工作模式 的 流程示意图如下图所示 :
在 Work queues 工作模式中,** "不需要" 设置交换器** ( RabbitMQ 会使用内部默认交换器进行消息转换 ),需要指定 唯一的** 消息队列进行消息传递** ,并且可以有多个消息消费者。
在这种模式下 ,多个消息消费者 通过 轮询的方式 依次接收 消息队列 中 存储的消息,** 一旦消息被某一个消费者接收** ,消息队列会** 将消息 移除** ,而接收 并处理消息 的 消费者 必须在 消费完一条消息后再准备接收下一条消息 。从上面的分析可以发现 ,Work queues 工作模式 适用于那些** 较为繁重** ,并且可以 进行拆分处理的业务 ,这种情况下可以 分派给多个消费者轮流处理业务。
② Publish/Subscribe 工作模式 ( "发布订阅" 模式 ) - ( 适用于 "相同业务功能处理" 的 场合 )
参考 RabbitMQ 官方文档 ,Publish/Subscribe工作模式的** 流程示意图如下图所示** :
在 Publish/Subscribe 工作模式中,必须** 先配置一个 "fanout"类型 的 交换器** ,不需要指定对应的** 路由键** ( Routing key ),同时会 将消息路由 到每一个 消息队列 上,然后 每个消息队列都可以** 对相同的消息进行 接收存储** ,进而由 各自消息队列关联 的 消费者 进行 消费。
从上面的分析可以发现 ,Publish/Subscribe 工作模式适用于进行** 相同业务功能处理的场合** ,例如,用户注册成功后 ,需要同时发送邮件通知和 短信通知,那么** 邮件服务消费者** 和 短信服务消费者需要** 共同消费** "用户注册成功 " 这一条消息。
③ Routing 工作模式 ( "路由"模式 ) - ( 适用于 "不同类型消息"分类处理的 场合 )
参考 RabbitMQ 官方文档 ,Routing 工作模式的** 流程示意图如下图所示** :
在 Routing 工作模式中,必须** 先配置一个 "direct"类型 的 交换器** ,并 指定不同的** 路由键值** ( Routing key ) 将 对应的消息 从 交换器路由 到 不同的消息队列进行 存储,由** 消费者进行 各自消费**。
从上面的分析可以发现 ,Routing 工作模式 适用于进行 "不同类型消息" 分类处理的场合 。例如 日志收集处理 ,用户可以配置不同的路由键值分别对不同级别 的日志信息 进行分类处理。
④ Topics工作模式 ( "通配符模式"模式 ) - ( 适用于 根据不同需求 "动态传递处理业务" 的场合 )
参考 RabbitMQ 官方文档 ,Topics 工作模式的** 流程示意图如下图所示** :
在 Topics 工作模式 中,必须 先配置 一个 "topic"类型的 交换器,并** 指定不同的 路由键值** ( Routing key ) 将 对应的消息 从 交换器路由 到 不同的消息队列进行 存储,然后由** 消费者进行 各自消费**。
Topics 模式 与 Routing 模式 的 主要不同在于 : Topics 模式设置的** 路由键是 包含通配符的,其中#** 匹配 多个字符, *匹配 一个字符,然后与** 其他字符一起使用" .** " 进行连接,从而** 组成动态路由键** ,在 发送消息 时可以 根据需求设置不同 的 路由键 ,从而 将消息路由 到 不同的消息队列。
通常情况下 ,Topics 工作模式适用于** 根据不同需求 "动态传递处理业务"的场合** 。例如,一些订阅客户只接收邮件消息 ,一些订阅客户只接收短信消息 ,那么可以根据客户需求 进行 动态路由匹配 从而 将订阅消息分发到不同的消息队列 中。
⑤ RPC工作模式 - ( 适用于 "分布式"架构的 "消息传递业务" / 适用于 "远程服务调用" 的业务场合 )
参考 RabbitMQ 官方文档 ,RPC 工作模式的** 流程示意图如下图所示** :
RPC 工作模式 与 Work queues 工作模式主体流程** 相似** ,都 不需要设置交换器 , 需要指定唯一 的 消息队列 进行 消息传递。
RPC 工作模式与 Work queues 工作模式的** 主要不同在于 : RPC 模式是一个 回环结构**,主要针对** 分布式架构的 消息传递业务**,** 客户端 : Client 先发送消息** 到 消息队列 ,远程服务端 : Server 获取消息 ,然后 再写入另一个消息队列 ,向 原始客户端 : Client 响应 消息处理结果。
从上面的分析 可以发现,RPC 工作模式 适用于 远程服务调用的 业务处理场合。例如,在** 分布式架构中必须考虑的 分布式事务管理问题**。
⑥ Headers工作模式
- Headers 工作模式在 RabbitMQ 所支持的工作模式中是** 较为少用的一种模式** ,其主体流程 与 Routing 工作模式 有些相似 。不过,使用 Headers 工作模式时,** 必须设置一个 headers 类型的 交换器,而 不需要设置路由键** ,取而代之的是在 Properties 属性配置中的 headers 头信息中使用keyvalue 的形式配置路由规则 。由于 Headers 工作模式使用较少 ,官方文档也没有详细说明。
⑦ 总结
- 上面讲述 RabbitMQ 支持的** 6种工作模式及 原理,其中有些工作模式** 可以 嵌套使用 ,例如,在 发布订阅模式中加入** 工作队列模式** 。这里介绍的6种工作模式 中 Publish/Subscribe 、Routing 、Topics 和 RPC模式 是 开发中较为常用 的 工作模式。
三、Erlang + RabbitMQ "安装"以及 "整合环境搭建" :
3.1 下载并安装 Erlang 和 RabbitMQ + RabbitMQ"可视化效果展示"
RabbitMQ 支持多平台安装 ,例如 Linux 、Windows 、MacOS 、Docker等 。这里,我们以 Windows 环境为例,介绍 RabbitMQ 的安装配置。
第一步 :
下载并安装Erlang :原因 :RabbitMQ服务端代码是使用** 并发式语言Erlang编写** 的,安装Rabbit MQ 的 前提 : 是安装Erlang 。
( 安装Erlang语言包时,必须以** 管理员的身份进行 安装** 。) 下载地址 :http://www.erlang.org/downloads
第二步 :
① 系统环境中 新建变量 + ② 编辑path并在** 其中添加** "** ERLANG_HOME** " 这个 变量名 :
变量名 :ERLANG_HOME
变量值 :erlang 的安装地址① :
② : %ERLANG_HOME%\bin
检验 :
cmd控制台输入** erl** ,看到版本号 就说明erlang安装成功 :
第三步:
下载并安装RabbitMQ :
下载地址 :https://www.rabbitmq.com/百度网盘获取RabbitMQ软件 : https://pan.baidu.com/s/1-RFOp3Tr5_jj22RFgS7zpw?pwd=krnl
下载完后直接安装。
第四步 :
安装RabbitMQ-Plugins :rabbitmq-plugins enable rabbitmq_management
输入 rabbitmqctl status 检验是否安装成功。
第五步 :
运行RabbitMQ , 打开 sbin目录 ,双击 rabbitmq-server.bat ,后在浏览器访问访问 : http://localhost:15672 ,展示效果如下图所示 :
默认用户名和 密码都是 guest ,登录成功后会进入** RabbitMQ可视化管理页面的 首页** 。
( RabbitMQ 默认提供了** 两个端口号** : 5672和 15672 ,其中 5672 用作** 服务端口号** ,15672用作** 可视化管理端口号**。)
3.2 Spring Boot "整合RabbitMQ" 环境搭建 :
① 创建Spring Boot 项目
创建项目 :
② 配置文件中添加 "配置信息"
- 配置文件中添加 "** 配置信息**" :
properties#配置RabbitMQ消息中间件的"连接配置" spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest #配置RabbitMQ虚拟主机路径/ , 默认可省略 spring.rabbitmq.virtual-host=/
连接的 RabbitMQ服务端口号为 : 5672 , 并使用** 默认用户guest连接**。