Prerequisite
This tutorial assumes that RABBITMQ is already installed and is running on a localhost
standard port (5672). If you use a different host, port, or certificate, you need to adjust the connection settings.
Where to get help
If you're having trouble reading this tutorial, you can contact us via the mailing list.
Theme
Use. NET client)
in tutorial [4], we improved our log system. We replaced the exchanger with a direct
switch that can only dull the broadcast message fanout
, so that we could have a selective receive log.
Although the use direct
of a switch improves our system, it still has limitations-it cannot be routed based on multiple criteria.
In our log system, we may not only subscribe to the log based on the severity of the log, but may also subscribe to the log based on the log distribution source. Perhaps you have learned this concept from the Unix syslog tool, and the Syslog tool can be used to route logs both based on severity (Info/warn/crit ... ) also based on the device (Auth/cron/kern ... Of
This mechanism gives us a lot of flexibility-we can listen to only cron
the critical error logs from, while listening to kern
all the logs from.
To implement this feature in our log system, we need to learn more complex topic
switches.
Topic Switching Device
A message sent to a topic
switch cannot be arbitrarily specified routing key
, it must be a list of words separated by points, which can be arbitrary, but typically specify some message-related attributes in it. See some examples of legitimate routing keys:,,, the stock.usd.nyse
nyse.vmw
quick.orange.rabbit
routing key can contain any number of words, but cannot exceed the upper limit of 255 bytes.
binding key
must also be in the same form, the topic
logic behind the switch is similar to the direct
switch-the message sent with the specified routing key is distributed to all queues that match its binding key. However, for binding keys, there are two important special cases to note:
*
(asterisks) can be substituted for a single word.
#
(hash) can be used instead of 0 or more words.
The example is the simplest explanation for the above:
In this example, the messages we intend to send are all used to describe the animals, which are sent using a routing key consisting of three words (two dots). In the routing key, the first word is used to describe the speed of action, the second is the color, and the third is the species, namely: <speed>.<colour>.<species>
.
We have created three bindings: Q1 binds the key .orange.
, Q2 binds the key *.*.rabbit
and lazy.#
.
These bindings can be summed up as:
- Q1 is interested in all the orange animals.
- Q2 is interested in rabbits and all the slow-moving animals.
Messages that are route keys are quick.orange.rabbit
sent to both queues, and messages are lazy.orange.elephant
sent to both queues. In addition, quick.orange.fox
only the first queue is entered, and lazy.brown.fox
only the second queue is entered. lazy.pink.rabbit
will only be sent to the second queue once, although it matches two bindings (avoids message duplication). quick.brown.fox
there is no matching binding, so it will be discarded.
What happens if we break the Convention and send a message that uses one or four words (for example: orange
and quick.orange.male.rabbit
) as a routing key? The answer is that these messages will be discarded because there is no match to any bindings.
However, in addition, for example, the route key is a lazy.orange.male.rabbit
message, although it has four words, it will match the last binding and will be sent to the second queue.
Topics Switching device
topic
The function of the exchanger is very powerful, it can show some other switch behavior.
When a queue is bound to a key #
(hash), it ignores the routing key and receives all messages, which is like a fanout
switch.
When special characters *
(asterisks) and #
(hashes) are not used in bindings, topic
the exchanger behaves like a direct
switch.
Grouped together
We are going to use a switch in our log system topic
, first assuming that the log's routing key consists of two words: <facility>.<severity>
.
The code is almost identical to the code in the previous tutorial.
EmitLogTopic.cs
The code:
Using system;using system.linq;using rabbitmq.client;using system.text;class emitlogtopic{public static void Main (Stri Ng[] 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); } }}
Code for
ReceiveLogsTopic.cs
:
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:co Nsumer); Console.WriteLine ("Press [Enter] to exit."); Console.ReadLine (); } }}
Please run the following example:
To receive all logs:
cd ReceiveLogsTopicdotnet run "#"
To receive kern
all logs from a device:
cd ReceiveLogsTopicdotnet run "kern.*"
Or, if you only want to listen to critical
the log at the level:
cd ReceiveLogsTopicdotnet run "*.critical"
You can create multiple bindings:
cd ReceiveLogsTopicdotnet run "kern.*" "*.critical"
To issue a log using a routing key kern.critical
:
cd EmitLogTopicdotnet run "kern.critical" "A critical kernel error"
Hopefully running these programs will make you enjoy yourself. Note that these codes do not have any presets for routing keys and binding keys, and you can try to use more than two routing key parameters.
(full source of EmitLogTopic.cs and ReceiveLogsTopic.cs)
Next, in tutorial [6], you will learn how to call a round trip message as a remote procedure.
Written in the last
This article is translated from the RABBITMQ official Tutorial C # version. If there is any discrepancy between the contents of this article and the official, please take the official latest content as the subject. The level is limited, translation is not good please forgive me, if there are translation errors please correct me.
-
Source Link: RabbitMQ tutorial-topics
-
Lab Environment: RabbitMQ 3.7.4,. NET Core 2.1.3, Visual Studio Code
/li>
-
Last update: 2018-09-06