Pure PHP Implementation Timer Task (timer), PHP implementation Timers timer
Timer tasks, common in Web applications, how to use PHP to implement timer tasks, there are roughly two scenarios: 1. Use the crontab command, write a shell script, invoke the PHP file in the script, and then execute the script on a regular basis, 2) with Ignore_user_abort () and Set_time_limit () to make the script run 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 to the script, after execution exit. So how do we use pure PHP to achieve purely timer tasks, and to adapt to the business needs of understanding the task?
Basic knowledge
This program is developed under Linux and runs in CLI mode, which is a brief introduction to the basics.
- cli:php command-line mode, common Web applications use FPM;
- Process: The process is the basic unit of program operation, the process is independent and non-interference, there is a separate running space, each process has a process control block;
- interprocess communication: Since the process is running independently, we need a mechanism to ensure the exchange of different process information, inter-process communication mainly include: Pipeline, IPC (shared memory, signal , Message Queuing), sockets;
- PCNTL extension: A process extension of PHP, mainly used in the Pcntl_alarm () function, detailed information please check the official website.
Implementation principle
Use a three-dimensional array to save all the tasks that need to be performed, the first index is a timestamp, the value is the method to perform the task, the callback parameter, and so on, the following array form:
Array (array(Array (1,arraytrue), )) Description : 1438156396 timestamp array(1,arrayarraytrue) The parameters are: execution interval, callback function, parameters passed to the callback function, whether persisted (Ture is persisted in the data, or deleted after execution)
These tasks can be methods of any class. Since it is a timed task, we need a similar to the timing of the East, this scheme uses the semaphore to do, every second to the current process to send SIGALRM signal, and capture the signal, trigger signal processing function, loop through the data, to determine whether there is the current time to perform the task. If any, it is triggered by a callback method, and the parameter is passed to the method.
1
Php2 /**3 * Timer4 */5 classTimer6 {7 //Save all Scheduled Tasks8 Public Static $task=Array();9 Ten //Timing Interval One Public Static $time= 1; A - /** - * Open Service the * @param $time int - */ - Public Static functionRun$time=NULL) - { + if($time) - { +Self::$time=$time; A } atSelf::Installhandler (); -Pcntl_alarm (1); - } - /** - * Register signal processing function - */ in Public Static functionInstallhandler () - { toPcntl_signal (SIGALRM,Array(' Timer ', ' Signalhandler ')); + } - the /** * * Signal processing function $ */Panax Notoginseng Public Static functionSignalhandler () - { theSelf::task (); + //Once a signal event is executed, the next one is triggered APcntl_alarm (self::$time); the } + - /** $ * Execute callback $ */ - Public Static functionTask () - { the if(Empty(Self::$task)) -{//no task, returnWuyi return ; the } - foreach(Self::$task as $time=$arr) Wu { - $current= Time(); About $ foreach($arr as $k=$job) -{//Traverse each task - $func=$job[' Func '];/*callback function*/ - $argv=$job[' argv '];/*callback function Parameters*/ A $interval=$job[' interval '];/*time interval*/ + $persist=$job[' persist '];/*Persistence of*/ the - if($current==$time) ${//current time has an execution task the the //Call the callback function and pass the parameter the Call_user_func_array($func,$argv); the - //Delete the task in unset(Self::$task[$time][$k]); the } the if($persist) About{//if persisted, the array is written, waiting for the next wake-up theSelf::$task[$current+$interval][] =$job; the } the } + if(Empty(Self::$task[$time])) - { the unset(Self::$task[$time]);Bayi } the } the } - - /** the * Add Task the */ the Public Static functionAdd$interval,$func,$argv=Array(),$persist=false) the { - if(Is_null($interval)) the { the return; the }94 $time= Time()+$interval; the //Write timed Tasks theSelf::$task[$time][] =Array(' func ' =$func, ' argv ' =$argv, ' interval ' =$interval, ' persist ' =$persist); the }98 About /** - * Remove all timer tasks101 */102 Public functionDellall ()103 {104Self::$task=Array(); the }106}
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? We think for ourselves. When the process accepts the SIGALRM signal, it triggers the Signalhandler function, and then iterates through the array to see if there is a task to be performed at the current time. Have a callback, pass the parameters, delete the current job, and then check whether to do the persistence task, then continue to write the current job to the event array to wait for the next trigger, and then set an alarm signal for the current process. It can be seen that this timer, as long as the trigger will be triggered from the inside again, the purpose of the loop.
1
PHP 2 3class dojob 4{ 5public function$paramarray()) 6 { 7 $time Time (); 8 Echo "Time: {$time}, Func:". Get_class ()."::". __function__. " (". Json_encode ($param).") \ n "; 9 }ten }
This is a callback class and function, to facilitate the description, adding a lot of debugging information. The timer class and callbacks are all there, so let's see what the usage scenario is.
1 !--?
php
2
3
require_once (__dir__. " /timer.php "
);
4
require_once (__dir__. " /dojob.php "
);
5
6
7 Timer::
dellall ();
8
9 timer::add (1,
array (' dojob ', ' job '),
array (),
True
);
Ten
one timer::add (3,
array (' dojob ', ' job '),
array (' a ' =>1),
false
);
echo "time start:".
Time ()." \ n "
;
Timer::
run ();
while (1
)
+
{
/ Span>sleep (1
);
pcntl_signal_dispatch ();
}
The code is very short, registering two jobs here, then running the timer, capturing the signal trigger action in an infinite loop, and failing to capture a handler function that will not trigger a pre-registration. Such a self-looping timer was developed. The results are as follows:
Like the task we added in our scene class, we performed two tasks at 90, a job with no parameters persisted, a job with non-persisted parameters, and then non-persisted jobs were no longer executed.
Summarize
- The current process cannot exit until the signal is received. Here I use a loop where the condition is always true. In our actual production environment, we need to create such a prerequisite, for example, we have a set of services, these services are always running, whether it is IO access, waiting for the socket link and so on, the current service will not terminate , even if the process is blocked, this scenario is used in a service that has been running.
- Currently PHP only supports triggers in seconds, and does not support smaller time units, which is basically sufficient for bit-timed tasks
http://www.bkjia.com/PHPjc/1040156.html www.bkjia.com true http://www.bkjia.com/PHPjc/1040156.html techarticle Pure PHP Implementation Timer Task (timer), PHP implementation Timer Timer task, the Web application is more common, how to use PHP to implement timer tasks, there are roughly two scenarios: 1) use ...