RabbitMQ学习之Routing(4)
上一节,是广播日志message到很多的receivers.
这节,我们讲订阅其中的一个子集。例如,我们想可以把危机的error message导到log file。而仍然可以打印所有的log messages到控制台。
这里使用到Direct exchage
Direct exchange
在使用fanout exchange时,没有很多的灵活性,它只是广播。
这节,我们将使用direct exchange . 在direct exchange背后的路由算法是简单的,即message会发送到一个binding key 正好匹配message的routing key的queue.
如图
我们可以看到,有两个queue绑定到exchange了。第一个queue是和binding key为orange的绑定的。并且第二个有两个bindings.一个是black,另一个是green.
带有routing key 为orange的发送到exchange的 message将会发送到queue Q1;
而routing key为black 和green的messages将会发送到Q2. 其他的messages会被丢弃。
Multiple binding(多重绑定)
如图,多重绑定,即一个binding key为black绑定到两个queue.
Emitting logs
我们会把日志严重级别(log severity)作为routing key. 那样,接收脚本将会选择它想要接收的严重级别进行接收。
channel.ExchangeDeclare(exchange: "direct_logs", type: "direct");
var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "direct_logs", routingKey: severity, basicProperties: null, body: body);
严重级别(Severity)
info, warning, error
Subscribing
接收程序跟之前大致一样,除了一个例外,我们将会为我们感兴趣的严重级别(serverity)创建一个新的binding.
var queueName = channel.QueueDeclare().QueueName; foreach(var severity in args) { channel.QueueBind(queue: queueName, exchange: "direct_logs", routingKey: severity); }
代码
EmitLogDirect.cs
using System;using System.Linq;using RabbitMQ.Client;using System.Text; class EmitLogDirect { 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: "direct_logs", //声明direct类型exchange type: "direct"); var severity = (args.Length > 0) ? args[0] : "info"; var message = (args.Length > 1) ? string.Join(" ", args.Skip( 1 ).ToArray()) : "Hello World!"; var body = Encoding.UTF8.GetBytes(message); channel.BasicPublish(exchange: "direct_logs", //发送routingkey 为severity的message routingKey: severity, basicProperties: null, body: body); Console.WriteLine(" [x] Sent '{0}':'{1}'", severity, message); } } Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); }
运行示例:
cd EmitLogDirect dotnet run error "Run. Run. Or it will explode."# => [x] Sent 'error':'Run. Run. Or it will explode.'
ReceiveLogsDirect.cs
using System;using RabbitMQ.Client;using RabbitMQ.Client.Events;using System.Text; class ReceiveLogsDirect { 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: "direct_logs", //声明direct类型exchange type: "direct"); var queueName = channel.QueueDeclare().QueueName; //声明带随机queue name的queue if(args.Length < 1) { Console.Error.WriteLine("Usage: {0} [info] [warning] [error]", Environment.GetCommandLineArgs()[0]); Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); Environment.ExitCode = 1; return; } foreach(var severity in args) { channel.QueueBind(queue: queueName, //绑定queue和exchange和特定值的routingkey exchange: "direct_logs", routingKey: severity); } Console.WriteLine(" [*] Waiting for messages."); var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); var routingKey = ea.RoutingKey; //接收的message的routing key Console.WriteLine(" [x] Received '{0}':'{1}'", routingKey, message); }; channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer); Console.WriteLine(" Press [enter] to exit."); Console.ReadLine(); } } }
使用示例:
cd ReceiveLogsDirect
dotnet run warning error > logs_from_rabbit.log
示例2
cd ReceiveLogsDirect dotnet run info warning error# => [*] Waiting for logs. To exit press CTRL+C
参考网址:
https://www.rabbitmq.com/tutorials/tutorial-four-dotnet.html