目录
4. Asp.Net Core中使用RabbitMQ(以上代码只是各队列的使用)
4.1 引入nuget RabbitMQ.Client 程序包。
4.4 ApiController(可以结合以上的队列代码使用)
1.消息队列概述
消息队列 是指利用 高效可靠 的 消息传递机制 进行与平台无关的 数据交流,并基于 数据通信 来进行分布式系统的集成。通过提供 消息传递 和 消息排队 模型,它可以在 分布式环境 下提供 应用解耦、弹性伸缩、冗余存储、流量削峰、异步通信、数据同步 等等功能,其作为 分布式系统架构 中的一个重要组件,有着举足轻重的地位。
2.消息队列的特点及应用场景
消息发送者 可以发送一个消息而无须等待响应。消息发送者 将消息发送到一条 虚拟的通道(主题 或 队列)上,消息接收者 则 订阅 或是 监听 该通道。一条信息可能最终转发给 一个或多个 消息接收者,这些接收者都无需对 消息发送者 做出 同步回应。整个过程都是 异步的。
当你需要使用 消息队列 时,首先需要考虑它的必要性。可以使用消息队列的场景有很多,最常用的几种,是做 应用程序松耦合、异步处理模式、发布与订阅、最终一致性、错峰流控 和 日志缓冲 等。反之,如果需要 强一致性,关注业务逻辑的处理结果,则使用 RPC
显得更为合适
3.RabbitMQ
3.1 初始RabbitMQ
是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,RabbitMQ是使用Erlang(高并发语言)语言来编写的,并且RabbitMQ是基于AMQP协议的。
3.2 Docker安装RabbitMQ
docker run -d --name rabbitmq -e RABBITMQ_DEFAULT_USER=123 -e RABBITMQ_DEFAULT_PASS=123-p 15672:15672 -p 5672:5672 rabbitmq:3-management
浏览器地址栏输入RabbitMQ服务器ip,输入登录账号123密码123,进入RabbitMQ。
3.3 RabbitMQ中的六大队列模式
//连接RabbitMQ
public class RabbitMQConnection
{
public static void SendMessage()
{
// 创建工厂对象
var connectionFactory = new ConnectionFactory()
{
HostName = "192.168.157.157",
Port = 5672,
UserName = "123",
Password = "123",
VirtualHost = "/"
};
// 通过工厂对象创建连接对象
var connection = connectionFactory.CreateConnection();
// 通过连接对象获取Channel对象
var channel = connection.CreateModel();
}
}
3.3.1 简单队列模式
最简单的工作队列,其中一个消息生产者,一个消息消费者,一个队列。也称为点对点模式。
//生产者
public static void SendMessage()
{
string queueName = "normal";
using (var connection = RabbitMQHelper.GetConnection())
{
// 创建信道
using(var channel = connection.CreateModel())
{
// 创建队列
channel.QueueDeclare(queue:queueName,durable: false, false, false, null);
// 没有绑定交换机,怎么找到路由队列的呢?
while (true)
{
string message = "Hello RabbitMQ Message";
var body = Encoding.UTF8.GetBytes(message);
// 发送消息到rabbitmq,使用rabbitmq中默认提供交换机路由,默认的路由Key和队列名称完全一致
channel.BasicPublish(exchange: "", routingKey: queueName, null, body);
Thread.Sleep(1000);
Console.WriteLine("Send Normal message");
}
}
}
}
//消费者
public class Receive
{
public static void ReceiveMessage()
{
// 消费者消费是队列中消息
string queueName = "normal";
var connection = RabbitMQHelper.GetConnection("192.168.3.215", 5672);
{
var channel = connection.CreateModel();
{
// 如果你先启动是消费端就会异常
channel.QueueDeclare(queueName, false, false, false, null);
var consumer = new EventingBasicConsumer(channel);
consumer.Received +=(model, ea) => {
var message = Encoding.UTF8.GetString(ea.Body.ToArray());
Console.WriteLine(" Normal Received => {0}", message);
};
channel.BasicConsume(queueName,true, consumer);
}
}
}
}
3.3.2 工作队列
一个消息生产者,一个交换器,一个消息队列,多个消费者。同样也称为点对点模式。
//生产者
public class WorkerSend
{
public static void SendMessage()
{
string queueName = "Worker_Queue";
using (var connection = RabbitMQHelper.GetConnection())
{
using(var channel = connection.CreateModel())
{
channel.QueueDeclare(queueName, false, false, false, null);
for (int i = 0; i < 30; i++)
{
string message = $"RabbitMQ Worker {i + 1} Message";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish("", queueName, null, body);
Console.WriteLine("send Task {0} message",i + 1);
}
}
}
}
}
//消费者
public class WorkerReceive
{
public static void ReceiveMessage()
{
string queueName = "Worker_Queue";
var connection = RabbitMQHelper.GetConnection();
{
var channel = connection.CreateModel();
{
channel.QueueDeclare(queueName, false, false, false, null);
var consumer = new EventingBasicConsumer(channel);
//设置prefetchCount : 1来告知RabbitMQ,在未收到消费端的消息确认时,不再分发消息,也就确保了当消费端处于忙碌状态时,不再分配任务。
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); //能者多劳
consumer.Received +=(model, ea) => {
var message = Encoding.UTF8.GetString(ea.Body.ToArray());
Console.WriteLine(" Worker Queue Received => {0}", message);
};
channel.BasicConsume(queueName,true, consumer);
}
}
}
}