PHP Implementation Timer Task (timer) ____php

Source: Internet
Author: User
Tags message queue time interval

This article explains the PHP Implementation Timer task (timer)

Timer task, in the Web application is more common, how to use PHP to implement the timer task, there are roughly two scenarios: 1 Use the crontab command, write a shell script, in the script to call the PHP file, and then execute the script regularly, 2 with the use of Ignore_user_abort () and Set_time_limit () to run the script out of the browser. The former is the use of Linux features, and PHP itself is not much of a relationship, the latter use of limited scenarios, and can only be triggered by an HTTP request the script, after execution exit. So how do we use pure PHP to achieve pure timer tasks, and can adapt to the task of understanding the business needs.

Basic knowledge

This program is developed under Linux and runs in CLI mode, which is a brief introduction to basic knowledge.

cli:php command line mode, common Web applications using the FPM;
Process: Process is the basic unit of the program operation, the process is independent operation and Non-interference, there is a separate operating space, each process has a process control block;
Interprocess communication: Now that the process is running independently, we need a mechanism to guarantee the exchange of different process information, inter-process communication mainly includes: Pipeline, IPC (shared memory, signal, message queue), socket;
PCNTL extension: A process extension of PHP, mainly use the Pcntl_alarm () function, please refer to the official website for more information.

Implementation principle

Use a three-dimensional array to save all tasks that need to be performed, the first index is the timestamp, the value is the method to perform the task, the callback parameter, and so on, the specific array form is as follows:

Array (
' 1438156396 ' => Array (
1,array (' Class ', ' Func '), Array (), true),
Description:
1 438156396 timestamp
Array (1,array (' Class ', ' Func '), Array (), true)
argument in sequence: execution interval, callback function, arguments passed to the callback function, persisted ( Ture is kept in the data, or deleted once after execution.

These tasks can be methods of any class. Since it is a timed task, we need a similar time, this scheme uses semaphores to do, every second to the current process to send SIGALRM signal, and capture the signal, triggering signal processing functions, loop through the data, to determine whether there is the current times need to perform tasks. If so, it is triggered by a callback and passes the parameter to the method.

<?php/** * Timer/class Timer {//Save all Scheduled Tasks public static $task = Array ();
 
   Regular interval public static $time = 1; /** * Open service * @param $time int */public static function run ($time = null) {if ($time) {self:: $tim
    e = $time;
    } self::installhandler ();
   Pcntl_alarm (1); /** * Registration Signal processing function */public static function Installhandler () {pcntl_signal (SIGALRM, Array (' Timer ', ' Signa
   Lhandler '));
   /** * Signal processing function */public static function Signalhandler () {self::task ();
   Once the signal event is executed, the next Pcntl_alarm (self:: $time) is triggered.
    /** * Execute callback/public static function task () {if (Empty (self:: $task)) {//No task, return returns;
   
     foreach (self:: $task as $time => $arr) {$current = time (); foreach ($arr as $k => $job) {//traverse each task $func = $job [' func '];/* callback function//$argv = $job [' argv '];/* callback function argument * /$interval = $job [' interval ']; /* Time interval * * $persist = $job [' persist ']; /* Persistent/if ($current = = $time) {//Current time has execute task//Call callback function, and pass parameter Call_user_func_array ($func, $ar
      
      GV);
       Delete the task unset (self:: $task [$time] [$k]);
       if ($persist) {//If persisted, the array is written, waiting for the next wake-up self:: $task [$current + $interval] = $job;
    } if (Empty (self:: $task [$time])) {unset (self:: $task [$time]);
   }}/** * Add task/public static function Add ($interval, $func, $argv = Array (), $persist = False)
    {if (Is_null ($interval)) {return;
   $time = time () + $interval; Write timed Task self:: $task [$time] = Array (' func ' => $func, ' argv ' => $argv, ' interval ' => $interval, ' persist ' =>$
   persist);
   /** * Delete all timer tasks */Public Function Dellall () {self:: $task = Array (); }
 }

This is the core of the timer class, there is a static variable to save all the tasks that need to be performed, why is this static? Everyone thinks for themselves. When the process receives the SIGALRM signal, triggers the Signalhandler function, then sequentially iterates through the array to see if there is a task to be performed at the current time. There is a callback, and the parameters are passed, delete the current job, and then check whether you want to do a persistent task, continue to write the current job to the event array, wait for the next trigger, and finally set an alarm signal for the current process

<?php
 
 class Dojob
 {public
  function job ($param = Array ())
  {
   $time = time ();
   echo "Time: {$time}, Func:". Get_class (). "::". __function__. " (". Json_encode ($param).") \ n ';
  }
 }
This is a callback class and function, to facilitate the description, adding a lot of debugging information. The timer class and the callback are all there, so let's see what the use scenario is.
<?php
 
 require_once (__dir__.) /timer.php ");
 Require_once (__dir__.) /dojob.php ");
 
 
 Timer::d ellall ();
 
 Timer::add (1, Array (' dojob ', ' job '), Array (), true);
 
 Timer::add (3, Array (' dojob ', ' job '), Array (' A ' =>1), false);
 
 echo "Time start:". Time (). \ n ";
 Timer::run ();
 
 while (1)
 {sleep
  (1);
  Pcntl_signal_dispatch ();
 }

The code is very short, there are two jobs registered here, then run the timer, in an infinite loop to catch the signal trigger action, if not capture will not trigger the registered handler function. Such a self circulation timer is developed. The results are as follows:

  

As with the tasks added to our scenario class, two tasks were performed at 90, a job with no parameters persisted, a job with parameters for Non-persistent, and then the Non-persistent job was no longer executed.

Summarize

1. Before receiving the signal, the current process cannot exit. Here I used the condition that the loop is always true. In our actual production environment, we need to create such a prerequisite, for example, we have a set of services that are always running, whether it is IO access, wait for the socket link, etc. The current service will not terminate, even if the process is blocking the problem, this scenario, that is, there is a running service to use.
2, the current PHP only support the trigger in seconds, do not support a smaller time unit, for the bit timing task is basically enough


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.