Turn: RabbitMQ and PHP (1) RabbitMQ and PHP (1)
In the project, RabbitMQ is used as a queue to process User message notifications. messages are generated by the front-end PHP code and processed in Python, which leads to code consistency problems, PHP and Python are required to modify the message definition. These two days I have spent some time studying how to use PHP to generate and process (consume) messages. When I checked the information, I found that there was very little information about the processing of message queues in PHP. it is necessary to talk about some areas that are confusing for beginners.
It is divided into two parts: 1. principle and Operation example of RabbitMQ; 2. service installation and how to use PHP as the daemon mode to process messages.
RabbitMQ is a popular open-source message queue system developed in erlang language. it fully implements AMPQ (Advanced Message queue protocol ). The website is on: http://www.rabbitmq.com/with tutorials and instance code (Python and Java ).
The AMPQ protocol is conceptually complex to meet various message queue requirements. First, rabbitMQ does not have any configuration by default. you need to connect the client and set the switch to work. Without figuring out these basic concepts, subsequent program design is prone to problems.
1. vhosts: virtual host
A RabbitMQ entity can have multiple vhosts. the user and permission settings are attached to vhosts. For common PHP applications, you do not need to set user permissions. you can simply use the default "/". you can use the default "guest ". A simple configuration example:
$ Conn_args = array (
'Host' => '2017. 0.0.1 ',
'Port' => '123 ',
'Login' => 'guest ',
'Password' => 'guest ',
'Vhost' => '/'
);
2. connection and channel: connection and channel
A connection refers to a physical connection. a client and a server have a connection. a connection can establish multiple channels, which can be understood as a logical connection. In general, it is enough to have a channel, and no more channels need to be created. Sample code:
// Create a connection and a channel
$ Conn = new AMQPConnection ($ conn_args );
If (! $ Conn-> connect ()){
Die ("Cannot connect to the broker! \ N ");
}
$ Channel = new AMQPChannel ($ conn );
3. exchange and routingkey: switch and route key
In order to distinguish different types of messages, the vSwitch and routing concepts are set. For example, send A message of Type A to A switch named 'C1', and send A message of type B to A switch of 'C2. When the client connects to C1 to process queue messages, only A type messages are obtained. Further, if there are too many messages of type A, you need to further differentiate them. for example, if A client only processes messages of type A for K users, routingkey is used for this purpose.
$ E_name = 'e _ linvo '; // switch name
$ K_route = array (0 => 'key _ 1', 1 => 'key _ 2'); // route key
// Create a vSwitch
$ Ex = new AMQPExchange ($ channel );
$ Ex-> setName ($ e_name );
$ Ex-> setType (AMQP_EX_TYPE_DIRECT); // direct type
$ Ex-> setFlags (AMQP_DURABLE); // persistence
Echo "Exchange Status:". $ ex-> declare (). "\ n ";
For ($ I = 0; $ I <5; ++ $ I ){
Echo "Send Message :". $ ex-> publish ($ message. date ('H: I: s'), $ k_route [I % 2]). "\ n ";
}
The code above shows that when a message is sent, it is enough to have a "switch. The sender does not need to worry about whether there is a corresponding processing queue behind the switch. Routingkey can be a null string. In the example, I used two keys to send messages alternately, so that the role of routingkey can be better understood below.
Vswitches have two important concepts:
A, type. Three types are available: Fanout is the simplest type. this model ignores routingkey. Direct is the most commonly used type and uses a definite routingkey. In this model, only messages of key_1 are received when 'key _ 1' is bound to receive messages. The last one is Topic. this mode is similar to Direct, but wildcard matching is supported, for example: 'key _ * ', key_1 and key_2 are accepted. The Topic looks good, but it may lead to less rigorous things. Therefore, Direct is recommended.
B. persistence. If a persistent vSwitch is specified, it can be rebuilt only when it is restarted. Otherwise, the client must re-declare and generate the vSwitch.
The persistence of vswitches is not the same as message persistence. Only messages in a persistent queue can be persisted. without a queue, messages are stored in no place. messages themselves also have a persistence mark during delivery, by default, messages delivered to persistent switches in PHP are persistent messages and do not need to be specified.
4. queue: queue
After talking about this, we can talk about queues. In fact, the queue is only for the receiver (consumer) and is created by the receiver as needed. Only when a queue is created will the switch send the newly received message to the queue. the switch will not include the message before the queue is created. In other words, before a queue is established, all messages sent are discarded. The following figure is clearer than the official RabbitMQ diagram ?? Queue is part of ReceiveMessage.
Next, let's take a look at the example of creating a queue and receiving messages:
$ E_name = 'e _ linvo '; // switch name
$ Q_name = 'Q _ linvo '; // queue name
$ K_route = ''; // route key
// Create a connection and a channel
$ Conn = new AMQPConnection ($ conn_args );
If (! $ Conn-> connect ()){
Die ("Cannot connect to the broker! \ N ");
}
$ Channel = new AMQPChannel ($ conn );
// Create a vSwitch
$ Ex = new AMQPExchange ($ channel );
$ Ex-> setName ($ e_name );
$ Ex-> setType (AMQP_EX_TYPE_DIRECT); // direct type
$ Ex-> setFlags (AMQP_DURABLE); // persistence
Echo "Exchange Status:". $ ex-> declare (). "\ n ";
// Create a queue
$ Q = new AMQPQueue ($ channel );
$ Q-> setName ($ q_name );
$ Q-> setFlags (AMQP_DURABLE); // persistence
// Bind the vSwitch and queue, and specify the route key
Echo 'queue Bind: '. $ q-> bind ($ e_name, $ k_route). "\ n ";
// Receives messages in blocking mode
Echo "Message: \ n ";
$ Q-> consume ('processmessage', AMQP_AUTOACK); // automatic ACK response
$ Conn-> disconnect ();
/**
* Consumption callback function
* Process messages
*/
Function processMessage ($ envelope, $ queue ){
Var_dump ($ envelope-> getRoutingKey );
$ Msg = $ envelope-> getBody ();
Echo $ msg. "\ n"; // process the message
}
As shown in the preceding example, a vSwitch can be created either by the message sender or by the message consumer.
After creating a queue (line: 20), you need to bind the queue to the line: 25 queue on the switch to work. The routingkey is also specified here. Some documents are written as bindingkey. In fact, it is easy to confuse the two nouns.
There are two ways to process messages:
A, one-time. $ Q-> get ([...]) is used to return immediately no matter the message cannot be obtained. this method is usually used to process the message queue by polling;
B. blocking. Use $ q-> consum (callback, [...]) the program enters the continuous listening state. each time a message is received, the function specified by callback is called once until a callback function returns FALSE.
For more information about callback, PHP call_back supports arrays, for example, $ c = new MyClass (); $ c-> counter = 100; $ q-> consume (array ($ c, 'myfunc') so that you can call your own processing class. The parameter definition of myfunc in MyClass is the same as processMessage in the previous example.
In the preceding example, $ routingkey = ''is used to receive all messages. We can change it to $ routingkey = 'key _ 1'. we can see that only the content with the routingkey set to key_1 is displayed in the result.
Note: routingkey = 'key _ 1' and routingkey = 'key _ 2' are two different queues. Assume that both client1 and client2 are connected to the key_1 queue. after a message is processed by client1, it is not processed by client2. Routingkey = ''is an alternative. client_all is bound to''. after all messages are processed, no messages will be sent to client1 and client2.
In programming, you need to plan the exchange name and how to use the key to separate different types of tags and insert the message sending code where the message is generated. Backend processing: one or more clients can be started for each key to improve the timeliness of message processing. The following section describes how to use PHP to process multi-threaded messages.
For more message models, see: http://www.rabbitmq.com/tutorials/tutorial-two-python.html