PHP Message Queuing

Source: Internet
Author: User
Tags sprintf rabbitmq

This article is mainly to share with you the PHP message queue in detail, I hope to help everyone, first we first understand what is Message Queuing.

1. What is Message Queuing

Message Queuing (English: Message queue) is an inter-process communication or a way of communicating between different threads of the same process

2. Why use Message Queuing

Message Queuing technology is a technique for exchanging information among distributed applications. Message Queuing can reside in memory or on disk, and queues store messages until they are read by the application. With Message Queuing, applications can execute independently, they do not need to know each other's location, or do not need to wait for the receiving program to receive this message before continuing execution.

3. What is the occasion for using Message Queuing

You first need to figure out the difference between Message Queuing and remote procedure calls, and when many readers consult me, I find that they need RPC (remote procedure Call) instead of Message Queuing.

Message Queuing has synchronous or asynchronous implementations, usually we use Message Queuing asynchronously, and remote procedure calls are mostly synchronous.

What is the difference between MQ and RPC? MQ typically passes an irregular protocol, which is defined by the user and implements store forwarding, whereas RPC is usually a private protocol, and the call procedure returns the result.

4. When to use Message Queuing

Synchronous requirements, remote procedure Call (PRC) is better for you.

asynchronous requirements, Message Queuing is better for you.

Currently, many Message Queuing software supports RPC functionality, and many RPC systems can also be called asynchronously.

Message Queuing is used to implement the following requirements

Store and forward

Distributed transactions

Publish a subscription

Content-based routing

Point-to-point connections

5. Who is responsible for handling Message Queuing

As a general practice, if a small project team can have a person implement, including message push, receive processing. If a large team typically defines a good message protocol and then each develops its own part, such as a team responsible for writing the Push Protocol section, the other team is responsible for writing the receive and processing sections.

So why don't we talk about the framing of message queues?

There are several benefits of framing:

Developers do not have to learn Message Queuing interfaces

Developers do not need to care about message push and receive

Developers push messages through a unified API

The developer's focus is on implementing business logic functions

6. How to implement the message queue framework

The following is an SOA framework developed by the author, which provides three interfaces, SOAP,RESTFUL,AMQP (RabbitMQ), that understand the framework and that you can easily expand further, such as adding XML-RPC, ZEROMQ, and so on.

Https://github.com/netkiller/SOA

This article speaks only about the Message Queue Framework section.

6.1. Daemon process

The message queue Framework is a local application (a command-line program) and we need to implement the daemon in order for him to run in the background.

https://github.com/netkiller/SOA/blob/master/bin/rabbitmq.php

Each instance processes a set of queues, the instantiation needs to provide three parameters, $queueName = ' queue name ', $exchangeName = ' interchange name ', $routeKey = ' route '

$daemon = new \framework\rabbitdaemon ($queueName = ' email ', $exchangeName = ' email ', $routeKey = ' email ');

The daemon needs to run with the root user, switch to a normal user after running, and create a process ID file to use when the process is stopped.

Daemon Core Code https://github.com/netkiller/SOA/blob/master/system/rabbitdaemon.class.php

6.2. Message Queuing protocol

A message protocol is an array that serializes or converts an array to a Message Queuing server, using a JSON-formatted protocol.

$msg = Array (' Namespace ' = ' Namespace ', "Class" and "e-mail", "Method" = "smtp", "Param" = = Array ($mail, $ Subject, $message, null));

Post-Serialization Protocol

{"Namespace": "single", "Class": "Email", "Method": "SMTP", "Param": ["netkiller@msn.com", "Hello", "Testhelloworld", NULL]}

The use of JSON format is considered universal, so that the push end can be used in any language. If compatibility is not considered, it is recommended to use binary serialization, such as Msgpack, which is more efficient.

6.3. Message Queuing processing

Message Queuing processing Core code

https://github.com/netkiller/SOA/blob/master/system/rabbitmq.class.php

So the processing of the message is done in the following section of code

$this->queue->consume (function ($envelope, $queue) {$speed = Microtime (true); $msg = $envelope->getbody (); $ result = $this->loader ($msg); $queue->ack ($envelope->getdeliverytag ()); Send ACK response manually//$this->logging->info (". $msg. $result) $this->logging->debug (' Protocol: '. $msg. '); $ This->logging->debug (' Result: '. $result. ' $this->logging->debug (' Time: '). (Microtime (True)-$speed).);

Public Function loader ($msg = NULL) is responsible for disassembling the protocol, then loading the corresponding class file, passing parameters, running methods, and feedback results.

Time can output how long it takes the program to run, which is useful for post-optimization.

Tips

Loader () can be further optimized by using multithreading to submit tasks to the thread pool each time it is called loader, so that Message Queuing can be processed in multithreading.

6.4. Testing

Test Code https://github.com/netkiller/SOA/blob/master/test/queue/email.php

<?php$queuename = ' example '; $exchangeName = ' email '; $routeKey = ' email '; $ mail = $argv [1]; $subject = $argv [2]; $message = Empty ($argv [3])? ' Hello world! ': '. $argv [3]; $connection = new Amqpconnection (Array (' host ' = ' 192.168.4.1 ', ' port ' = ' 5672 ', ' vhost ' = '/', ' login ' = ') Guest ', ' password ' = ' guest '), $connection->connect () or Die ("Cannot connect to the broker!\n"); $channel = new Amqpchannel ($connection), $exchange = new Amqpexchange ($channel); $exchange->setname ($exchangeName); $queue = new Amqpqueue ($channel); $queue->setname ($queueName); $queue->setflags (amqp_durable); $queue Declarequeue (); $msg = Array (' Namespace ' = ' Namespace ', "Class" = "Email", "Method" = "smtp", "Param" = Array ($mail, $subject, $message, null)) $exchange->publish (Json_encode ($msg), $routeKey);p rintf ("[x] Sent%s \ r \ n" , Json_encode ($msg)); $connection->disconnect (); 

Only a small number of test and demonstration programs are given here, if you have any questions, please go to the Profanity Group, or ask the public.

7. Multithreading

The above Message Queue Core code is as follows

$this->queue->consume (function ($envelope, $queue) {$msg = $envelope->getbody (); $result = $this->loader ($ msg); $queue->ack ($envelope->getdeliverytag ());});

This code production environment used for half a year, found that the efficiency is low. Some business fields are very fast, but they take longer to process and tend to queue up.

Increasing multithreading can make more efficient use of hardware resources and improve business processing power. The code is as follows

<?phpnamespace framework;require_once (__dir__. ') /autoload.class.php '), class Rabbitthread extends \threaded {private $queue;p ublic $classspath;p rotected $msg;p ublic function __construct ($queue, $logging, $msg) {$this->classspath = __dir__. ' /.. /queue '; $this->msg = $msg; $this->logging = $logging; $this->queue = $queue;} Public Function Run () {$speed = Microtime (true); $result = $this->loader ($this->msg); $this->logging->debug (' Result: '. $result. ' $this->logging->debug (' Time: '). (Microtime (True)-$speed).} privatepublic function Loader ($msg = null) {$protocol = Json_decode ($msg, true); $namespace = $protocol [' namespace '];$ class = $protocol [' class ']; $method = $protocol [' method ']; $param = $protocol [' param ']; $result = null; $classspath = $this- >classspath. ' /'. $this->queue. ' /'. $namespace. ' /'. Strtolower ($class). '. class.php ', if (Is_file ($classspath)) {require_once ($classspath);//$class = Ucfirst (substr ($request _uri, Strrpos ($ Request_uri, '/') +1)); (Class_exists ($class)) {if (method_exists ($class, $method)) {$obj = new $class, if (! $param) {$tmp = $obj. $method (); $result = Json_encode ($tmp ); $this->logging->info ($class. '. $method. ' ()');} else{$tmp = Call_user_func_array (Array ($obj, $method), $param); $result = (Json_encode ($tmp)); $this->logging-> Info ($class. '. $method. ' ("'. Implode ('", "', $param) ') ');}} else{$this->logging->error (' Object ' $class. ' and '. $method. ' is not exist. ');}} else{$msg = sprintf ("Object is not exist. (%s) ", $class); $this->logging->error ($msg);}} else{$msg = sprintf ("Cannot loading interface! (%s) ", $classspath); $this->logging->error ($msg);} return $result;}} Class RabbitMQ {Const LOOP = 10;protected $queue;p rotected $pool;p ublic function __construct ($queueName = ', $exchangeNam E = ', $routeKey = ') {$this->config = new \framework\config (' Rabbitmq.ini '); $this->logfile = __dir__. ' /.. /log/rabbitmq.%s.log '; $this->logqueue = __dir__. ' /.. /log/queue.%s.log '; $this->logging = new \framework\log\logging ($this->logfile, $debug =true); //. H:i:s$this->queuename= $queueName, $this->exchangename= $exchangeName, $this->routekey= $routeKey; $this->pool = new \pool ($this->config->get (' pool ') [' thread ']);} Public Function Main () {$connection = new \amqpconnection ($this->config->get (' rabbitmq ')); try {$connection- Connect (), if (! $connection->isconnected ()) {$this->logging->exception ("Cannot connect to the broker!". PHP_EOL);} $this->channel = new \amqpchannel ($connection), $this->exchange = new \amqpexchange ($this->channel); $this- >exchange->setname ($this->exchangename); $this->exchange->settype (Amqp_ex_type_direct); Direct type $this->exchange->setflags (amqp_durable); Long-lasting? $this->exchange->declareexchange () $this->queue = new \amqpqueue ($this->channel); $this Queue->setname ($this->queuename); $this->queue->setflags (amqp_durable); Long-lasting? $this->queue->declarequeue (); $tHis->queue->bind ($this->exchangename, $this->routekey); $this->queue->consume (function ($ Envelope, $queue) {$msg = $envelope->getbody (); $this->logging->debug (' Protocol: '. $msg. ');//$result = $ This->loader ($msg); $this->pool->submit (New Rabbitthread ($this->queuename, New \framework\log\logging ( $this->logqueue, $debug =true), $msg) $queue->ack ($envelope->getdeliverytag ()); }); $this->channel->qos (0,1);} catch (\amqpconnectionexception $e) {$this->logging->exception ($e->__tostring ());} catch (\exception $e) {$this->logging->exception ($e->__tostring ()); $connection->disconnect (); $this- >pool->shutdown ();}} Private Function Fault ($tag, $msg) {$this->logging->exception ($msg); throw new \exception ($tag. ': '. $msg);} Public Function __destruct () {}}
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.