Home>

What is a timing scheduler

laravel provides a command timing task function by default,Under other php frameworks,Without this scheduled task,How do we run some asynchronous scripts?We can only rely on the crontab provided by our system to do it, which causes us to change the crontab code on the server every time we add a new scheduled task in the version to get this configuration.

The execution command isphp artisan schedule:run to execute, where to execute it,Yes, this transfer still needs to rely on our crontab to execute, but only needs to be configured once.All subsequent timing tasks are controlled in our business code

Scenes

We have a scheduled task to import data

//Import library data every minute
$schedule->command (self ::signature)->withoutoverlapping ()->everyminute ()->runinbackground ();

It is best to use runinbackground () for long import here, which means asynchronous execution.In fact, the ampersand is added to the end of the shell script, which is completely dependent on the system on Linux.

Here withoutoverlapping () is used to indicate that only one task can be executed at a time,The main logic uses an exclusive lock implementation,Relying on our cache driver, I use redis here. Later, as the lock expires, the key provided by redis is expired.

problem appear

This task is perfect under normal circumstances,Because there is only one run at a time,You can just runBut a scene appearsOne day after our qa classmates deployed the environment,Our server is silently importing the library,Because usingwithoutoverlapping ($expire_at=1440) At this time, a lock was generated in redis,This default parameter takes the lock expiration time,The default is one day.Then because our docker environment needs to change parameters and then restart the back-end server service,Our restart is also more violent,Is to send the kill signal directly, causing all processes running inside to kill instantly, and at this time our redis lock lacks,And it ’s about 1440 minutes,Then when our server restarts,Found that the lock was always there,There is no way to perform subsequent operations,Can only wait.

solve

Then I can reduce the lock time.It turned out that I changed it to 30 minutes in 1 day. No problem. We did the same with the first version.Officials can do the same.

Then we thought,Can it be a monitoring program,After the process exited, it was immediately monitored and expired.So you do n’t have to set a time,This is of course the ideal state for all software developers:if i want to drive you,I removed the lock and removed it.Whether normal or not.

solution

Explanation:

When this command starts,Get the pid of the process, and then fork the child process, you can pass this pid to the child process. The child process performs a probe every 10s.Get whether the id of the parent process is consistent with the passed in pid,Popularize a knowledge point here,If the parent process exits abnormally,This child process will be taken over by the init process (pid=1) before exiting, then this is an orphan process. At the same time, each time the child process probes, it will change the redis lock expiration time.If the detection interval is 10s, then our expiration time setting is 14s, a little more time.

Code

Code implementation is always so pale,Here is a laravel extension to do it,The advantage is that any code is completed without affecting our main body,Our laravel can be upgraded at will.

github address:github.com/zzh78727258...

composer address:packagist.org/packages/ze...

to sum up

The overall implementation does not use commands such as ps grep to determine whether a process exists, because our docker environment does not necessarily support these commands.Just compare the simple pid with the parent_id.

laravel hooks the command from the beginning to the end,We can listen under the listener

public function subscribe ($events)
 {
  $events->listen (
   [
    commandstarting ::class, //When the command starts
   ],   __class__. "@handle"
  );
 }

The overall code is extended based on laravel,Will not affect the upgrade operation of laravel.

php
  • Previous Python dictionary change value method summary
  • Next Detailed solution to the problem of unable to redirect when Ajax request