In the previous tutorial, we improved our logging system. We use the direct type forwarder to enable the receiver to perform selective receiving logs, rather than fanout, which can only be transmitted without the brain.
Although our system has been improved with the direct type, it still has some limitations-it cannot be routed based on multiple criteria.
In our logging system, we may be able to subscribe not only to the severity of the log, but also to the source that sent the log. You may understand this concept from the Unix tool syslog, which is based on severity (Info/warn/crit ...). and equipment (Auth/cron/kern ...). ) forward the log.
This gives us a lot of flexibility-we may want to subscribe to a serious error from cron, or we can listen to all the logs of Kern.
To implement the above requirements in our system, we need to learn a slightly more complex topic type of forwarder (topic Exchange) topic Forwarding (topic Exchange)
Messages sent to a forwarder of the subject type cannot be arbitrarily set the selection key (Routing_key)-It must be a list of words separated by dots. These words can be anything, but usually they specify some of the features associated with the message. Examples of several valid routing keys: Stock.usd.nyse,nyse.vmw,quick.orange.rabbit. There can be any number of words in the routing key, up to 255 bytes.
The binding key must also be in the same form. The logic behind the forwarder of the subject type is similar to the direct type forwarder: A special selection key is forwarded to the queue where the binding key matches. Note that there are two special situations with respect to binding keys. :
* (STAR) can replace a word.
# (hash) can replace 0 or more words.
In one example, the simplest explanation is:
In this example, we will send all the messages that describe the animal. The message will append a select key that will be used by three word identifiers (two dots). The first word identifier describes the speed, the second word identifier describes the animal's color, and the third word identifier describes the animal's species:<speed>.<color>.<species>.
We created three bindings: Q1 binding Keys *.orange.* and Q2 with *.*.rabbit and lazy. #绑定.
These bindings can be summed up as:
Q1 is interested in all the orange animals.
Q2 wanted to hear all about the rabbit and everything about the lazy animal.
A message with the Quick.orange.rabbit selection key will be forwarded to two queues. Messages with Lazy.orange.elephant will also be forwarded to two queues. On the other hand, Quick.orange.fox will only go to Q1, and Lazy.brown.fox can only be forwarded to Q2. Lazy.pink.rabbit will only be forwarded to Q2 once, although it matches two binding keys. Quick.brown.fox cannot match any of the binding keys, so it will be discarded.
If we violate our convention, send a select key of one or four identifiers, similar to: Orange,quick.orange.male.rabbit, these selection keys cannot match any of the binding keys, so messages will be discarded.
Lazy.orange.male.rabbit, on the other hand, can be forwarded to Q2, although it is four identifiers, and lazy. #匹配. Topic Exchange
The transponder of the subject type is very powerful and can implement other types of forwarders.
when the queue is bound to the ' # ' (hash) binding, it receives all messages, regardless of the routing key, similar to the ' fanout ' type forwarder.
when special characters ' * ' (asterisk) and ' # ' (hash) are not used in bindings, the subject forwarder will resemble a direct type forwarder.
a complete example
We will use the topic forwarder in our logging system. We will start with a working assumption that the log selection key will have two words:<facility>.<severity>.
Code for EmitLogTopic.cs:
Using System;
Using System.Linq;
Using Rabbitmq.client;
Using System.Text; Class Emitlogtopic {public static void Main (string[] args) {var factory = new ConnectionFactory () {Host
Name = "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); }
}
}
ReceiveLogsTopic.cs Code:
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, Noack:true, Consumer:co
Nsumer);
Console.WriteLine ("Press [Enter] to exit");
Console.ReadLine (); }
}
}
Run the following example:
Receive all the logs:
CD receivelogstopic
dotnet Run "#"
Receive all logs from Device Kern:
CD receivelogstopic
dotnet Run "kern.*"
Or if you only want to receive a log of critical:
ReceiveLogsTopic.exe "*.critical"
You can create multiple bindings:
CD receivelogstopic
dotnet Run "kern.*" "*.critical"
and use the Select key kern.critical type to issue the log:
CD emitlogtopic
dotnet Run "kern.critical" "A Critical kernel Error"