此篇介绍rabbitmq的Topic
一、虽然Routing可以让我们用更适合于工作业务的方式操作消息队列,但还是存在一定的局限性,例如不能同时适应多个,比如我们不仅想要监听来自cron的错误消息,也要坚定kern的消息,而Topic类型的exchange可以解决这个问题。
二、Topic exchange
topic exchange 发送的消息,routing-key不能是任意的,必须是一个以…为界的列表,列表的单词可以是任意的。有效的routing-key例如:”stock.usd.nyse”, “nyse.vmw”, “quick.orange.rabbit”. 可以是多个单词组成,但是不能参过255个字符。
* (star) 可以取代其中的一个word.
# (hash) 可以取代0或多个word.
建立这样的一个routingKey : “< speed>.< colour>.< species>”.
Q1 对于颜色为orange的感兴趣,订阅了它
Q2 想监听关于rabbit是的所有和光宇lazy的一切.
如果我们使用一个或四个word,像”orange”或”quick.orange.male.rabbit”,因为匹配不到,消息会丢失
“lazy.orange.male.rabbit”, 则会匹配最后一个binding规则,会被分发给Q2
三、实例
publish
using System;
using System.Linq;
using RabbitMQ.Client;
using System.Text;
class EmitLogTopic
{
public static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "topic_logs",
type: "topic");
var routingKey = (args.Length > 0) ? args[0] : "anonymous.info";
var message = (args.Length > 1)
? string.Join(" ", args.Skip( 1 ).ToArray())
: "Hello World!";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "topic_logs",
routingKey: routingKey,
basicProperties: null,
body: body);
Console.WriteLine(" [x] Sent '{0}':'{1}'", routingKey, message);
}
}
}
subscribe
using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;
class ReceiveLogsTopic
{
public static void Main(string[] args)
{
var factory = new ConnectionFactory() { HostName = "localhost" };
using(var connection = factory.CreateConnection())
using(var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "topic_logs", type: "topic");
var queueName = channel.QueueDeclare().QueueName;
if(args.Length < 1)
{
Console.Error.WriteLine("Usage: {0} [binding_key...]",
Environment.GetCommandLineArgs()[0]);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
Environment.ExitCode = 1;
return;
}
foreach(var bindingKey in args)
{
channel.QueueBind(queue: queueName,
exchange: "topic_logs",
routingKey: bindingKey);
}
Console.WriteLine(" [*] Waiting for messages. To exit press CTRL+C");
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
var routingKey = ea.RoutingKey;
Console.WriteLine(" [x] Received '{0}':'{1}'",
routingKey,
message);
};
channel.BasicConsume(queue: queueName,
autoAck: true,
consumer: consumer);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
}