1、消息中间件

  消息队列中间件是指利用高效可靠地消息传递机制传递消息。有两种传递模式:点对点模式、发布/订阅模式。流行的消息中间件有RabblitMQ、Kafka、RockerMQ。它们都提供了基于存储和转发的应用程序之间的异步数据发送,即应用程序彼此不直接通信,而是与作为中介的消息中间件通信。

2、组成部分

  RabbitMQ的整体模型架构如图。RabbitMQ的组成由 生产者、交换器、绑定、队列、消费者组成。

2.1 Server(broker)

   接受客户端连接,实现AMQP消息队列和路由功能的进程。

2.2 Virtual Host

  其实是一个虚拟概念,类似于权限控制组,一个Virtual Host里面可以有若干个Exchange和Queue,但是权限控制的最小粒度是Virtual Host

2.3 连接

  生产者和消费者都需要和RabbitMQ Broker建立连接,连接是TCP连接。一旦TCP连接建立起来,客户端紧接着创建一个AMQP信道(Channel)。信道是建立在TCP Connection之上的虚拟连接,RabbitMQ处理每条AMQP指令都是通过信道完成的。因为建立和销毁TCP连接开销大,所以选择TCP连接复用,减少开销。

  

2.4 生产者和消费者

  生产者:创造消息,发布到RabbitMQ中。消息包含两个部分:标签和消息体。标签是为了描述这条消息,生产者把消息交由RabbitMQ之后会根据标签把消息发送给感兴趣的消费者。在消息路由的过程中,消息的标签会丢弃,存入到队列中的消息只有消息体,

  消费者:接受消息。消费者连接到RabbitMQ 服务器,并订阅到队列上。消费者只能得到消息体,也就不知道消息的生产者是谁。

2.5 绑定和路由键

  路由键:生产者将消息发送给交换器的时候,指定RoutingKey.

  绑定键:通过绑定键将交换器和队列联系起来。如下图

2.6 交换器

  生产者将消息发送到交换器,由交换器将消息路由到一个或多个对列中。如果路由不到,直接丢弃消息或者返回给生产者。队列是生产者和消费者传递消息的一个中介,所有消息都必须通过交换器将消息放入队列中,不能直接将消息放到队列中。

  交换器类型:  

Fanout:会将所有发送到交换器的消息路由到所有与改交换器绑定的队列中。这种情况BingKey和RoutingKey相当于不起作用。

Direct:会把消息路由到BindingKey和RoutingKey完全匹配的队列中。如下图 消息只会进入队列一中。

  

Topic:会按照一定规则将BindingKey和RoutingKey相匹配的队列中。BindingKey可以存在两种特殊字符串"*"和"#"。“#”号用于匹配一个单词,“*”匹配多个单词。

  

Headers:Headers类型的交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。

路由键、交换器类型、绑定键三者共同决定了消息进入哪些队列中。

2.7 队列  

用于存储消息。RabbitMQ中消息只能存储在队列后中。多个消费者可以订阅同一个队列,队列中的消息会被平均分摊给多个消费者。RabbitMQ 不支持队列层面的广播消费。

附上一张完整的结构图:

3、消息确认

  在生产者发送消息到消费者消费消息的流程中,有两个地方需要消费确认:

  1. 生产者要确认发出的消息到达RabbitMQ。
  2. 消息从队列到达消费者的过程。队列要确认发出的消息被消费者消费,才会将消息从队列中删除。

  为了保证,生产者的消息到达RabbitMQ,可以通过事务机制和发送方确认机制实现。

  事务实现:

    Channel.TxSelect 将当前信道设置成事务模式

    Channel.TxCommit 提交事务

    Channel.TxRollback 事务回滚

  发送方确认机制:

   生产者将信道设置成confirm(确认)模式,一旦信道进入confirm模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从l开始),一旦消息被投递到所有匹配的队列之后,RabbitMQ 就会发送一个确认(Basic.Ack) 给生产者(包含消息的唯一ID) ,这就使得生产者知晓消息已经正确到达了目的地了(如上图的流程1)。如果消息和队列是可持久化的,那么确认消息会在消息写入磁盘之后发出。

   生产者调用channel.ConfirmSelect将信道设置为confirm模式,事务机制和Publisher confirm机制确保的是消息能够正确地发送至RabbitMQ,这里的“发送至RabbitMQ”的含义指消息被正确地发送到交换器。

   事务机制在一条消息发送之后会使发送端阻塞,以等待RabbitMQ 的回应,之后才能继续发送下一条消息。相比之下, 发送方确认机制最大的好处在于它是异步的,一旦发布一条消息,生产者应用程序就可以在等信道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者应用程序便可以通过回调方法来处理该确认消息。

为了保证,队列中发出的消息被消费者消费,RabbitMQ提供了消息确认机制。

  消费者订阅队列时,可以指定autoAck参数,autoAck等于false,RabbitMQ会等待消费者显示地回复确认信号才能从队列后中删除(如上图的流程2)。autoAck等于true,会在消息发送去后删除,不管消费者是否真正消费到这条消息。当autoAck 参数置为false ,对于RabbitMQ 服务端而言,队列中的消息分成了两个部分:一部分是等待投递给消费者的消息、一部分是己经投递给消费者,但是还没有收到消费者确认信号的消息。

  如果RabbitMQ 一直没有收到消费者的确认信号,并且消费此消息的消费者己经断开连接,则RabbitMQ 会安排该消息重新进入队列,等待投递给下一个消费者,当然也有可能还是原来的那个消费者。RabbitMQ 不会为未确认的消息设置过期时间,它判断此消息是否需要重新投递给消费者的唯一依据是消费该消息的消费者连接是否己经断开。

4、API

  4.1 创建连接

 ConnectionFactory factory = new ConnectionFactory
{
UserName = "admin",
Password = "admin",
HostName = "118.21.96.213"
};
var connection = factory.CreateConnection();
var channel = connection.CreateModel();

  4.2 声明交换器

void ExchangeDeclare(string exchange, string type, bool durable, bool autoDelete, IDictionary<string, object> arguments);
//声明交换器后,不需要等待交换器返回。但如果服务器未完成创建,而客户端使用了这个交换器,会发生异常。
void ExchangeDeclareNoWait(string exchange, string type, bool durable, bool autoDelete, IDictionary<string, object> arguments);
  • exchange:交换器名称
  • type:交换器的类型
  • durable:是否持久化
  • autoDelete:是否自动删除。自动删除的前提是至少有一个队列或者交换器与这个交换器绑定, 之后所有与这个交换器绑定的队列或者交换器都与此解绑
  • internal:设置是否内置。如果为true,客户端无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式
  • arguments:参数设置。

    4.3 删除交换器

void ExchangeDelete(string exchange, bool ifUnused);

void ExchangeDeleteNoWait(string exchange, bool ifUnused);
  • ifUnused:为true,表示没有被使用的情况下才会被删除。设置为false,无论如何都要被删除

  4.4 声明队列

QueueDeclareOk QueueDeclare(string queue, bool durable, bool exclusive, bool autoDelete, IDictionary<string, object> arguments);
void QueueDeclareNoWait(string queue, bool durable, bool exclusive, bool autoDelete, IDictionary<string, object> arguments);
  • Queue:队列名称
  • Durable:是否持久化。持久化的队列会存盘,在服务器重启的时候可以保证不丢失相关信息。
  • Exclusive:设置是否排他。
  • AutoDelete:设置是否自动删除。

  如果队列为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。排他队列是基于连接(Connection)可见的,同一个连接的不同信道(Channel)是可以同事访问同一连接创建的排他队列。  “首次”是指如果一个连接已经声明了一个排他队列,其他连接是不允许建立同名的排他队列的。即使该队列是持久化的,一旦连接关闭或者客户端退出,改排他队列都会被自动删除。

  自动删除的前提是:至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。

  4.5 删除队列

//返回队列删除期间清除的消息数
uint QueueDelete(string queue, bool ifUnused, bool ifEmpty); void QueueDeleteNoWait(string queue, bool ifUnused, bool ifEmpty);
  • ifUnused:为true,表示没有被使用的情况下才会被删除。设置为false,无论如何都要被删除
  • ifEmpty:为true,表示在队列为空(队列里面没有任何消息堆积)的情况下才能够删除。

  4.6 队列绑定

void QueueBind(string queue, string exchange, string routingKey, IDictionary<string, object> arguments);

void QueueBindNoWait(string queue, string exchange, string routingKey, IDictionary<string, object> arguments);

  4.7 交换器绑定/解除绑定

void ExchangeBind(string destination, string source, string routingKey, IDictionary<string, object> arguments);

void ExchangeBindNoWait(string destination, string source, string routingKey, IDictionary<string, object> arguments);

void ExchangeUnbind(string destination, string source, string routingKey, IDictionary<string, object> arguments);

void ExchangeUnbindNoWait(string destination, string source, string routingKey, IDictionary<string, object> arguments);
  • destination:交换器名称
  • source:交换器名称

消息从source交换器发送到destination交换器中。

  4.8 发送消息

void BasicPublish(string exchange, string routingKey, bool mandatory, IBasicProperties basicProperties, byte[] body);
  • exchange:消息发送到的交换器
  • routingKey:路由键
  • mandatory:当为true时,交换机无法根据自身类型和路由键找到符合条件的队列,消息会返回给生产者。当为false时,消息直接丢弃。
  • basicProperties:其他参数设置
  • body:消息字节数组

消息中间件RabbitMQ(一)的更多相关文章

  1. 分布式系统之消息中间件rabbitmq

    分布式系统之消息中间件rabbitmq 博客分类: 感谢:  一般php 用rabbitmq  java 用activemq  http://spartan1.iteye.com/blog/11802 ...

  2. 分布式系统消息中间件——RabbitMQ的使用基础篇

    分布式系统消息中间件——RabbitMQ的使用基础篇

  3. 分布式系统消息中间件——RabbitMQ的使用思考篇

    分布式系统消息中间件--RabbitMQ的使用思考篇 前言     前面的两篇文章分布式系统消息中间件--RabbitMQ的使用基础篇与分布式系统消息中间件--RabbitMQ的使用进阶篇,我们简单介 ...

  4. 分布式系统消息中间件——RabbitMQ的使用进阶篇

    分布式系统消息中间件--RabbitMQ的使用进阶篇 前言     上一篇文章 (https://www.cnblogs.com/hunternet/p/9668851.html) 简单总结了分布式系 ...

  5. 消息中间件——RabbitMQ(一)Windows/Linux环境搭建(完整版)

    前言 最近在学习消息中间件--RabbitMQ,打算把这个学习过程记录下来.此章主要介绍环境搭建.此次主要是单机搭建(条件有限),包括在Windows.Linux环境下的搭建,以及RabbitMQ的监 ...

  6. 消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!

    前言 本章学习,我们可以了解到以下知识点: 互联网大厂为什么选择RabbitMQ? RabbiMQ的高性能之道是如何做到的? 什么是AMQP高级协议? AMQP核心概念是什么? RabbitMQ整体架 ...

  7. 消息中间件——RabbitMQ(四)命令行与管控台的基本操作!

    前言 在前面的文章中我们介绍过RabbitMQ的搭建:RabbitMQ的安装过以及各大主流消息中间件的对比:,本章就主要来介绍下我们之前安装的管控台是如何使用以及如何通过命令行进行操作. 1. 命令行 ...

  8. 消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!

    前言 本章我们来一次快速入门RabbitMQ--生产者与消费者.需要构建一个生产端与消费端的模型.什么意思呢?我们的生产者发送一条消息,投递到RabbitMQ集群也就是Broker. 我们的消费端进行 ...

  9. 消息中间件——RabbitMQ(六)理解Exchange交换机核心概念!

    前言 来了解RabbitMQ一个重要的概念:Exchange交换机 1. Exchange概念 Exchange:接收消息,并根据路由键转发消息所绑定的队列. 蓝色框:客户端发送消息至交换机,通过路由 ...

  10. 消息中间件——RabbitMQ(七)高级特性全在这里!(上)

    前言 前面我们介绍了RabbitMQ的安装.各大消息中间件的对比.AMQP核心概念.管控台的使用.快速入门RabbitMQ.本章将介绍RabbitMQ的高级特性.分两篇(上/下)进行介绍. 消息如何保 ...

随机推荐

  1. temp--重庆农商行银联前置改造项目出差

    2019年度 杨伟携程订郎菲酒店 158, 单人住一晚 (3.5晚), 杨伟招行信用卡 预授权 1000. 与方程一起住 1915房    (其实前台预授权是  1000-158 = 842) 3.6 ...

  2. windows安装zookeeper

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...

  3. PC装MAC(VM虚拟机)想体验苹果系统的福利

    Windows下 VM12虚拟机安装OS X 10.11(详细教程) 工具/原料 Mac OS X 10.11 镜像文件 unlocker208文件 VMware Workstation12(版本不一 ...

  4. xtrabackup单表备份与恢复

    官网最新版本下载地址 https://www.percona.com/downloads/XtraBackup/LATEST/ yum install percona-xtrabackup; [epe ...

  5. 扁平化promise调用链(译)

    这是对Flattened Promise Chains的翻译,水平有限请见谅^ ^. Promises对于解决复杂异步请求与响应问题堪称伟大.AngularJS提供了$q和$http来实现它:还有很多 ...

  6. python之路(四)-set集合

    set集合 set是一个无序且不重复的元素集合优点:访问速度快,解决重复问题 l1 = [1,2,34,5,6,7,4,3,3,] s2 = set(l1) #可以以列表元祖等作为参数传进来,set集 ...

  7. 数独计算(C#)

    计算零到多个可能的数独结果,并打印到Console中. 调用方法 MainController mc = new MainController(); mc.Do(); 输入 数独数据 类型为int[, ...

  8. retrofit+rxjava封装

    public class RetrofitHelper { private static OkHttpClient okHttpClient; private static ServiceAPI se ...

  9. 如果解决小程序1024kb渲染之坑

    问题: 在小程序开发中如果有那么个场景和操作步骤,获取商品下拉列表商品列表data为goodsList 当从后台获取数据response.data.list,通常我们会setData({goodsLi ...

  10. Spring注解使用注意点

    1 @RestController @Controller  @RestController注解相当于@ResponseBody + @Controller合在一起的作用.  如果只是使用@RestC ...