(2)RabbitMQ架构设计与应用场景
1.什么是消息中间件?
消息是指应用间传输的数据。消息体包括文本字符串、Json、内嵌对象等。
消息中间件是基于队列模型实现异步和同步传输数据的。
作用:解耦,冗余(存储)、扩展性、削峰、可恢复性、顺序保证、缓冲、异步通信。通俗点来说就是支持支撑高并发、异步解耦、流量削峰、降低耦合度。
2. AMQP是什么?
AMQP(Advanced Message Queuing Protocol,高级消息队列协议)是一个进程间传递异步消息的网络协议。
RabbitMQ是遵从AMQP协议的,而RabbitMQ的模型架构又和AMQP的模型架构是一样的。
AMQP实体模型如下:
工作原理如下:
生产者(Publisher)将消息发送给交换器,交换器和队列绑定。当生产者发送消息时所携带的RoutingKey与绑定时的BindingKey相匹配时,消息即被存入相应的队列之中,消费者可以订阅相应的队列来获取消息。
3.RabbitMQ相关概念
RabbitMQ实体模型如下:
在了解完上图RabbitMQ模型后,现在让我们来看看RabbitMQ运转流程:
●生产者推送消息:
(1)生产者连接到RabbitMQ的Broker建立一个连接(Connection),开启一个信道(Channel)。
(2)生产者声明一个交换器,并设置相关属性,比如交换机类型、是否持久化等。
(3)生产者声明一个队列并设置相关属性,比如是否排他、是否持久化、是否自动删除等。
(4)生产者通过路由键将交换器和队列绑定起来。
(5)生产者发送消息至RabbitMQ的Broker,其中包含路由键、交换器等信息。
(6)相应的交换器根据接收到的路由键查找相匹配的队列。
(7)如果找到,则将从生产者发送过来的消息存入相应的队列中。
(8)如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者。
(9)关闭信道。
(10)关闭连接。
●消费者接收消息:
(1)消费者连接到RabbitMQ的Broker,建立一个连接(Connection),开启一个信道(Channel)。
(2)消费者向RabbitMQ的Broker请求消费相应队列中的消息,可能会设置相应的回调函数,以及做些准备工作(推拉模式)。
(3)等待RabbitMQ的Broker回应并投递相应队列中的消息,消费者接收消息。
(4)消费者确认(ack)接收到的消息。
(5) RabbitMQ从队列中删除相应己经被确认的消息。
(6)关闭信道。
(7)关闭连接。
注:上述有两个概念可以了解下,分别是信道(Channel)与连接(Connection),我们知道无论是生产者还是消费者,都需要和RabbitMQ的Broker建立连接,这个连接就是一条TCP连接,也就是Connection的TCP连接建立起来,客户端紧接着可以创建一个AMQP信道(Channel),每个信道都会被指派一个唯一的ID。Channel是建立在Connection之上的虚拟连接,RabbitMQ处理的每条AMQP指令都是通过信道完成的。如图所示:
*这里大伙可能会有一个疑问,为什么Connection能完成Channel连接工作,还要引入Channel呢?
试想这样一个场景,一个应用程序中有很多个线程需要从RabbitMQ中消费消息或者生产消息,那么必然需要建立很多个Connection,也就是许多个TCP连接。然而对于操作系统而言,建立和销毁TCP连接是非常昂贵的开销,如果遇到使用高峰,性能瓶颈也随之显现。RabbitMQ采用类似NIO1(Non-blocking 1/0)的做法,选择TCP连接复用,不仅可以减少性能开销,同时也便于管理。
*NIO1,也称非阻塞(I/O),包含三大核心部分Channel(信道)、Buffer(缓冲区)和Selector(选择器)。NIO基于channel和Buffer进行操作,总是从信道读取数据到缓冲区中,或者从缓冲区写入到信道中。Selector用于监听多个信道的事件(比如连接打开,数据到达等)。因此,单线程可以监听多个数据的信道。NIO1中有个很有名的Reactor模式,有兴趣小伙伴可以去阅读下,这里就不详解了。
*每个线程分别把持一个信道,所以信道复用了Connection TCP连接。同时RabbitMQ可以确保每个线程的私密性,就像拥有独立的连接一样。当每个信道的流量不是很大时,复用单一的Connection可以在产生性能瓶颈的情况下有效地节TCP连接资源。但是当信道本身的流量很大时,这时候多个信道复用一个Connection就会产生性能瓶颈,进而使整体的流量被限制了。此时就需要开辟多Connection,将这些信道均摊到这些Connection中,至于这些相关的调优策略需要根据业务自身的实际情况进行调节。
下面让我们来了解下实体中每个角色模型。
●Producer(生产者):投递消息到服务端的一方。投递消息分为两部分:消息体(payload)和标签(label)。
◎消息体:一般是带有业务逻辑结构的数据,例如一个json数据。
◎标签:消息的标签是用来表述这条消息,例如一个交换器名称跟路由键。
●Broker(代理):MQ服务节点。也可以看作一个实例,或者一台RabbitMQ服务器。
●Exchange(交换器):生产者将消息投递到队列中,实际是将消息投递到交换器,由其路由到一个或者多个队列当中。如果路由不到,会返回给生产者或者丢弃。交换器包含路由键(RoutingKey)和绑定键(BindingKey),还有四种类型,后面会重点介绍。
◎路由键:生产者投递消息给交换器时会指定一个路由键,用作路由规则来决定消息的流向。
◎绑定键:交换器跟队列是通过一个绑定键关联的,这样Rabbitmq才能正确把消息投递到相关队列去。如图所示:
从上图可知道,交换器相当于投递包裹的邮箱,路由键当于填写在包裹上的地址,绑定键当于包裹目的地,当填写在包裹上地址和实际想要投递的地相匹配时,那么这个包裹才会被正确投递到目的地,最后这个目的地的“收件人”(队列)才可以保留这个包裹。如果填写的地址有错,邮递员不能正确投递到目的地,那么包裹可能会回退给“寄件人”(生产者),或者可能会被丢弃。其实在某些情形下路由键和绑定键可以看作同一个东西。
●Queue(队列):用于存储消息。遵循先进先出,后进后出原则。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin),即轮询给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
4.为什么要用到MQ?
4.1传统Http请求缺点
●传统Http请求是基于请求与响应的模型下进行的,在高并发的情况下,客户端会发送大量的请求达到服务器端,这样有可能会导致我们服务器端要处理大量堆积请求,增加服务器压力。
●像Window IIS服务器(IIS线程池)处理每个请求都有自己独立的线程,如果超过最大线程数,IIS的w3wp进程不会再将http.sys的队列中的请求去线程池中调用线程处理,如果请求堆积过多的情况下,有可能会导致服务器崩溃。所以一般都会在nginx入口实现限流。
●http请求处理比较耗时的业务逻辑情况下,容易造成客户端(Client)一直等待,阻塞等待过程中会导致客户端超时发生重试策略,有可能会引发幂等性问题。
总结:综合以上Http请求缺点,如果接口是为Http协议的情况下,最好不要处理比较耗时的业务逻辑,耗时的业务逻辑应该单独交给多线程或者是mq去处理。
4.2MQ应用场景
结合上述总结可以知道,在处理Http请求比较耗时业务时,可以交给多线程或者是mq去处理,下面我们结合常见用户注册应用场景来解释这两者区别:
如上图所示,客户端发起一个注册用户请求,处理业务逻辑如下:
(1)InsertUser(插入用户信息),需要1秒处理时间。
(2)SendEmail(发送邮件),需要2秒处理时间。
(3)SendCoupons(发送优惠卷),需要3秒处理时间。
按照上述串行处理流程,该功能处理时间总共为6秒,这意味着用户需要等待6秒,这种用户体验是非常差的。下面再来看看多线程跟MQ如何处理这些业务逻辑。
●多线程处理
如上图所示,客户端发起一个注册用户请求到服务端后,插入用户信息同时开启一个线程处理发送邮件和优惠卷,当插入用户信息成功后立即响应状态给客户端,所以整个过程只花费1秒处理时间。
◎优点:适合小型项目,实现异步处理。
◎缺点:消耗服务器CPU资源,没有解耦。
●MQ处理
如上图所示,客户端发起一个注册用户请求到服务端后,插入用户信息同时往MQ投递一个消息处理发送邮件和优惠卷,当插入用户信息成功后立即响应给客户端,所以整个过程只花费1秒处理时间。
◎优点:适合中大型项目,实现异步处理,流量削峰、降低耦合度。
◎缺点:增加系统复杂度。
5.主流MQ区别对比
特性 |
ActiveMQ |
RabbitMQ |
RocketMQ |
Kafka |
开发语言 |
java |
erlang |
java |
scala |
单机吞吐量 |
万级 |
万级 |
10万级 |
10万级 |
时效性 |
ms级 |
us级 |
ms级 |
ms级以内 |
可用性 |
高(主从架构) |
高(主从架构) |
非常高(分布式架构) |
非常高(分布式架构) |
功能特性 |
成熟的产品,在很多公司得到应用,有较多的文档,各种协议支持较好。 |
基于erlang开发,所以并发能力很强,性能极其好,延时很低管理界面较丰富。 |
MQ功能比较完备,扩展性佳。 |
只支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域应用广。 |
参考文献:
RabbitMQ实战指南
(2)RabbitMQ架构设计与应用场景的更多相关文章
- TYPESDK手游聚合SDK服务端设计思路与架构之一:应用场景分析
TYPESDK 服务端设计思路与架构之一:应用场景分析 作为一个渠道SDK统一接入框架,TYPESDK从一开始,所面对的需求场景就是多款游戏,通过一个统一的SDK服务端,能够同时接入几十个甚至几百个各 ...
- 亿级流量场景下,大型架构设计实现【2】---storm篇
承接之前的博:亿级流量场景下,大型缓存架构设计实现 续写本博客: ****************** start: 接下来,我们是要讲解商品详情页缓存架构,缓存预热和解决方案,缓存预热可能导致整个系 ...
- 亿级流量场景下,大型缓存架构设计实现【1】---redis篇
*****************开篇介绍**************** -------------------------------------------------------------- ...
- 聊聊Zookeeper应用场景、架构设计、选主机制
Zookeeper作为一个分布式协调系统提供了一项基本服务:分布式锁服务,分布式锁是分布式协调技术实现的核心内容.像配置管理.任务分发.组服务.分布式消息队列.分布式通知/协调等,这些应用实际上都是基 ...
- 两年内从零到每月十亿 PV 的发展来谈 Pinterest 的架构设计(转)
原文:Scaling Pinterest - From 0 To 10s Of Billions Of Page Views A Month In Two Years 译文:两年内从零到每月十亿 PV ...
- EF6多线程与分库架构设计之Repository
1.项目背景 这里简单介绍一下项目需求背景,之前公司的项目基于EF++Repository+UnitOfWork的框架设计的,其中涉及到的技术有RabbitMq消息队列,Autofac依赖注入等常用的 ...
- EF6的多线程与分库架构设计实现
1.项目背景 这里简单介绍一下项目需求背景,之前公司的项目基于EF++Repository+UnitOfWork的框架设计的,其中涉及到的技术有RabbitMq消息队列,Autofac依赖注入等常用的 ...
- .net core实践系列之短信服务-架构设计
前言 上篇<.net core实践系列之短信服务-为什么选择.net core(开篇)>简单的介绍了(水了一篇).net core.这次针对短信服务的架构设计和技术栈的简析. 源码地址:h ...
- 架构设计:系统间通信(20)——MQ:消息协议(下)
(接上文<架构设计:系统间通信(19)--MQ:消息协议(上)>) 上篇文章中我们重点讨论了"协议"的重要性.并为各位读者介绍了Stomp协议和XMPP协议. 这两种协 ...
随机推荐
- UDP&串口调试助手用法(3)
发送参数配置 下面以 UDP 通道为例介绍 发送数据配置 概览 选择数据源 文件: 选择发送的文件 源码: 自己手动键入发送数据,默认输入的为16进制数据, 定时器发送周期 单位为毫秒. 发送帧计数 ...
- 【LeetCode】45. Jump Game II 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 贪心 日期 题目地址:https://leetcod ...
- 【LeetCode】946. Validate Stack Sequences 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 模拟过程 日期 题目地址:https://leetc ...
- 【LeetCode】650. 2 Keys Keyboard 只有两个键的键盘(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 素数分解 日期 题目地址:https://le ...
- 1131 - Just Two Functions
1131 - Just Two Functions PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 ...
- 1054 - Efficient Pseudo Code
1054 - Efficient Pseudo Code PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: ...
- 带SD读卡的USB HUB方案芯片MA8621|用于带读卡的USB HUB拓展坞方案芯片MA8621
MA8621是一款带SD读卡器控制器的USB 2.0高速3端口集线器方案芯片,主要用在USB TYPEC拓展坞或者USB typec扩展底座上面. 1. MA8621功能概述 MA8621是USB 2 ...
- markdownpad 2 pro版本(注册码)
简介 markdown – 一种轻量级文本标记语言,当今程序员必备技能markdownpad -- windows平台下好用的markdown编辑器 官网下载地址:http://www.markdow ...
- SpringBoot集成MyBatis-Plus框架详细方法
1.说明 本文详细介绍Spring Boot集成MyBatis-Plus框架的方法, 使用MySQL数据库进行测试, 包括完整的开发到测试步骤, 从一开始的Spring Boot工程创建, 到MySQ ...
- PaperRead - Comparison of Fundamental Mesh Smoothing Algorithms for Medical Surface Models
几种常见平滑算法的实现可以参见: 几种网格平滑算法的实现 - Jumanco&Hide - 博客园 (cnblogs.com) 1 Introduction 图像空间中相关的组织和结构,变换成 ...