Header交换机不依赖于routing key和binding key,而是根据发送消息内容的headers参数来确定消息发送到哪一个队列中,供消费者消费。
通过一个示例说明此类交换机的用法,项目结构:
代码实例:
生产者
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;
namespace AspNetCore.RabbitMQ.MessageProducer.MessageProducer
{
/// <summary>
/// Header类型交换机
/// </summary>
public class HeaderExchange
{
public static void Show()
{
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";//rabbitmq服务在本地运行
factory.UserName = "guest";//用户名
factory.Password = "guest";//密码
//创建链接
using (IConnection connection = factory.CreateConnection())
{
//创建信道
using (IModel channel = connection.CreateModel())
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("生产者已准备就绪......");
//声明交换机exchange
channel.ExchangeDeclare(exchange: "HeaderExchange", type: ExchangeType.Headers, durable: true, autoDelete: false, arguments: null);
//声明两个队列
channel.QueueDeclare(queue: "HeaderExchangeAllQueue", durable: true, exclusive: false, autoDelete: false, arguments: null);
channel.QueueDeclare(queue: "HeaderExchangeAnyQueue", durable: true, exclusive: false, autoDelete: false, arguments: null);
//绑定exchange和queue
channel.QueueBind(queue: "HeaderExchangeAllQueue", exchange: "HeaderExchange", routingKey: string.Empty,
arguments: new Dictionary<string, object>
{
{ "x-match","all"},
{ "name","zhangsan"},
{ "pass","123"}
});
channel.QueueBind(queue: "HeaderExchangeAnyQueue", exchange: "HeaderExchange", routingKey: string.Empty,
arguments: new Dictionary<string, object>
{
{ "x-match","any"},
{ "name","zhangsan"},
{ "pass","123"}
});
//待发送的消息
{
string message = "name和pass都相同";
var props = channel.CreateBasicProperties();
props.Headers = new Dictionary<string, object>()
{
{ "name","zhangsan"},
{ "pass","123"}
};
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "HeaderExchange", routingKey: string.Empty, basicProperties: props, body: body);
Console.WriteLine($"消息 {message} 已发送到队列");
}
{
string message = "只有name相同";
var props = channel.CreateBasicProperties();
props.Headers = new Dictionary<string, object>()
{
{ "name","zhangsan"},
{ "pass","234"}
};
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "HeaderExchange", routingKey: string.Empty, basicProperties: props, body: body);
Console.WriteLine($"消息 {message} 已发送到队列");
}
}
}
}
}
}
声明了两个队列,HeaderExchangeAllQueue和HeaderExchangeAnyQueue。HeaderExchangeAllQueue是需要name和pass两个参数完全匹配才会进入此队列中。HeaderExchangeAnyQueue是name和pass两个参数中有任一参数匹配到就会进入此队列。
main方法:
扫描二维码关注公众号,回复:
13302685 查看本文章

class Program
{
static void Main(string[] args)
{
HeaderExchange.Show();
Console.ReadLine();
}
}
消费者一:
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
namespace AspNetCore.RabbitMQ.MessageConsumer_01.MessageConsumer
{
/// <summary>
/// 消费者 Header类型交换机
/// </summary>
public class HeaderExchange
{
public static void Show()
{
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";//rabbitmq服务在本地运行
factory.UserName = "guest";//用户名
factory.Password = "guest";//密码
//创建链接
using (IConnection connection = factory.CreateConnection())
{
//创建信道
using (IModel channel = connection.CreateModel())
{
Console.ForegroundColor = ConsoleColor.Green;
try
{
//基于当前信道创建事件
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body.ToArray());
Console.WriteLine($"接收成功 {message}");
};
//处理消息
channel.BasicConsume(queue: "HeaderExchangeAllQueue", autoAck: true, consumer: consumer);
channel.BasicConsume(queue: "HeaderExchangeAnyQueue", autoAck: true, consumer: consumer);
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
}
main方法:
class Program
{
static void Main(string[] args)
{
HeaderExchange.Show();
Console.ReadLine();
}
}
运行结果:
生产者服务启动后,可以看到消息进入到队列中
从可视化工具中也可以看到两个消息根据规则进入到对应的队列中,消息一同时符合两个队列的规则,消息二符合HeaderExchangeAnyQueue队列的规则。所以最终HeaderExchangeAnyQueue队列中有两条消息,HeaderExchangeAllQueue队列中有一条消息。
启动消费者服务,可以看到第一条消息从两个不同的队列中各被消费了一次,第二条消息被消费一次。
总结:Header类型交换机不需要依赖key。更多的时候像这种key-value的键值,可能会存储在数据库中,就可以定义一个动态规则来拼装这个key-value,从而达到消息灵活转发到不同的队列中去。