RabbitMQ入门到进阶系列:
RabbitMQ入门到进阶系列(二)
第三章:RabbitMQ的工作模式
RabbitMQ 提供了 6 种工作模式:简单模式、work queues、Publish/Subscribe 发布与订阅模式、Routing
路由模式、Topics 主题模式、RPC 远程调用模式(远程调用,不太算 MQ;暂不作介绍)。
3.1简单模式
简单模式中生产者、消息队列、消费者是一对一关系。我们可以把生产者理解为给你寄快递的人,消息队列是邮局,里面存放着很多快递,然后派送收件人(消费者)。
我们建立两个控制台应用程序分别模拟发布者和消费者,当然在一个解决方案里建两个项目也行,能区分开就好。
两个程序都得安装RabbitMQ.Client包
3.1.1生产者代码
using RabbitMQ.Client;
namespace Publisher
{
class Program
{
static void Main(string[] args)
{
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory
{
UserName = "xiaolu1",//用户名
Password = "xiaolu1",//密码
HostName = "129.211.5.88"//rabbitmq 服务器ip
};
//创建连接
var connection = factory.CreateConnection();
//创建通道
var channel = connection.CreateModel();
//声明一个队列
channel.QueueDeclare("hello", false, false, false, null);
Console.WriteLine("RabbitMQ连接成功,请输入消息,输入exit退出!");
string input;
do
{
input = Console.ReadLine();
var msg = Encoding.UTF8.GetBytes(input);
//发布消息
//第一个参数是交换机也就是
//简单模式可以不用交换机,留空即使用默认交换机
channel.BasicPublish("", "hello", null, msg);Exchange,
} while (input.Trim().ToLower() != "exit");
}
}
}
我们创建了一个名为hello的消息队列,启动程序输入消息再看看RabitMQ页面是否生成了对应的消息队列
可以看到的确有一个名为hello 的消息队列并且有两条消息,证明我们的消息发布成功。
3.1.2消费者代码
//连接Broker
ConnectionFactory factory = new ConnectionFactory()
{
HostName = "129.211.5.88",
UserName = "xiaolu1",
Password = "xiaolu1"
};
//创建连接
var connection = factory.CreateConnection();
//创建channel
var channel = connection.CreateModel();
//声明队列
channel.QueueDeclare("hello", true, false, false, null);
EventingBasicConsumer eventingBasicConsumer = new EventingBasicConsumer(channel);
eventingBasicConsumer.Received += (sender, e) =>
{
var message = Encoding.UTF8.GetString(e.Body);
Console.WriteLine(message);
};
//消费队列
channel.BasicConsume(queue: "hello",
consumer: eventingBasicConsumer);
消费者成功接收到了信息。
3.2Work queues模式
我们可以把Work queues理解为饭堂大家排着队依次打饭,即轮训的方式消费队列。
我们稍微修改下上一节的生产者代码,直接循环发送100次消息,然后启动两个消费者
我们可以看到消息是被两个消费者一人一条的轮询方式消费掉的。
3.3Pub/Sub 订阅模式
在订阅模型中,多了一个 Exchange 角色,而且过程略有变化:
⚫ P:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
⚫ C:消费者,消息的接收者,会一直等待消息到来
⚫ Queue:消息队列,接收消息、缓存消息
⚫ Exchange:交换机(X)。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、
递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有常见以下3种类型:
➢ Fanout:广播,将消息交给所有绑定到交换机的队列
➢ Direct:定向,把消息交给符合指定routing key 的队列
➢ Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列
我们可以把订阅模式理解为日常生活中的订阅报纸(现在已经没人订了),有人订阅了《人民日报》,有人订阅了《南国早报》。那么出版社(生产者)会把报纸(消息)先交给邮局(交换机)然后由邮局根据每个人的订阅情况(routing_key)具体派送报纸,也就是定向模式。通配符模式和SQL中的通配符匹配相似,满足通配条件的就给你发一份。广播模式就更容易理解了,没有限制只要是消息队列就能接收。
3.3.1Fanout交换机
生产者代码
// 生成随机队列名称
var queueName = channel.QueueDeclare().QueueName;
//使用fanout exchange type,指定exchange名称
channel.ExchangeDeclare(exchange: "fanoutExchange", type: "fanout");
var message = "Hello Rabbit!";
var body = Encoding.UTF8.GetBytes(message);
//发布到指定exchange,fanout类型无需指定routingKey
channel.BasicPublish(exchange: "fanoutExchange", routingKey: "", basicProperties: null, body: body);
消费者代码
//申明fanout类型exchange
channel.ExchangeDeclare (exchange: "fanoutExchange", type: "fanout");
//申明随机队列名称
var queuename = channel.QueueDeclare ().QueueName;
//绑定队列到指定fanout类型exchange,无需指定路由键
channel.QueueBind (queue : queuename, exchange: "fanoutEC", routingKey: "");
3.3.2Direct交换机
生产者代码
// 生成随机队列名称
var queueName = channel.QueueDeclare().QueueName;
//使用direct exchange type,指定exchange名称
channel.ExchangeDeclare(exchange: "directExchange", type: "direct");
var message = "Hello Rabbit!";
var body = Encoding.UTF8.GetBytes(message);
//发布到direct类型exchange,必须指定routingKey
channel.BasicPublish(exchange: "directExchange", routingKey: "green", basicProperties: null, body: body);
消费者代码
//申明direct类型exchange
channel.ExchangeDeclare (exchange: "directExchange", type: "direct");
//绑定队列到direct类型exchange,需指定路由键routingKey
channel.QueueBind (queue : green, exchange: "directExchange", routingKey: "green");
3.3.3Topic交换机
生产者代码
// 生成随机队列名称
var queueName = channel.QueueDeclare().QueueName;
//使用topic exchange type,指定exchange名称
channel.ExchangeDeclare(exchange: "topicExchange", type: "topic");
var message = "Hello Rabbit!";
var body = Encoding.UTF8.GetBytes(message);
//发布到topic类型exchange,必须指定routingKey
channel.BasicPublish(exchange: "topicExchange", routingKey: "first.green.fast", basicProperties: null, body: body);
消费者代码
//申明topic类型exchange
channel.ExchangeDeclare (exchange: "topicExchange", type: "topic");
//申明随机队列名称
var queuename = channel.QueueDeclare ().QueueName;
//绑定队列到topic类型exchange,需指定路由键routingKey
channel.QueueBind (queue : queuename, exchange: "topicExchange", routingKey: "#.*.fast");