RabbitMQ

简介

MQ全称是Message Queue,可以理解为消息队列的意思,简单来说就是消息以管道的方式进行传递。
RabbitMQ 是一个实现了AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,用Erlang语言的。

使用场景

在我们秒杀抢购商品的时候,系统会提醒我们稍等排队中,而不是像几年前一样页面卡死或报错给用户。
像这种排队结算就用到了消息队列机制,放入通道里面一个一个结算处理,而不是某个时间断突然涌入大批量的查询新增把数据库给搞宕机,所以RabbitMQ本质上起到的作用就是削峰填谷,为业务保驾护航。

工作机制

生产者、消费者和代理
在了解消息通讯之前首先要了解3个概念:生产者、消费者和代理。
生产者:消息的创建者,负责创建和推送数据到消息服务器;
消费者:消息的接收方,用于处理数据和确认消息;
代理:就是RabbitMQ本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。
消息发送原理
首先你必须连接到Rabbit才能发布和消费消息,那怎么连接和发送消息的呢?
你的应用程序和Rabbit Server之间会创建一个TCP连接,一旦TCP打开,并通过了认证,认证就是你试图连接Rabbit之前发送的Rabbit服务器连接信息和用户名和密码,有点像程序连接数据库,一旦认证通过你的应用程序和Rabbit就创建了一条AMQP信道(Channel)。
信道是创建在“真实”TCP上的虚拟连接,AMQP命令都是通过信道发送出去的,每个信道都会有一个唯一的ID,不论是发布消息,订阅队列或者介绍消息都是通过信道完成的。
为什么不通过TCP直接发送命令?
对于操作系统来说创建和销毁TCP会话是非常昂贵的开销,假设高峰期每秒有成千上万条连接,每个连接都要创建一条TCP会话,这就造成了TCP连接的巨大浪费,而且操作系统每秒能创建的TCP也是有限的,因此很快就会遇到系统瓶颈。
如果我们每个请求都使用一条TCP连接,既满足了性能的需要,又能确保每个连接的私密性,这就是引入信道概念的原因。

消息持久化

Rabbit队列和交换器有一个不可告人的秘密,就是默认情况下重启服务器会导致消息丢失,那么怎么保证Rabbit在重启的时候不丢失呢?答案就是消息持久化。

当你把消息发送到Rabbit服务器的时候,你需要选择你是否要进行持久化,但这并不能保证Rabbit能从崩溃中恢复,想要Rabbit消息能恢复必须满足3个条件:

投递消息的时候durable设置为true,消息持久化,代码:channel.queueDeclare(x, true, false, false, null),参数2设置为true持久化;
设置投递模式deliveryMode设置为2(持久),代码:channel.basicPublish(x, x, MessageProperties.PERSISTENT_TEXT_PLAIN,x),参数3设置为存储纯文本到磁盘;
消息已经到达持久化交换器上;
消息已经到达持久化的队列;
持久化工作原理
Rabbit会将你的持久化消息写入磁盘上的持久化日志文件,等消息被消费之后,Rabbit会把这条消息标识为等待垃圾回收。
持久化的缺点
消息持久化的优点显而易见,但缺点也很明显,那就是性能,因为要写入硬盘要比写入内存性能较低很多,从而降低了服务器的吞吐量,尽管使用SSD硬盘可以使事情得到缓解,但他仍然吸干了Rabbit的性能,当消息成千上万条要写入磁盘的时候,性能是很低的。
所以使用者要根据自己的情况,选择适合自己的方式。

RabbitMQ 基本使用

官网[:](https://www.rabbitmq.com)
先安装 otp_win64_24.0.exe
将 D:\apps\erl-24.0\bin 添加到环境变量中,运行CMD,输入erl,测试安装是否成功

再安装 rabbitmq-server-3.8.17.exe 安装在本机中
将 D:\apps\RabbitMQ Server\rabbitmq_server-3.8.17\sbin 添加到环境变量中,运行CMD,
输入 rabbitmqctl status 查看状态
输入 rabbitmq-plugins enable rabbitmq_management 启动管理工具 启动成功后,在浏览器输入地址http://127.0.0.1:15672/,进入管理页面,账户密码都是guest。
输入 rabbitmqctl list_queues 去RabbitMQ的服务器查看当前消息队列
还有许多其他命令

RabbitMQ c# 应用

Nuget上搜索RabbitMQ
版本 5.2.0 以上版本 至少需要 .NET Framework 4.6.1
本机测试 发送消息和接收消息,几乎是同步的
服务端安装到本机的话,可以用作两个程序之间 进程通信 使用,效果还不错。对于不了解其他方式,这种方式好用
RabbitMQ Send
var factory = new ConnectionFactory();
factory.HostName = "localhost";//主机名,Rabbit会拿这个IP生成一个endpoint,这个很熟悉吧,就是socket绑定的那个终结点。
factory.UserName = "guest";//默认用户名,用户可以在服务端自定义创建,有相关命令行
factory.Password = "guest";//默认密码

using (var connection = factory.CreateConnection())//连接服务器,即正在创建终结点。
{
    //这里Rabbit的玩法就是一个通道channel下包含多个队列Queue
    using (var channel = connection.CreateModel())
    {
         channel.QueueDeclare("HoneyQueue", false, false, false, null);//创建一个名称为 HoneyQueue 的消息队列
         var properties = channel.CreateBasicProperties();
         properties.DeliveryMode = 1;
         string message = "My name is Honey!";          //传递的消息内容
         channel.BasicPublish("", "HoneyQueue", properties, Encoding.UTF8.GetBytes(message)); //生产消息
    }
}
RabbitMQ Received
var factory = new ConnectionFactory();
factory.HostName = "localhost";
factory.UserName = "guest";
factory.Password = "guest";

var connection = factory.CreateConnection();
var channel = connection.CreateModel();
channel.QueueDeclare("HoneyQueue", false, false, false, null);
var consumer = new EventingBasicConsumer(channel);//消费者
channel.BasicConsume("HoneyQueue", true, consumer);//消费消息
consumer.Received += (model, ea) =>
{
    var body = ea.Body;
    var message = Encoding.UTF8.GetString(body);
};
// 程序结束时 释放 connection & channel

RabbitMQ 服务器端 应用

设置下防火墙的入站规则和出站规则,将5672的UDP端口开放一下。
HostName为我们的服务器地址:factory.HostName = "1.1.1.1";
guest账号默认是不支持远程连接的。
管理页面中添加用户,设置权限;
factory.HostName = "1.1.1.1";
factory.UserName = "Honey";
factory.Password = "123456";

报错:None of the specified endpoints were reachable
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值