.Net6基本使用RabbitMQ
1.安装RabbitMQ.Client包
2.通过创建连接类代码,必须为单例模式
ConnectionFactory connectionFactory = new ConnectionFactory
{
UserName = "guest",
Password = "guest",
HostName = "localhost",
Port = 5672
//VirtualHost = "/"
};
3.普通模式使用一对一模式
/// <summary>
/// 普通模式发送消息-生产者
/// </summary>
/// <param name="factory"></param>
public static void OrdinarySend(ConnectionFactory factory)
{
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
//创建队列,声明创建一个队列,如果队列已存在,则使用这个队列
//第一个参数:队列名称
//第二个参数:是否持久化,false为不持久化,mq停止或重新启动消息丢失
//第三个参数:是否队列私有化,fasle则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用
//第四个参数:是否自动删除消息,false代表连接停掉后不自动删除队列
channel.QueueDeclare("helloMQ", false, false, false, null);
string message = "Hello World";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish("", "helloMQ", null, body);
Console.WriteLine($"发送消息成功:{message}");
}
/// <summary>
/// 普通消费者模式
/// </summary>
/// <param name="factory"></param>
public static void OrdinaryCustomer(ConnectionFactory factory)
{
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
//创建队列,声明创建一个队列,如果队列已存在,则使用这个队列
//第一个参数:队列名称
//第二个参数:是否持久化,false为不持久化,mq停止或重新启动消息丢失
//第三个参数:是否队列私有化,fasle则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用
//第四个参数:是否自动删除消息,false代表连接停掉后不自动删除队列
channel.QueueDeclare("helloMQ", false, false, false, null);
EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
//false只是确认签收当前的消息,设置为true的时候则代表签收改消费者所有未签收的消息
channel.BasicAck(ea.DeliveryTag, false);
Console.WriteLine($"接受到消息:{message}");
};
//从MQ服务器中获取数据
//第一个参数:队列名
//第二个参数:是否自动确认消息,false代表手动确认,这是mq推荐的做法
channel.BasicConsume("helloMQ", false, consumer);
Console.WriteLine("消费成功.....");
}
4.工作者模式
/// <summary>
/// 工作模式生成者代码
/// </summary>
/// <param name="factory"></param>
public static void WorkSend(ConnectionFactory factory)
{
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
//创建队列,声明创建一个队列,如果队列已存在,则使用这个队列
//第一个参数:队列名称
//第二个参数:是否持久化,false为不持久化,mq停止或重新启动消息丢失
//第三个参数:是否队列私有化,fasle则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用
//第四个参数:是否自动删除消息,false代表连接停掉后不自动删除队列
channel.QueueDeclare("WorkSend_Quest4", false, false, false, null);
var index = 0;
while (true)
{
string message = "Hello World"+ index;
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish("", "WorkSend_Quest4", null, body);
Console.WriteLine($"正在发送消息成功:{message}");
Thread.Sleep(1000);
index++;
}
}
/// <summary>
/// 工作模式消费者
/// </summary>
public static void WorkCustomer(ConnectionFactory factory,string flag)
{
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
//创建队列,声明创建一个队列,如果队列已存在,则使用这个队列
//第一个参数:队列名称
//第二个参数:是否持久化,false为不持久化,mq停止或重新启动消息丢失
//第三个参数:是否队列私有化,fasle则代表所有消费者都可以访问,true代表只有第一次拥有它的消费者才能一直使用
//第四个参数:是否自动删除消息,false代表连接停掉后不自动删除队列
channel.QueueDeclare("WorkSend_Quest4", false, false, false, null);
EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
//prefetchCount:表示每次最多消费一个消息
channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
//false只是确认签收当前的消息,设置为true的时候则代表签收改消费者所有未签收的消息
channel.BasicAck(ea.DeliveryTag, false);
Console.WriteLine($"{flag}正在消费到消息:{message}");
};
//从MQ服务器中获取数据
//第一个参数:队列名
//第二个参数:是否自动确认消息,false代表手动确认,这是mq推荐的做法
channel.BasicConsume("WorkSend_Quest4", false, consumer);
Console.WriteLine($"{flag}消费成功.....");
}
5.发布订阅/路由模式
/// <summary>
/// 发布订阅模式生成者代码
/// </summary>
/// <param name="factory"></param>
public static void SubSend(ConnectionFactory factory, string exchangeType)
{
//var exchangeName = "fanout_exchange";
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
if (exchangeType == ExchangeType.Direct) //路由模式
{
Console.WriteLine("Hello, World! 生产者");
Console.WriteLine($"输入 routingKey:");
string routingKey = Console.ReadLine();
//ring routingKey = "exchange1_routingKey";
#region 定义交换机
string exchangeName = "exchange2";
channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct); // 把交换机设置为 fanout 发布订阅模式
#endregion
string str;
do
{
Console.WriteLine("发送内容:");
str = Console.ReadLine()!;
byte[] body = Encoding.UTF8.GetBytes(str); // 消息内容
channel.BasicPublish(exchangeName, routingKey, null, body); // 发送消息
} while (str.Trim().ToLower() != "exit");
}
else if (exchangeType == ExchangeType.Fanout) //广播模式
{
#region 定义交换机
string exchangeName = "exchange1";
channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Fanout); // 把交换机设置为 fanout 发布订阅模式
#endregion
string str;
do
{
Console.WriteLine("发送内容:");
str = Console.ReadLine()!;
byte[] body = Encoding.UTF8.GetBytes(str); // 消息内容
channel.BasicPublish(exchangeName, "", null, body); // 发送消息
} while (str.Trim().ToLower() != "exit");
}
}
/// <summary>
/// 发布订阅模式消费者代码
/// </summary>
/// <param name="factory"></param>
public static void SubCustomer(ConnectionFactory factory, string exchangeType)
{
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
if (exchangeType == ExchangeType.Fanout)
{
#region 声明交换机
string exchangeName = "exchange1";
channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout);
#endregion
#region 声明队列
string queueName = exchangeName + "_" + new Random().Next(1, 1000);
Console.WriteLine("队列名称:" + queueName);
channel.QueueDeclare(
queue: queueName,//消息队列名称
durable: false,//是否持久化,true持久化,队列会保存磁盘,服务器重启时可以保证不丢失相关信息。
exclusive: false,//是否排他,true排他的,如果一个队列声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除.
autoDelete: false,//是否自动删除。true是自动删除。自动删除的前提是:致少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除.
arguments: null 设置队列的一些其它参数
);
#endregion
channel.QueueBind(queueName, exchangeName, ""); // 将队列与交换机绑定
// 创建消费者对象
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
byte[] message = ea.Body.ToArray();
Console.WriteLine("接收到的消息为:" + Encoding.UTF8.GetString(message));
channel.BasicAck(ea.DeliveryTag, false); // 开启返回消息确认
};
channel.BasicConsume(queue: queueName, autoAck: false, consumer); // 将autoAck设置false 关闭自动确认.
}
else if (exchangeType == ExchangeType.Direct)
{
Console.WriteLine("Hello, World! 生产者");
Console.WriteLine($"输入 routingKey:");
string routingKey = Console.ReadLine();
#region 声明交换机
string exchangeName = "exchange2";
channel.ExchangeDeclare(exchangeName, ExchangeType.Direct);
#endregion
#region 声明队列
string queueName = exchangeName + "_" + new Random().Next(1, 1000);
Console.WriteLine("队列名称:" + queueName);
channel.QueueDeclare(
queue: queueName,//消息队列名称
durable: false,//是否持久化,true持久化,队列会保存磁盘,服务器重启时可以保证不丢失相关信息。
exclusive: false,//是否排他,true排他的,如果一个队列声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除.
autoDelete: false,//是否自动删除。true是自动删除。自动删除的前提是:致少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除.
arguments: null 设置队列的一些其它参数
);
#endregion
channel.QueueBind(queueName, exchangeName, routingKey); // 将队列与交换机绑定
//channel.QueueBind(queueName, exchangeName, "key2");
//channel.QueueBind(queueName, exchangeName, "key3"); // 可以通过绑定多个,来匹配多个路由
// channel.BasicQos(0, 1, false); // 告诉Rabbit每次只能向消费者发送一条信息,再消费者未确认之前,不再向他发送信息
// 创建消费者对象
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
byte[] message = ea.Body.ToArray();
Console.WriteLine("接收到的消息为:" + Encoding.UTF8.GetString(message));
channel.BasicAck(ea.DeliveryTag, true); // 开启返回消息确认
};
channel.BasicConsume(queue: queueName, autoAck: false, consumer); // 将autoAck设置false 关闭自动确认
}
}