rabbitmq的构架和原理(三)

时间:2022-12-11 14:15:58

前言

前面博文已经将安装配置和站点管理介绍了,现在开始正式学习rabbitmq的使用了;

rabbitMQ的构架

rabbitmq作为消息队列,一条消息从发布到订阅消费的完整流程为:

消息   -->  交换机exchange  ---> 队列queue  --->  消费者

rabbitmq的核心就在交换机和队列

使用流程

发布者(推送消息的一端):

  1. 创建一个tcp长连接connection,连接rabbitmq的监听端口5672;

  2. 在TCP长连接下创建一个信道channel,信道可以理解为connection的一个分支;

  3. 通过信道向rabbitmq声明一个交换机exchange,设置交换机的类型,名称,是否持久化等属性;

  4. 通过信道向rabbitmq声明一个队列queue,设置队列的名称,是否持久化等参数;

  5. 通过信道向rabbitmq声明一个绑定binding,设置绑定的交换机名称,队列名称,绑定的路由键;

  6. 通过信道向rabbitmq推送一条消息,指定交换机和路由;

消费者(接收消息的一端):

  1. 从第一步到第四步和发布者做的事情是一模一样的,如果已经存在相应的exchange、queue等则跳过;

  2. 通过信道向rabbitmq声明一个订阅,订阅特定的queue,并且设置回调函数及是否确认等;

  3. 通过信道监听rabbitmq推送过来的消息;

深入理解

创建连接connection

  • rabbitmq实现的是AMQP通信协议,其所允许的最大AMQP连接数,本质上是TCP连接数;

  • 采用TCP长连接,自带SSL认证机制,类似https,保证数据的传输安全;

  • 其TCP连接的上限可以通过调整操作系统的限制来变更,详情linux修改TCP最大连接数

创建信道channel

  • 信道channel可以理解成是connection下的分支,也就是说多个channel共享一个connection,为什么要这么做呢?

  • 创建TCP连接是一个非常耗时的操作,如果一个应用需要多个connection的话,每次的创建和关闭会性能降低,而创建多个channel共享一个connection提高性能,节约系统资源;

  • 多个channel是相互独立隔离的,这导致了一个问题就是,由于主机只能识别不同的TCP连接,但不能识别不同的信道发送过来的消息,因此rabbitmq为每个创建的信道分配了一个信道ID用来识别不同信道发送的消息;

  • 每个信道都是为独立的进程或线程准备的,因此多线程或多进程共享信道是不被允许的;

  • 在一个TCP下可创建的chnnel的数量理论上是没有上限的,只取决于系统资源,但可以通过配置channel_max参数设置上限;

声明交换机exchange

  • 作用:交换机使用来管理分发消息的,一边接受发布者提交的消息,根据消息提供的参数选择相应的处理办法,交换机是不会存储消息的,只有转发或丢弃功能;

  • 如果消息携带的路由键没有对应的路由队列,交换机会将消息丢弃;

声明交换机时的重要属性:

name:名称,必须唯一;
type:类型,共有四种,默认direct;
Durability:是否持久化,默认否;
Auto delete:是否自动删除;
Internal:是否是内部交换机,默认否;
Arguments:设置额外的参数;

交换机的类型

直连交换机direct

  • 顾名思义直连交换机根据消息携带的路由键将该消息投递到绑定的队列;

  • 如果有多个队列使用相同的路由键和直连交换机绑定,那么直连交换机会将消息同时转发到多个队列;

  • rabbitmq本身存在默认交换机,默认交换机的本质就是名称为空的直连交换机,当任何一个新的队列被声明的时候,rabbitmq会使用这个队列的名字作为路由键自动绑定默认交换机;

  • 通过rabbitmqctl list_exchanges命令查看所有的交换机,可以看到有一个名称为空的direct;

扇形交换机funout

  • 作用:扇形交换机会将消息推送到绑定的所有的队列中,不会理会路由键是什么;

  • 在声明funout和队列绑定的时候,也有一个路由键参数,但是写什么都无所谓,funout会将其忽略的;

主题交换机topic

  • 作用:主题交换机使用比较复杂的路由键匹配规则实现一路或多路路由;

路由键规则:

  • 使用.分割的词语列表,也可以是单个词语,长度不能超过255个字节;

  • *号用来匹配一个单词,这个单词不能为空,#号用来匹配0个或多个单词;

user.*  用来匹配所有绑定了以user开头并且使用了两个单词的路由键;
user.# 用来匹配所有绑定了以user开头并且使用了一个以上单词的所有路由键;

头交换机headers

  • 通过判断消息中携带的额外的属性来分发消息给对应的队列,性质和直连交换机很相似;

  • 其区别在于使用消息的属性替换路由键作为路由的规则;

注意

  • 每个交换机的名字是唯一的,如果重复声明交换机并且声明的参数完全一样,那么mq会忽略该声明;

  • 如果声明交换机已经存在,但修改了它的属性,比如类型或持久化等,那么会报错;所以修改的方法是先删除原来的交换机再创建一个新的交换机;

队列queue

  • queue用来缓存消息,并向消费者推送消息;

  • 声明队列的名称最多255个字节,可以是任意字符串;

  • 如果声明时名字为空,mq会随机生成一个名字;

  • 声明队列不可以用amq.开头,否则报错, amq.是rabbitmq内部使用的默认队列;

  • 如果多个消费者订阅同一个队列的消息,那么队列会用轮询的方式推送消息,这种方式可以实现负载均衡;

注意:

  • 每个队列的名字是唯一的,如果重复声明交换机并且声明的参数完全一样,那么mq会忽略该声明;

  • 如果声明的该队列已经存在,但修改了它的属性,比如类型或持久化等,那么会报错;所以修改的方法是先删除原来的队列再创建一个新的队列;

消息订阅

  • 消费者可以向队列订阅消息,每个消费者都会被分配一个标志符;

  • 订阅时可以设置消费回执,告诉mq什么时候可以将消息删除了,默认是自动删除的;

  • 消费者也可以向mq发送 拒绝消息 ,这时消息会被放回队列等待投递到其他的消费者;

  • 消费者订阅的时候可以设置预取计数,当存在多个消费者共同订阅一个队列的时候,由于是轮询机制,但每个消费者的消费能力可能是不一样的,这可能造成有的消费者闲的要死,有的忙的要死,设置预取数量,在没有收到回执确认前,该队列推送的消息是有限的,可以提高整体的吞吐量;

消息,交换机,队列的持久化

  • 消息持久化是在消息投递前定义的,设置了持久化后,消息会被保存在磁盘,当被消费后会从磁盘中删除,但是也不能保证100%持久化成功,因为消息是先放到内存中的,如果此时主机崩溃,还是会有一部分来不及写入磁盘;

  • 交换机持久化是在声明该交换机的时候设置的,当主机崩溃或重启后,mq一重新上线会自动重新声明一个和原来完全一样的交换机;

  • 队列持久化是在队列被声明的时候设置的,mq重新上线会自动重新声明一个和原来完全一样的queue,但是队列里的消息会全部丢失;

参考

rabbitmq的构架和原理(三)的更多相关文章

  1. rabbitmq之核心构架和原理总结(四)

    前言 前面博文已经将安装配置和站点管理介绍了,现在开始正式学习rabbitmq的使用了: rabbitMQ的构架 rabbitmq作为消息队列,一条消息从发布到订阅消费的完整流程为: 消息 --&gt ...

  2. 跟vczh看实例学编译原理——三:Tinymoe与无歧义语法分析

    文章中引用的代码均来自https://github.com/vczh/tinymoe.   看了前面的三篇文章,大家应该基本对Tinymoe的代码有一个初步的感觉了.在正确分析"print ...

  3. word2vec原理(三) 基于Negative Sampling的模型

    word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...

  4. RabbitMQ基本概念和原理

    RabbitMQ基本概念和原理 1.AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计. 2.Rabb ...

  5. 并发之AQS原理(三) 如何保证并发

    并发之AQS原理(三) 如何保证并发 1. 如何保证并发 AbstractQueuedSynchronizer 维护了一个state(代表了共享资源)和一个FIFO线程等待队列(多线程竞争资源被阻塞时 ...

  6. RabbitMQ的构架

    初识rabbitMQ RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现. AMQP :Advanced Message Queue,高级消息队列协议.它是应用层协议的一个开放 ...

  7. Vue项目搭建及原理三

    我每次写博客都要先在本地写一遍草稿,所以之前有些发布顺序可能会有一丢丢凌乱 哈哈哈,以后绝对改正,那下面我们就说一下创建及项目目录结构吧 三.创建项目 1.初始化Webpack p.p1 { marg ...

  8. 【c#】RabbitMQ学习文档(三)Publish/Subscribe(发布/订阅)

    (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个任务会被交付给一个[工人].在这一部分我们将做一些完全不同的事情--我们将向多个 ...

  9. socket通信原理三次握手和四次握手详解

    对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1.         什么是TCP/IP.UDP?2.         Sock ...

随机推荐

  1. sh4.case语句

    case ... esac 与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构.case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令.case语句格式如下: ...

  2. 会场安排问题--nyoj题目14

    会场安排问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办.小刘的工 ...

  3. android 推断应用程序是系统程序还是用户程序

    直接上代码: AppInfo.java <span style="font-size:18px;">package com.example.packages; publ ...

  4. CSS背景图片定位

    原文:CSS背景图片定位 在网页开发中我们经常需要对图片进行分割(如下图)来使用,而不是分别提供单独的图片来调用,常见的如页面背景,按钮图标等,这样做的好处就是减少请求次数,节省时间和带宽. 对背景图 ...

  5. 【LeetCode】327&period; Count of Range Sum

    题目: Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusiv ...

  6. 在thinkphp框架中使用后台传值过来的数组,在hightcart中使用数组

    js的数组是和php里面数组是不一样的,所以模板文件需要先接受,然后利用Js代码转化之后再使用,接受后台的数组有几种办法 1.后台传过来的json数组,利用Js是可以接受的,然后将json数据利用js ...

  7. net core体系-3再次认识net core

    1 什么是ASP.NET Core ASP.NET Core 是一个全新的开源.跨平台框架,可以用它来构建基于网络连接的现代云应用程序,比如:Web 应用,IoT(Internet Of Things ...

  8. ZOJ 3827 Information Entropy 水

    水 Information Entropy Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Informati ...

  9. 在linux下 用p7zip 命令行下 解压 iso文件

    todo tomorrorw! 在linux下可以通过 mount IOSFILE.iso /media/myiso/ -o loop 这种方式挂载,然后直接从 目录中拷贝 iso的内容出来就可以. ...

  10. fdisk命令详解

    基础命令学习目录 原文链接:https://www.cnblogs.com/xiaofengkang/archive/2011/06/06/2073579.html fdisk -l 可以列出所有的分 ...

相关文章