Message Queuing deals with problems with background tasks
projects often have background running tasks, such as sending mail, because to connect to the mail server, often takes 5-10 seconds or even longer, if you can give users a successful prompt information, and then slowly in the background to handle the operation of sending mail, it is clear that there will be a better user experience.
In order to achieve similar requirements, the general implementation method in Web projects is to use Message Queuing, such as MEMCACHEQ,RABBITMQ, etc., are well-known products.
Message Queuing is simply one of the simplest advanced first out queues, a member of a queue is a piece of text. It's because Message Queuing is so simple that when you're holding a message queue, it's a bit of a sense of not being able to do it, because it's just a task that sends a message, and it's a lot of questions:
- Message Queuing can only store string-type data, and how can a "task" such as sending a message be converted to a "message" In a message queue?
- Message Queuing is responsible for the storage and access of data, and it cannot execute any program, so how do we extract the data from one of the message queues and then convert the data back to the task and execute it.
- We cannot predict when the message queue will have data generation, so our task execution program also needs to have the ability to monitor Message Queuing, a daemon that resides in the background.
- The General Web application PHP is run as CGI and cannot reside in memory. We know that PHP also has the CLI mode, so how efficient is the daemon to be implemented in PHP CLI?
- When the daemon is running, can the Web application interact with the daemon to enable the function of the process to be opened/killed and to get the running status of the process?
The design and role division of Resque for backstage tasks
The best answer I can find so far, not from PHP, but from Ruby's project Resque, is that Resque clearly and simply solves a series of problems with background tasks, and Resque's design is also clone to Python, PHP, Nodejs and other languages: such as Python under the pyres and PHP php-resque, and so on, there are various language versions of the Resque implementation, and in this blog, we certainly want to use the PHP version as an example to explain how to run a background task with Php-resque, There may be some details that are not the same as the Ruby version, but the PHP version is the subject of this article.
This is how Resque solves these problems:
Role partitioning for background tasks
in fact, from the above problem already can see, rely on a message queue is unable to solve all problems, need new role intervention. In Resque, a background task is abstracted to be done together by three roles:
- Job | Task: A job is a task that needs to be done in the background, such as sending a message for example in this article, can be abstracted as a job. A job is a class in Resque.
- Queue | Queue: That is, the message queue above, in Resque, the queue is implemented by Redis. Resque also provides a simple queue manager that enables functions such as job insert/fetch queues.
- Worker | Performer: is responsible for removing the job from the queue and executing it, which can be run in the background as a daemon.
So based on this division, a background task under the Resque of the basic process is this:
- Write a background task as a separate class, this class is a job.
- Where you need to use a daemon, the system places the name of the job class and the required parameters in the queue.
- Open a worker on a command-line basis and specify the queues that the worker needs to process by using parameters.
- The worker runs as a daemon and periodically checks the queues.
- When there is a job in the queue, the worker takes out the job and runs it, which is instantiating the job class and executing the methods in class.
At this point you can complete the full run of a background task.
In Resque, there is also an important design: A worker who can handle a queue or many queues, and can speed up the execution of a queue by increasing the number of worker processes/threads.
Installation of Php-resque
what needs to be explained in advance is that, due to the process of opening up and management, Php-resque use the PHP pcntl function, so can only run under Linux, and need PHP to compile the PCNTL function. If you want to do the same thing with windows, you can look for other language versions of Resque, and PHP is very unsuitable for background tasks under Windows.
Take Ubuntu12.04lts as an example, Ubuntu installed PHP with APT has already compiled the PCNTL function by default, without any configuration, the following instructions are root account
Install Redis
Apt-get Install Redis-server
Install composer
Apt-get Install Curl
cd/usr/local/bin
curl-s http://getcomposer.org/installer | php
chmod a+x Composer.phar
alias composer= '/usr/local/bin/composer.phar '
Use composer to install Php-resque
Suppose the web directory is/opt/htdocs
Apt-get install git git-core
cd/opt/htdocs
git clone git://github.com/chrisboulton/php-resque.git
CD Php-resque
Composer Install
The use of Php-resque
1. Preparation of a worker
in fact, Php-resque has given a simple example, the demo/job.php file is the simplest job:
Class Php_job
{public
function perform ()
{sleep
();
Fwrite (STDOUT, ' hello! ');
}
This job is to output characters to stdout in 120 seconds hello!
In the design of Resque, a job must have a perform method, and the worker will automatically run this method.
2. Insert job into queue
Php-resque also gives the simplest insertion queue implementation demo/queue.php:
if (Empty ($argv [1])) {
die (' Specify ' the name of a job to add. e.g, PHP queue.php php_job ');
}
Require __dir__. '/init.php ';
Date_default_timezone_set (' GMT ');
Resque::setbackend (' 127.0.0.1:6379 ');
$args = Array (
' time ' => time (),
' array ' => array (
' test ' => ' Test '),
);
$jobId = Resque::enqueue (' Default ', $ARGV [1], $args, true);
echo "Queued job". $jobId. " \ n ';
In this example, queue.php needs to run CLI, insert the first parameter received by the CLI as the job name, and plug in the queue named ' Default ', and output the job Id of the queue that was just inserted into the screen. In the terminal input:
PHP demo/queue.php Php_job
As a result, you can see the on-screen output:
Queued Job B1f01038e5e833d24b46271a0e31f6d6
That is, the job has been added successfully. Note that the job name here is the same as the job class name we write: Php_job
3. View Job performance
Php-resque also provides an example of viewing the job's running status, running directly:
PHP demo/check_status.php B1f01038e5e833d24b46271a0e31f6d6
You can see the output as:
Tracking status of B1f01038e5e833d24b46271a0e31f6d6. Press [break] to stop.
Status of B1f01038e5e833d24b46271a0e31f6d6 Is:1
The job status we just created is 1. In Resque, a job has the following 4 states:
- resque_job_status::status_waiting = 1; Waiting
- resque_job_status::status_running = 2; (under Implementation)
- resque_job_status::status_failed = 3; Failed
- Resque_job_status::status_complete = 4; End
Because no worker is running, the job you just created is still waiting.
4. Run worker
this time we write demo/resque.php directly:
<?php
date_default_timezone_set (' GMT ');
Require ' job.php ';
Require '.. /bin/resque ';
You can see that a worker needs at least two parts:
You can include the job class file directly, or you can use the automatic loading mechanism of PHP to specify the path of the job class and implement the automatic load.
Contains the default worker:bin/resque for Resque
To run in a terminal:
Queue=default PHP demo/resque.php
The previous Queue section is set environment variables, and we specify that the current worker is only responsible for handling the default queue. You can also use
queue=* PHP demo/resque.php
To process all queues.
Run after output as
#!/usr/bin/env PHP
* * * starting worker
Check with PS command:
You can see that a PHP daemon is already running
1000 4607 0.0 0.1 74816 11612 pts/3 s+ 14:52 0:00 php demo/resque.php
Use the previous check job instructions again
PHP demo/check_status.php B1f01038e5e833d24b46271a0e31f6d6
We'll see you in 2 minutes.
Status of B1f01038e5e833d24b46271a0e31f6d6 Is:4
The task is already running, and the output should be visible on the screen hello!