Routing (routing)
(using Php-amqplib)
In the previous tutorial, we built a simple logging system. We were able to broadcast logs messages to many receivers.
Last time, we built a simple log system to broadcast messages to multiple receivers.
In this tutorial we "re going to add a feature to It-we" re going to make it possible to subscribe only to a subset of the Messages. For example, we'll be able to direct only critical error messages to the log file (to save disk space), while still bein G able to print all of the logs messages on the console.
This time we're going to add a feature up?? So that it can just listen to part of the message. For example, we can only indicate that a fatal error message is stored to the log file (stored to the hard disk), but all messages can still be printed in the console.
Bindings (bundle)
In previous examples we were already creating bindings. Recall code like:
For the last example, we have created a bundle. You may remember, as follows:
$channel->queue_bind ($queue _name, ' logs ');
A binding is a relationship between an exchange and a queue. This can being simply read As:the queue is interested in messages from this exchange.
The relationship between the exchanger and the queue is called bundling. It can be simply understood as: This queue is interested in the message of this particular exchanger.
Bindings can take an extra routing_key parameter. To avoid the confusion with a $channel:: Basic_publish parameter We "re going to call it a binding key. This is what we could create a binding with a key:
The bundle can set an additional Routing_key parameter. To avoid confusion with $channel:basic_publish parameters, we call it a bundle key (banding key). This is how we use key to create a bundle.
$binding _key = ' black '; $channel->queue_bind ($queue _name, $exchange _name, $binding _key);
The meaning of a binding key depends on the exchange type. The fanout exchanges, which we used previously, simply ignored its value.
The meaning of the binding key is the type of the exchanger. The previously used fanout type of exchanger would simply ignore this value.
Direct Exchange (directed switch)
Our logging system from the previous tutorial broadcasts all messages to all consumers. We want to extend this to allow filtering messages based on their severity. For example we want the script which was writing log messages to the disk to only receive critical errors, and not wast E disk space on warning or info log messages.
The previous log system broadcasts all messages to all consumers. We want to expand it?? Allows messages to be filtered based on severity. For example, we might want a script that persists a log to persist only fatal errors, and it will not waste hard disk space on warning and information (info) messages.
We were using a fanout exchange, which doesn ' t give us much flexibility-it ' s only capable of mindless broadcasting.
How much flexibility did we use with the fanout exchanger? It's just a headless broadcast.
We'll use a direct exchange instead. The routing algorithm behind a direct exchange is simple-a message goes to the queues whose binding key exactly matches The routing key of the message.
We will replace the fanout exchanger with a directional switch. The algorithm behind the directional switch is simple?? The message is pushed to: Message routing key and queue binding key exactly match the queue.
To illustrate, consider the following setup:
To clarify, think about the following structure:
In this setup, we can see the direct Exchange X with a queues bound to it. The first queue is bound with binding key orange, and the second have both bindings, one with binding key Blackand the other One with green.
On this structure, we can see that the switch X is bundled with two queues. The first queue is bundled with a binding key orange, the second has two bindings,
The first one uses the binding key black and the other one is green.
In such a, setup a message published to the exchange with a routing key orange would be routed to queue Q1. Messages with a routing key of Black or green would go to Q2. All other messages'll be discarded.
In this structure, messages sent to the switch with routing key oranges are routed to the queue Q1. Messages with black and green routing key will be entered into the Q2. All messages outside this will be discarded.
Multiple bindings (multiple bundle)
It is a perfectly legal to bind multiple queues with the same binding key. In our example we could add a binding between X and Q1 with binding key black. In this case, the direct exchange would behave like fanout and would broadcast the message to all the matching queues. A message with routing key black is delivered to both Q1 and Q2.
Bundling multiple queue hairs with the same binding key is not a problem. In our example, we can use black to create a bundle between X and Q1. In this case, the directional switch behaves like a fanout switch, broadcasting the message to all matching queues. Q1 and Q2 will receive a message with routing key black.
Emitting logs (log release)
We ' ll use the This model for our logging system. Instead of Fanout We ll send messages to a direct exchange. We'll supply the log severity as a routing key. That's the receiving script would be able to select the severity it wants to receive. Let's focus on emitting logs first.
We will apply this pattern to our log system. Unlike the fanout switch, we send a message to the specified exchanger. Log severity level as
Routing key. In that case, the receiving script can select the message you want to receive based on the severity level. Let's get the release log done first.
As always, we need to create an exchange first:
In the old way, you first create a switch:
$channel->exchange_declare (' direct_logs ', ' direct ', False, false, false);
And we ' re ready to send a message:
Ready to launch!!? Message--#
$channel->exchange_declare (' direct_logs ', ' direct ', False, false, false); $channel->basic_publish ($msg, ' Direct_logs ', $severity);
To simplify things we'll assume that's ' severity ' can be one of ' info ', ' warning ', ' error '.
For simplicity, we assume that the severity level can be one of the info,warning,error.
Subscribing (subscription)
Receiving messages would work just like in the previous tutorial, with one exception-we ' re going to create a new binding For each severity, we ' re interested in.
Receiving the message is the same as before, but a little different?? We have to create a bundle for each severity level of interest.
foreach ($severities as $severity) { $channel->queue_bind ($queue _name, ' direct_logs ', $severity);}
Putting it all together (fitness!!!) Are you coming?? haha
The code for emit_log_direct.php class:
Emit_log_direct.php Class Code:
Channel (); $channel->exchange_declare (' direct_logs ', ' direct ', False, false, false); $severity = $argv [1];if (Empty ( $severity)) $severity = "info"; $data = Implode (", Array_slice ($ARGV, 2)), if (Empty ($data)) $data =" Hello world! "; $msg = new Amqpmessage ($data), $channel->basic_publish ($msg, ' direct_logs ', $severity); echo "[X] Sent", $severity, ': ', $data, ' \ n '; $channel->close (); $connection->close ();? >
The code for receive_logs_direct.php:
receive_logs_direct.php Code:
Channel (); $channel->exchange_declare (' direct_logs ', ' direct ', False, false, false); list ($queue _name,,) = $ Channel->queue_declare ("", False, False, true, false); $severities = Array_slice ($argv, 1); if (empty ($severities)) { File_put_contents (' Php://stderr ', "Usage: $argv [0] [info] [WARNING] [error]\n"); Exit (1);} foreach ($severities as $severity) {$channel->queue_bind ($queue _name, ' direct_logs ', $severity);} Echo ' [*] waiting for logs. To exit Press CTRL + C ', ' \ n '; $callback = function ($msg) {echo ' [x] ', $msg->delivery_info[' Routing_key '], ': ', $msg-> ; body, "\ n";}; $channel->basic_consume ($queue _name, ", False, True, False, False, $callback), while (Count ($channel->callbacks ) {$channel->wait ();} $channel->close (); $connection->close ();? >
If you want to save only ' warning ' and ' error ' (and not ' info ') log messages to a file, just open a console and type:
If you want to store only warning and error messages to the log file, open console input:
$ php receive_logs_direct.php Warning error > Logs_from_rabbit.log
If you're like-to-see-all-the-log messages on your-screen, open a new terminal and do:
To view all the messages on the screen, open a new window to enter:
$ PHP receive_logs_direct.php Info Warning Error [*] waiting for logs. To exit Press CTRL + C
And, for example, to emit an error log message just type:
Yes, for example, to publish an error message, type:
$ php emit_log_direct.php Error "Run. Run. Or it'll explode. " [x] Sent ' error ': ' Run. Run. Or it'll explode. '
(Full source code for (emit_log_direct.php source) and (receive_logs_direct.php source))
Source code for emit_log_direct.php and receive_logs_direct.php
Move on to tutorial 5 to the Find out what to listen for messages based on a pattern.
Next we'll talk about how to listen to messages based on patterns.