消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题

实现高性能,高可用,可伸缩和最终一致性架构。

  RabbitMQ 是采用 Erlang 语言实现 AMQP (Advanced Message Queuing Protocol,高级消息 队列协议)的消息中间件,它最初起源于金融系统,用于在分布式系统中存储转发消息。

  RabbitMQ 整体上是一个生产者与消费者模型,主要负责接收、存储和转发消息。可以把消息传递的过程想象成:当你将一个包裹送到邮局,邮局会暂存并最终将邮件通过邮递员送到收件人的手上, RabbitMQ 就好比由邮局、邮箱和邮递员组成的一个系统。从计算机术语层面来说,RabbitMQ 模型更像是一种交换机模型          

  Producer:生产者,就是投递消息的一方。

  生产者创建消息,然后发布到 RabbitMQ 中。消息一般可以包含 2 个部分:消息体和标签 CLabel)。消息体也可以称之为 payload,在实际应用中,消息体一般是一个带有业务逻辑结构的数据,比如一个 JSON 字符串。当然可以进一步对这个消息体进行序列化操作。消息的标签用来表述这条消息 , 比如一个交换器的名称和一个路由键。 生产者把消息交由 RabbitMQ, RabbitMQ 之后会根据标签把消息发送给感兴趣的消费者 CConsumer)。

   Consumer: 消费者, 就是接收消息的一方。

   消费者连接到 RabbitMQ 服务器,并订阅到队列上。 当消费者消费一条消息时, 只是消费 消息的消息体 Cpayload)。 在消息路由的过程中 , 消息的标签会丢弃, 存入到队列中的消息只 有消息体,消费者也只会消费到消息体, 也就不知道消息的生产者是谁,当然消费者也不需要 知道。

   Broker: 消息中间件的服务节点。
   对于 RabbitMQ 来说, 一个 RabbitMQ Broker 可 以简单地看作一个 RabbitMQ 服务节点 , 或者 RabbitMQ 服务实例 。 大多数情况下也可以将一个 RabbitMQ Broker 看作一台 RabbitMQ 服务器。

  交换器(Exchange)

  Rabbitmq中,生产者会将消息先发送到交换器,然后由交换器根据路由规则将消息转发到队列中,如果路由不到,或许会返回给生产者,或许直接丢弃。

  交换器有四种类型:fanout,direct,topic,header   

  Binding: 绑定。 RabbitMQ 中通过绑定将交换器与队列关联起来,在绑定的时候一般会指定一个绑定键 (BindingKey),这样 RabbitMQ 就知道如何正确地将消息路由到队列了。

  routingkey:路由键。生产者将消息发送给交换器时,一般会指定一个routingkey,用来指定消息的路由规则, routingkey需要与交换器类型和绑定键 (BindingKey) 联合使用才能最终生效。

  队列(queue)

  队列是Rabbitmq的内部对象,用于存储消息。Rabbitmq的消息只能存储在队列中。消费者可以从队列中获取消息并消费。如多个消费者订阅同一个队列,这时队列内的消息会被平均分摊(轮询)给多个消费者处理。

  交换器类型:

  fanout :将所有消息转发至交换器绑定的所有队列中。

  direct :它会把消息路由到那些 BindingKey 和 RoutingKey完全匹配的队列中。

  topic :它与 direct 类型的交换器相似,也是将消息路由到 BindingKey 和 RoutingKey 相匹配的队 列中,但这里的匹配规则有些不同,它约定:

  •     RoutingKey 为一个点号". "分隔的字符串(被点号" "分隔开的每一段独立的字符 串称为一个单词 ),如“com.rabbitmq.client”;  
  •     BindingKey 和 RoutingKey 一样也是点号". "分隔的字符串;
  •       BindingKey 中可以存在两种特殊字符串"*"和"#",用于做模糊匹配,其中"*"用于匹配一个单词,"#"用于匹配多规格单词(可以是零个)。

  header :该类型的交换器性能很差,而且也不实用,基本上不会看到它的存在。

生产者代码:

  nuget:添加RabbitMQ.Client;

 IConnectionFactory conFactory = new ConnectionFactory//创建连接工厂对象
{
HostName = "*.*.*.*",//IP地址
Port = ,//端口号
UserName = "yan",//用户账号
Password = "yan"//用户密码
};
 using (IConnection con = conFactory.CreateConnection())
{
using (IModel channel = con.CreateModel())
{
channel.ExchangeDeclare("ExchangeName", "direct", true, false, null); //声明交换器,dureable:是否持久化,autoDelete:是否自动删除
channel.QueueDeclare("QueueName", true, false, false, null); //声明队列 dureable:是否持久化,exclusive:是否排他 autoDelete:是否自动删除
channel.QueueBind("QueueName", "ExchangeName", "RoutingKey", null);
var properties = channel.CreateBasicProperties();
properties.DeliveryMode = ; //消息持久化
channel.BasicPublish("ExchangeName", "RoutingKey", properties, Encoding.UTF8.GetBytes("HelloWord")); //发布消息
}
12 }

声明交换器参数:

  durable: 设置是否持久化。 durable 设置为 true 表示持久化, 反之是非持久化。持 久化可以将交换器存盘,在服务器重启 的时候不会丢失相关信息。 

  autoDelete: 设置是否自动删除。 autoDelete 设置为 true 则表示自动删除。自动 删除的前提是至少有一个队列或者交换器与这个交换器绑定, 之后所有与这个交换器绑
定的队列或者交换器都与此解绑。注意不能错误地把这个参数理解为: "当与此交换器 连接的客户端都断开时, RabbitMQ 会自动删除本交换器"。

  声明队列参数:

  durable: 设置是否持久化。为 true 则设置队列为持久化。持久化的队列会存盘,在 服务器重启的时候可以保证不丢失相关信息。

  exclusive: 设置是否排他。为 true 则设置队列为排他的。如果一个队列被声明为排 他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。这里需要注意 三点:排他队列是基于连接(Connection) 可见的,同一个连接的不同信道 (Channel) 是可以同时访问同一连接创建的排他队列; "首次"是指如果一个连接己经声明了一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同:即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除,这种队列 适用于一个客户端同时发送和读取消息的应用场景。

  autoDelete: 设置是否自动删除。为 true 则设置队列为自动删除。自动删除的前提是: 至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。不能把这个参数错误地理解为: "当连接到此队列的所有客户端断开时,这 个队列自动删除",因为生产者客户端创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列。

消费者代码:

 IConnectionFactory conFactory = new ConnectionFactory//创建连接工厂对象
{
HostName = "*.*.*.*",//IP地址
Port = ,//端口号
UserName = "yan",//用户账号
Password = "yan"//用户密码
};
using (IConnection con = conFactory.CreateConnection())
{
using (IModel channel = con.CreateModel())
{
channel.ExchangeDeclare("ExchangeName", "direct", true, false, null); //声明交换器,dureable:是否持久化,autoDelete:是否自动删除
channel.QueueDeclare("QueueName", true, false, false, null); //声明队列 dureable:是否持久化,exclusive:是否排他 autoDelete:是否自动删除
channel.QueueBind("QueueName", "ExchangeName", "RoutingKey", null);
EventingBasicConsumer consumer = new EventingBasicConsumer(channel); //声明事件基本消费者
consumer.Received += (ch,ea) => {
  var message = Encoding.UTF8.GetString(ea.Body);
  Console.WriteLine($"收到消息: {message}"); //消费消息
  channel.BasicAck(ea.DeliveryTag, false); //确认该消息已被消费
};
channel.BasicConsume("QueueName", false, consumer); //启动消费者,并设置为手动应答消息
}
}

  channel.BasicReject(ea.DeliveryTag,false);  //拒绝消息 requeue true:消息重新存入队列。false:立即会把消息从队列中移除。  

  为了保证消息从队列可靠地达到消费者, RabbitMQ 提供了消息确认机制( message acknowledgement)。 消费者在订阅队列时,可以指定 autoAck 参数,当 autoAck 等于 false 时, RabbitMQ 会等待消费者显式地回复确认信号后才从内存(或者磁盘)中移去消息(实质上是先打上删除标记,之后再删除)。当 autoAck 等于 true 时, RabbitMQ 会自动把发送出去的 消息置为确认,然后从内存(或者磁盘)中删除,而不管消费者是否真正地消费到了这些消息。

  采用消息确认机制后,只要设置 autoAck 参数为 false,消费者就有足够的时间处理消息 (任务),不用担心处理消息过程中消费者进程挂掉后消息丢失的问题, 因为 RabbitMQ 会一直 等待持有消息直到消费者显式调用 Basic.Ack 命令为止。
  当 autoAck 参数置为 false,对于 RabbitMQ 服务端而言,队列中的消息分成了两个部分: 一部分是等待投递给消费者的消息:一部分是己经投递给消费者,但是还没有收到消费者确认信号的消息。如果 RabbitMQ 一直没有收到消费者的确认信号,并且消费此消息的消费者己经 断开连接,则 RabbitMQ 会安排该消息重新进入队列,等待投递给下一个消费者,当然也有可能还是原来的那个消费者。

  RabbitMQ 不会为未确认的消息设置过期时间,它判断此消息是否需要重新投递给消费者的唯一依据是消费该消息的消费者连接是否己经断开,这么设计的原因是 RabbitMQ 允许消费者 消费一条消息的时间可以很久很久。

rabbitMq 学习笔记(一)的更多相关文章

  1. RabbitMQ学习笔记(五) Topic

    更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...

  2. RabbitMQ学习笔记1-hello world

    安装过程略过,一搜一大把. rabbitmq管理控制台:http://localhost:15672/   默认账户:guest/guest RabbitMQ默认监听端口:5672 JAVA API地 ...

  3. (转) Rabbitmq学习笔记

    详见原文: http://blog.csdn.net/shatty/article/details/9529463 Rabbitmq学习笔记

  4. 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群

    在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...

  5. 官网英文版学习——RabbitMQ学习笔记(一)认识RabbitMQ

    鉴于目前中文的RabbitMQ教程很缺,本博主虽然买了一本rabbitMQ的书,遗憾的是该书的代码用的不是java语言,看起来也有些不爽,且网友们不同人学习所写不同,本博主看的有些地方不太理想,为此本 ...

  6. RabbitMQ学习笔记五:RabbitMQ之优先级消息队列

    RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...

  7. RabbitMQ学习笔记(六) RPC

    什么RPC? 这一段是从度娘摘抄的. RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的 ...

  8. 官网英文版学习——RabbitMQ学习笔记(八)Remote procedure call (RPC)

    在第四篇学习笔记中,我们学习了如何使用工作队列在多个工作者之间分配耗时的任务.   但是,如果我们需要在远程计算机上运行一个函数并等待结果呢?这是另一回事.这种模式通常称为远程过程调用或RPC.   ...

  9. 官网英文版学习——RabbitMQ学习笔记(二)RabbitMQ安装

    一.安装RabbitMQ的依赖Erlang 要进行RabbitMQ学习,首先需要进行RabbitMQ服务的安装,安装我们可以根据官网指导进行http://www.rabbitmq.com/downlo ...

  10. RabbitMQ学习笔记一

    前 言 -解决问题  一.RabbitMQ安装  1.安装erlang 环境 a.下载erlang 版本,注意这里需要和安装的rabbitMq版本相配对,rabbitMQ官方网站上可以查到:https ...

随机推荐

  1. VS调试

    1.调试输出变量值 F9先设置断点,开始调试后,依次选择调试——>窗口——>局部变量和监视——>监视1. 点击“全部中断”——>之后局部变量会显示相关变量值,监视1可以查看变量 ...

  2. 代码审计-md5()函数

    <?php error_reporting(0); $flag = 'flag{test}'; if (isset($_GET['username']) and isset($_GET['pas ...

  3. uiautomator输入中文实例

    package com.demo3; import jp.jun_nama.test.utf7ime.helper.Utf7ImeHelper; import com.android.uiautoma ...

  4. woocommerce如何隐藏SKU

    有时我们不想在woocommerce网站前台显示SKU,如下图所示,因为sku一多整个排版可能会乱,那么要如何隐藏sku呢?随ytkah一起来看看 在当前主题的function.php文件中加入如下代 ...

  5. Git 克隆远程仓库到本地

    Git 克隆远程仓库到本地 参考 $ git clone --help https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E8%8E%B7% ...

  6. Linux系统运维笔记,CentOS 7.4防火墙配置

    1.查看firewall服务状态 systemctl status firewalld 2.查看firewall的状态 firewall-cmd --state 3.开启.重启.关闭.firewall ...

  7. win10 连接samba 账号密码不正确,win7可以访问

    1.本地安全策略,本地策略-安全选项,需要修改成默认的值的修改方式: 查找注册表浏览到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA ...

  8. Hibernate 连接MySQL/SQLServer/Oracle数据库的hibernate.cfg.xml文件

    用Hibernate配置连接数据库可以方便我们对POJO的操作,节省了很多时间和代码.下面就分别说明连接不同数据库需要在hibernate.cfg.xml做的配置. 需要数据库驱动包可以点击这里下载: ...

  9. Word文字中嵌套的图片向上突出,与文字的高度不一致

    文字中嵌套的图片向上突出,与文字的高度不一致. 调整方法: 选中图片,找到Font字体设置,选中位置下拉框,选择适当项. Select the inline graphic by clicking o ...

  10. Task和async/await详解

    一.什么是异步 同步和异步主要用于修饰方法.当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法:当一个方法被调用时立即返回,并获取一个线程执行该方法内部的业务 ...