前言

前面博文已经将安装配置和站点管理介绍了,现在开始正式学习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. 深入理解Kafka核心设计及原理(四):主题管理

    转载请注明出处:https://www.cnblogs.com/zjdxr-up/p/16124354.html 目录: 4.1创建主题 4.2 优先副本的选举 4.3 分区重分配 4.4 如何选择合 ...

  2. 深入理解Kafka核心设计及原理(五):消息存储

    转载请注明出处:https://www.cnblogs.com/zjdxr-up/p/16127749.html 目录: 5.1文件目录布局 5.2消息压缩 5.3日志索引 5.4日志文件及索引文件分 ...

  3. rabbitmq的构架和原理(三)

    前面两篇博文已经将环境安装和相关配置介绍了,现在开始正式学习rabbitmq的使用了: rabbitMQ的构架 rabbitmq作为消息队列,一条消息从发布到订阅消费的完整流程为: 消息 --> ...

  4. struts2的核心和工作原理

    struts2的核心和工作原理 设计目标 Struts设计的第一目标就是使MVC模式应用于web程序设计.技术优势 Struts2有两方面的技术优势,一是所有的Struts2应用程序都是基于clien ...

  5. MFC原理第四讲.动态创建机制

    MFC原理第四讲.动态创建机制 一丶要学习的知识点以及简介 动态创建是什么意思? 动态创建其实就是跟C++的new一样.都是创建对象.但是规避了C++语法的缺陷. 例如: char * ClassNa ...

  6. JVM 内部原理(四)— 基本概念之 JVM 结构

    JVM 内部原理(四)- 基本概念之 JVM 结构 介绍 版本:Java SE 7 每位使用 Java 的程序员都知道 Java 字节码在 Java 运行时(JRE - Java Runtime En ...

  7. 动态替换Linux核心函数的原理和实现

    转载:https://www.ibm.com/developerworks/cn/linux/l-knldebug/ 动态替换Linux核心函数的原理和实现 在调试Linux核心模块时,有时需要能够实 ...

  8. 转 Spring源码剖析——核心IOC容器原理

    Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...

  9. 002/区块链核心概念与原理详解(Mooc)

    1.课程介绍 (一).区块链前世今生 密码朋克--神秘组织(邮件组) 2.区块链核心概念与原理 (一)比特币是数字货币 为什么叫区块链? 因为比特币系统里面的数据是一个个的区块来存储,并且通过hash ...

随机推荐

  1. wpf拖拽

    简单拖拽的实现是,实现源控件的MouseDown事件,和目标控件Drop事件.调用DragDrop.DoDragDrop()以启动拖放操作,DragDrop.DoDragDrop()函数接受三个参数: ...

  2. mac终端命令-----常规操作

    OSX 的文件系统 OSX 采用的Unix文件系统,所有文件都挂在跟目录 / 下面,所以不在要有Windows 下的盘符概念. 你在桌面上看到的硬盘都挂在 /Volumes 下. 比如接上个叫做 US ...

  3. Python 文件对象和方法

    Python文件对象和方法 1.打开和关闭文件 Python提供了必要的函数和方法进行默认情况下的文件基本操作,我们可以用file对象做大部分文件操作. open()方法 我们必须先用Python内置 ...

  4. 51nod 1385凑数字(字符串+构造)

    题目大意: 给定一个n,要求找出一个最短的字符串S,使得所有1到n的整数都是S的子序列. 比如n=10,那么S=”1234056789”的时候,是满足条件的.这个时候S的长度是10. 现在给出一个n, ...

  5. VS2017常用快快捷键

    VS2017常用快快捷键 VS中代码对齐等快捷键        在VS中,选定代码后,按Ctrl+K+F组合键,可以自动进行代码对齐.        注意:要先按下Ctrl和K,再按下F,因为Ctrl ...

  6. bzoj 3132: 上帝造题的七分钟 (二维树状数组)

    推推公式,最后变成四个东西的前缀和 然后不知道为什么一直wa,数据在本地测是没有错的& 好心的管理员还给了某位p党大神a了的代码,感人肺腑(虽然还是没发现到底我的程序是问题) var f1,f ...

  7. 那些常用的JS命令

    window.location.reload()刷新当前页面. parent.location.reload()刷新父亲对象(用于框架) opener.location.reload()刷新父窗口对象 ...

  8. lamp 源码安装

    #!/bin/bash #description:mysql-.tar apache2.4.23 php5.6.27 function check_ok(){ ] then echo "-- ...

  9. linux安装卸载MySQL以及密码设置+Hive测试

    linux系统卸载MYSQL 1,先通过yum方式卸载mysql及相关组件 命令:yum remove mysql* 2.通过命令:rpm -qa|grep -i mysql 查找系统的有关于mysq ...

  10. bzoj1178 [Apio2009]CONVENTION会议中心 区间dp+贪心

    [Apio2009]CONVENTION会议中心 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1130  Solved: 444[Submit][S ...