版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fanbin168/article/details/89321189
RabbitMQ提供了四种Exchange:direct, topic, fanout, header
header模式在实际使用中较少,本文只对前三种模式进行比较。
Topic ExChange属于模糊连接模式(主题模式),
直连模式就是 Exchange 通过 指定的RoutingKey 将 消息转发到与之绑定的Queue中
注:可以这样理解:生产者想发送一条消息到指定的Queue队列中,首先这条消息会Exchange接收到,因为Exchange与queue是进行了绑定,这个绑定指定了RoutingKey(路由名称),这时候Exchange就会通过这个路由名称,来找到指定的Queue,然后将消息保存到Queue中 这就是直连模式
注:当一个Exchange与Queue进行绑定的时候,不是一定要指定RoutingKey的,比如Fanout 模式下就不需要指定RoutingKey
Topic ExChange与Direct ExChange不同点是在于,Topic ExChange可以模糊匹配RoutingKey(路由)来将数据转发到与之绑定的Queue中,而Direct ExChange则是需要完全匹配RoutingKey(路由)才转发。
Topic模式下 必须先启动消费者端,然后再生产者端。
ProducterApp:生产者端
注意:在Topic模型下,生产者段不需要创建Queue 自然也不需要设定Queue与Exchange绑定
扫描二维码关注公众号,回复:
5979293 查看本文章
using RabbitMQ.Client;
using System.Text;
namespace ProducterApp
{
class Program
{
/// 连接配置
/// </summary>
private static readonly ConnectionFactory rabbitMqFactory = new ConnectionFactory() //创建一个工厂连接对象
{
HostName = "192.168.31.30",
UserName = "admin",
Password = "admin",
VirtualHost = "/vhost001", //如果不设置,虚拟主机名称路径默认为 /
Port = 5672, //注意:5672 --是client端通信口 15672 -- 是管理界面ui端口
};
/// <summary>
/// 路由名称
/// </summary>
const string ExchangeName = "exchange002";
static void Main(string[] args)
{
using (IConnection conn = rabbitMqFactory.CreateConnection()) //创建一个连接
{
using (IModel channel = conn.CreateModel()) //创建一个Channel
{
//注意:在Topic模型下,生产者段不需要创建Queue 自然也不需要设定Queue与Exchange绑定
//Exchange的Type类型有:direct,topic, fanout,headers
//direct:所有发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue;当消费者要消费这个Queue中的消息都会时候它要求消费者的RoutingKey与生产者的RoutingKey完全匹配
//topic:所有发送到Topic Exchange的消息都会转发到所有关心的RoutingKey
//durable是Exchange(交换机)的属性,它表示是否需要持久化,为true则为持久化。false表示不需要持久化
//autoDelete:它是Exchange(交换机)的属性,它的值有true和false两种
//为true 则表示当最后一个绑定到Exchange(交换机)上的Queue(队列)删除后,就自动删除该Exchange
//这段话也很好理解,假如Exchange(交换机)上绑定了三个Queue(队列),当这个三个Queue(队列)都被删除的时候这个Exchange(交换机)将会被自动删除
//arguments:它是扩展参数,用于扩展AMQP协议自制定化的使用
channel.ExchangeDeclare(ExchangeName, "topic", durable: false, autoDelete: false, arguments: null); //声明一个Exchange(交换机)
string routingKey1 = "user.america";//这个routingKey的值可以随便你自己设置
string routingKey2 = "user.china";
string routingKey3 = "user.china.beijing";
var props = channel.CreateBasicProperties();
props.Persistent = true;
for (int i = 0; i < 5; i++)
{
//发送的消息必须是二进制的
channel.BasicPublish(exchange: ExchangeName, routingKey: routingKey1, basicProperties: props, body: Encoding.UTF8.GetBytes("你好美国,这是我的第" + i + "条消息"));
channel.BasicPublish(exchange: ExchangeName, routingKey: routingKey2, basicProperties: props, body: Encoding.UTF8.GetBytes("你好中国,这是我的第" + i + "条消息"));
channel.BasicPublish(exchange: ExchangeName, routingKey: routingKey3, basicProperties: props, body: Encoding.UTF8.GetBytes("你好中国北京,这是我的第" + i + "条消息"));
}
}
}
}
}
}
CustomerApp:消费者端
using RabbitMQ.Client;
using System;
using System.Text;
namespace CustomerApp
{
class Program
{
/// <summary>
/// 连接配置
/// </summary>
private static readonly ConnectionFactory rabbitMqFactory = new ConnectionFactory()
{
HostName = "192.168.31.30",
UserName = "admin",
Password = "admin",
Port = 5672,
VirtualHost = "/vhost001",
};
/// <summary>
/// 路由名称
/// </summary>
const string ExchangeName = "exchange002";
//队列名称
const string QueueName = "queue002";
static void Main(string[] args)
{
using (IConnection conn = rabbitMqFactory.CreateConnection())
{
using (IModel channel = conn.CreateModel())
{
//创建交换机这里将Exchange(交换机)Type设定为topic 【消费者端的交换机名称要与生产者端的交换机名称保持一致】
channel.ExchangeDeclare(ExchangeName, "topic", durable: false, autoDelete: false, arguments: null);
//创建队列【消费者端需要创建队列,生产者端不需要创建队列】
channel.QueueDeclare(QueueName, durable: true, autoDelete: false, exclusive: false, arguments: null);
//如果生产者端的交换机通过 user.america,user.china,user.china.beijing 这三条RoutingKey来发送消息
//那么"user.#" 那么消费者端就只能接受到生产者端生产者通过user.america和user.china这两条RoutingKey发送过来的消息
//如果消费者端的RoutingKey改成user.# 那么消费者端可以接受到生产者端生产者通过user.america和user.china和user.china.beijing这三条RoutingKey发送过来的所有消息
string routingKey = "user.*";
channel.QueueBind(QueueName, ExchangeName, routingKey: routingKey);
while (true)
{
//System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
BasicGetResult msgResponse = channel.BasicGet(QueueName, autoAck: true);//这个true表示消费完这条数据是否删除,true表示删除,false表示不删除
if (msgResponse != null)
{
var msgBody = Encoding.UTF8.GetString(msgResponse.Body);
Console.WriteLine(string.Format("接收时间:{0},消息内容:{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), msgBody));
}
}
}
}
}
}
}