PHP RabbitMQ tutorial (Three)

Publish / Subscribe

We are the one to create a work queue, and assumes the task of transmitting queue corresponds to a certain client. In this chapter we will do something completely different things - we will send a message to multiple consumers, also known as "publish / subscribe" model.

To illustrate this pattern, we will create a simple logging system (logging system, hereinafter referred to as the log system), which consists of two programs - the first is to send log information, and the second is to receive and print the log.

The system logs each receiving end of a program running will receive the information, so that you can run a receiving end put the logs saved to the hard disk, run the other receiving end to display the log to the screen in real time.

In essence, the content log is broadcast to all of the receiving end.

Switch

We sent in the previous chapters from a queue and receive messages, now that the introduction complete the RabbitMQ messaging model for everyone.

Let's quickly go over the back in the previous chapter contents:

>生产者是一个用来发送消息的程序

>队列是一个存储消息的缓冲区

>消费者是一个接收消息的程序

The core idea of ​​RabbitMQ messaging model is that the producers never be sent directly to any message queue, in fact, under normal circumstances the producers do not even know which queue the message should be sent to.

Producers can send a message to the switch, the switch is very simple. Receiving a message from a producer on the one hand, on the other hand to push the message queue. Exchange must know how to handle the received message is pushed to a queue? Pushed to multiple queues? Or discard the message. This rule is specified by the switch type (exchange type).

Here are a few types of switches: direct, topic, headers, fanout. Here we focus on the last -fanout, create a type of fanout switch, named logs.

$channel->exchange_declare('logs','fanout',false,false,false);

fanout switch is very simple, you can guess from the name of its functions, which all received messages broadcast to all it knows of the queue, that's what our log system needs to function.

Switch list

You can use rabbitmqctl command lists all the switches on the server:

sudo rabbitmqctl list_exchanges

Listing exchanges ...
        direct
amq.direct      direct
amq.fanout      fanout
amq.headers     headers
amq.match       headers
amq.rabbitmq.log        topic
amq.rabbitmq.trace      topic
amq.topic       topic
logs    fanout
...done.

There are some results amq. * And a number of unnamed switches, which are some of the switch created by default, they are now less likely to need to use.

Unnamed switch

In the previous section we know nothing of the switch until the queue can send messages. Probably because we were're using a null string, "" the definition of the default switch.

Recall how previously announced:

$channel->basic_publish($msg,'','hello');

Here is the default or unnamed switch: the message is routing_key value Here we use the default or nameless exchange: messages are routed to the queue with the name specified by routing_key, if it exists The routing key is the second argument. to basic_publish

You can now post messages to the queue.

$channel->exchange_declare('logs','fanout',false,false,false);
$channel->basic_publish($msg,'logs');

Temporary queue

Maybe you remember we used before a specified queue (remember hello task_queue queue and queue it?). You can name a queue is critical - we need to specify a worker to the same queue. When producers and consumers want to use the same queue to queue name it is very important.

But in our system log situation is different, we want to receive all the news, not just part of it, we are concerned with the latest news instead of the old, it is necessary to do two things.

First, when connected to RabbitMQ, needs an empty queue, you can manually create a random name of the queue, or, better approach is, let us randomly selected a server queue name.

Second, once lost connection with consumers, need to queue automatically deleted. Big Box   PHP RabbitMQ tutorial (c) the p->

In php-amqplib , when we create a name for the empty queue, in fact, created a generation is a non-persistent queue name.

list($queue_name, ,) = $channel->queue_declare("");

After performing the method, $ queue_name variable contains a string RabbitMQ generated. For example, perhaps this: amq.gen-JzTY20BRgKO-HjmUJj0wLg.

When the connection is closed, the queue will be deleted, because the queue is unique.

Binding (Bindlings)

A fanout exchange type and a queue we've created. Now we need to make the switch to send messages to the queue. The relationship between the switch and the call queue bindings (Binding)

$channel->queue_bind($queue_name,'logs');

Now, logs will switch message is appended to the queue.

Listed bindings (Listing bindings)

You can use rabbitmqctl list_bindings list all bindings being used exist.

Integrate

Producers sending log messages, and before the code looks no different, the most important change is that now wants to send a message to our logs exchanger, it is necessary to provide a routing_key when sending, but fanout type exchanger this value is negligible. Below is emit_log.php code.

<?php

require_once __DIR__ .'/verdor/autoload.php';
use PhpAmqpLibConnectionAMQPStreamConnection;
use PhpAmqpLibMessageAMQPMessage;

$connection = new AMQPStreamConnection('localhost',5672,'guest','guest');
$channel = $channel->channel();

$channel->exchange_declare('logs','fanout',false,false,false);

$data = implode(' ',array_slice($argv,1));

if(empty($data)) $data = "info:Hello World";
$msg = new AMQPMessage($data);

$channel->basic_publish($msg,'logs');

echo "[x]Sent ",$data,"n";

$channel->close();
$connection->close();
?>

(emit_log.php)

As you can see, the connection is established declares switch, this step is necessary because sending a message to a non-existent exchange is prohibited.

If the queue is not bound to the exchanger, information is lost, but which for us is if the consumer does not listen, we can safely discard the message.

receive_logs.php:

<?php

require_once __DIR__ .'/vendor/autoload.php';
use PhpAmqpLibConnectionQMAPStreamConnection;

$connection = new AMQPStreamConnection('localhost',5672,'guest','guest');
$channel = $connection->channel();

$channel->queue_bind($queue_name,'logs');

echo '[*] Waiting for logs. To exit press CTRL+C',"n";

$callback = function($msg){
	echo '[x]',$msg->body,"n";
};

$channel->basic_consume($queue_name,'',false,true,false,false,$callback);

whild(count($channel->callbacks)){
	$channel->wait();
}

$channel->close();
$connection->close();
?>

(receive_logs.php)

If you want to save the log to a file, you can enter the command

php receive_logs.php > logs_from_rabbit.log

If you want to see on the screen log, open a new terminal and run:

php receive_logs.php

Send log:

php emit_log.php

Use rabbitmqctl list_bindings can confirm that the code does create a binding and queue when running two receive_logs.php will see something like this:

sudo rabbitmqctl list_bindings
Listing bindings ...
logs    exchange        amq.gen-JzTY20BRgKO-HjmUJj0wLg  queue           []
logs    exchange        amq.gen-vso0PVvyiRIL2WoV3i48Yg  queue           []
...done.

For the interpretation of the results is very simple, send data logs exchangers to two servers specified queue, which is what we want to achieve.

Want to figure out how to monitor part of the message, go to Part IV.

Original Address: Publish / the Subscribe

Guess you like

Origin www.cnblogs.com/lijianming180/p/12099814.html