参考:2021最新版RabbitMQ详解,从基础入门到高级内容-消息中间件_哔哩哔哩_bilibili
课程学习笔记
一、RabbitMQ 介绍
1、AMQP (Advanced Message Queuing Protocol) 高级消息队列协议
2、简介
特点:消息可靠,支持持久化
3、基础,应用场景
二、RabbitMQ安装
在docker中安装,docker的一些命令
三、入门案例
四、原理分析
概念介绍
1、Message 消息
2、Publisher 发布者/提供者:是一个向交换器中发布消息的客户端应用程序;
3、Consumer 订阅者/提供者:是一个从消息队列中取得消息的客户端应用程序;
4、Exchange 交换器:接收生产者发送的消息,并将消息路由给服务器中的队列
三种类型
1、diect 发布与订阅,需要完全一致
2、topic 主题,匹配规则,模糊匹配
3、fanout 广播,与路由键无关
5、Binding 绑定:用于消息队列和交换器之间的关联,一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表;
6、Queue 消息队列:消息的容器,也是终点;
7、Routing-key 路由键:RabbitMQ决定消息该投递到哪个队列的规则,队列通过路由键绑定到交换器,消息发送到MQ服务器时,消息将持有一个路由键,即便是空的,RabbitMQ 也会将其和绑定使用的路由键进行匹配,如果匹配成功,消息会投递到该队列,如果不匹配,消息将会进入黑洞;
8、connection 连接:rabbit服务器和服务建立的TCP链接;
9、channel 信道
1、是TCP里面的虚拟连接,例如:电缆相当于CTP,信道是一个独立的光纤束,一条TCP连接上创建多个信道是没有问题的;
2、TCP一旦打开,就会创建AMQP信道
3、无论是发布消息、接收消息、订阅队列,这些动作都是通过信道完成的
10、Virtual Host 虚拟主机:
表示一批交换器,消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限机制。vhost是AMQP概念的基础,必须在链接时指定,RabbitMQ 默认的vhost是 /
11、Borker 消息队列服务器实体
五、Direct 交换器
发布于订阅,完全匹配
代码演示
六、Topic 交换器
模糊匹配
七、Fanout 交换器
与路由键无关
总结
八、进阶-消息持久化
设置 autoDelete = "false"
Queue中和Exchange中都可以设置
Queue:当所有的消费者客户端连接断开后,是否自动删除队列;
Exchange:当所有的绑定队列都不再使用时,是否自动删除交换器
九、进阶-ACK 消息确认机制
消费者在处理消息时出现异常,防止消息丢失,需要ACK;
总结 ACK,优点
1、如果一个消费者在处理消息出现了网络不稳定,服务器异常等现象,会将消息重新放入队列中
2、如果在集群的情况下,RabbitMQ会立即将这个消息推送给在线的其他消费者,这种机制保障了消费者在服务端故障的时候不会丢失任何的数据和任务;
3、消息永远不会从RabbitMQ中删除:只有当消费者正确发送ACK反馈后,RabbitMQ收到确认后,消息才会从RabbitMQ的服务中删除;
4、消息的ACK机制默认就是打开的;
演示
注意事项:如果忘记掉ACK,Message会一直重复分发,占用大量内存,可以设置重试次数防止,还可以设置重试间隔时间;
同事分享:
X-Consistent-hash 交换器
启用命令:.\rabbitmq-plugins.bat enable rabbitmq_consistent_hash_exchange
演示测试,动态增加和删除队列
其他资料
安装本地RabbitMQ步骤
1、RabbitMQ服务端代码是使用并发式语言Erlang编写的,安装Rabbit MQ的前提是安装Erlang,PS: Erlang 要求电脑名称不能有 中文。
2、安装RabbitMQ服务
3、安装RabbitMQ-Plugins
打开命令提示符,输入rabbitmq-plugins enable rabbitmq_management命令进行安装
打开浏览器,输入地址http://localhost:15672,回车打开RabbitMQ管理登录界面,输入账号guest、密码guest,点击「Login」登录
.NET CORE 集成 rabbitMQ 实战
AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
RabbitMQ提供了可靠的消息机制、跟踪机制和灵活的消息路由,支持消息集群和分布式部署。适用于排队算法、秒杀活动、消息分发、异步处理、数据同步、处理耗时任务、CQRS等应用场景。
direct,匹配
fanout,广播
topic 主题
static void Main(string[] args)
{
Console.WriteLine("请输入Provider或者Consumer,Provider创建消息提供者,Consumer创建消息消费者");
string input = Console.ReadLine();
if (input.ToLower() == "provider")
{
CreateMsgProvider();
}
else {
CreateMsgConsumer();
}
}
/// <summary>
/// 创建消息提供者
/// </summary>
public static void CreateMsgProvider()
{
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory
{
UserName = "guest", //用户名
Password = "guest", //密码
HostName = "127.0.0.1" //rabbitmq ip
};
//创建连接
var connection = factory.CreateConnection();
//创建通道
var channel = connection.CreateModel();
//声明一个队列
channel.QueueDeclare("hello", false, false, false, null);
Console.WriteLine("\nRabbitMQ连接成功,请输入消息,输入exit退出!");
string input;
do
{
input = Console.ReadLine();
var sendBytes = Encoding.UTF8.GetBytes(input);
//发布消息
channel.BasicPublish("", "hello", null, sendBytes);
} while (input.Trim().ToLower() != "exit");
channel.Close();
connection.Close();
}
/// <summary>
/// 创建消息消费者
/// </summary>
public static void CreateMsgConsumer()
{
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory
{
UserName = "guest", //用户名
Password = "guest", //密码
HostName = "127.0.0.1" //rabbitmq ip
};
//创建连接
var connection = factory.CreateConnection();
//创建通道
var channel = connection.CreateModel();
//事件基本消费者
EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
//接收到消息事件
consumer.Received += (ch, ea) =>
{
var message = Encoding.UTF8.GetString(ea.Body.ToArray());
Console.WriteLine($"收到消息:{message}");
//Console.WriteLine($"收到该消息[{ea.DeliveryTag}] 延迟10s发送回执");
延迟10秒
//Thread.Sleep(10000);
//确认该消息已被消费
channel.BasicAck(ea.DeliveryTag, false);
};
//启动消费者 设置为手动应答消息
channel.BasicConsume(consumer, "hello");
Console.WriteLine("消费者已启动");
Console.ReadKey();
channel.Dispose();
connection.Close();
}