rabbitMq 学习笔记(一)
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题
实现高性能,高可用,可伸缩和最终一致性架构。
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 学习笔记(一)的更多相关文章
- RabbitMQ学习笔记(五) Topic
更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...
- RabbitMQ学习笔记1-hello world
安装过程略过,一搜一大把. rabbitmq管理控制台:http://localhost:15672/ 默认账户:guest/guest RabbitMQ默认监听端口:5672 JAVA API地 ...
- (转) Rabbitmq学习笔记
详见原文: http://blog.csdn.net/shatty/article/details/9529463 Rabbitmq学习笔记
- 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群
在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...
- 官网英文版学习——RabbitMQ学习笔记(一)认识RabbitMQ
鉴于目前中文的RabbitMQ教程很缺,本博主虽然买了一本rabbitMQ的书,遗憾的是该书的代码用的不是java语言,看起来也有些不爽,且网友们不同人学习所写不同,本博主看的有些地方不太理想,为此本 ...
- RabbitMQ学习笔记五:RabbitMQ之优先级消息队列
RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...
- RabbitMQ学习笔记(六) RPC
什么RPC? 这一段是从度娘摘抄的. RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的 ...
- 官网英文版学习——RabbitMQ学习笔记(八)Remote procedure call (RPC)
在第四篇学习笔记中,我们学习了如何使用工作队列在多个工作者之间分配耗时的任务. 但是,如果我们需要在远程计算机上运行一个函数并等待结果呢?这是另一回事.这种模式通常称为远程过程调用或RPC. ...
- 官网英文版学习——RabbitMQ学习笔记(二)RabbitMQ安装
一.安装RabbitMQ的依赖Erlang 要进行RabbitMQ学习,首先需要进行RabbitMQ服务的安装,安装我们可以根据官网指导进行http://www.rabbitmq.com/downlo ...
- RabbitMQ学习笔记一
前 言 -解决问题 一.RabbitMQ安装 1.安装erlang 环境 a.下载erlang 版本,注意这里需要和安装的rabbitMq版本相配对,rabbitMQ官方网站上可以查到:https ...
随机推荐
- 3. gn入门
Chromium是用gn和ninja进行编译的,即gn把.gn文件转换成.ninja文件,然后ninja根据.ninja文件将源码生成目标程序.gn和ninja的关系就与cmake和make的关系差不 ...
- 【比赛游记】CSP2019游记
往期回顾:[比赛游记]NOIP2018游记 提高 D1: 密码 Ren2Zhen1Si0Kao9?. A B C 00:04 00:32 -5 \(100 + 100 + 0 = 200\) 因为提前 ...
- 初识v4l2(五)-------v4l2_ioctl浅析
上一篇文章中,已经介绍了v4l2_open.v4l2_read.v4l2_write的调用过程,相对于v4l2_ioctl,它们是比较简单的.下面来分析v4l2_ioctl.注意在这里还是分析以viv ...
- @TableField(select=false)
使用这个注解排除删除标识字段.
- web框架--tornado框架之模板引擎
使用Tornado实现一个简陋的任务表功能demo来讲解tornado框架模板引擎 一.demo目录结构 二.具体文件内容 2.1.commons.css .body{ margin: 0; back ...
- 为什么accpet会重新返回一个套接字
在服务器端,socket()返回的套接字用于监听(listen)和接受(accept)客户端的连接请求.这个套接字不能用于与客户端之间发送和接收数据. accept()接受一个客户端的连接请求,并返回 ...
- CF888G XOR-MST 最小异或生成树
CF888G XOR-MST 链接 CF888G 思路 trie上贪心,先左右两边连边,再用一条边的代价连起左右两颗树.因为内部的边一定比跨两棵树的边权笑,显然是对的. 代码自己瞎yy的.启发式合并 ...
- SPOJ31428 FIBONOMIAL(斐波那契数列)
神鱼推题,必是好题. 前几天刚做过[BJOI2019]勘破神机,于是就会这题了.(BJ人民强啊……%鱼) 首先要求是 $$\sum\limits_{i=0}^nx^if_i$$ 应该很明显能想到把 $ ...
- [LeetCode] 390. Elimination Game 淘汰游戏
There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number ...
- C# HTTP系列1 HttpWebRequest类
系列目录 [已更新最新开发文章,点击查看详细] .NET Framework 中 System.Net 命名空间下提供了 HttpWebRequest 和 HttpWebResponse 2个 ...