开发者

Scheduling jobs from a web environment on Linux

I am developing an applicat开发者_如何学Cion in PHP on Linux/Apache. I want to be able to schedule PHP jobs (scripts) for execution at some specific time in the future from within the application.

I know that many people will recommend cron and at, but first of all I don't need recurrence (cron) and secondly and most importantly, I need the solution to be able to scale. At was not designed with race condititions in mind, and if two users try to add a job at the same time one or both may fail.

It's also important that jobs are executed at their specified time, and not just 'polled' once per minute or so.

Can anyone please suggest solutions for this task? Thank you.


write a php-script as a daemon the script runs in the background, wakes up every some microseconds, checks for tasks to execute. if it has some tasks to execute, it could then fork itself and start the task.

if you don't like, that the script wakes up every some microseconds, you could also calculate the usleep time to the next task and then fork to start it. when tasks are being added or deleted, just send signal to the program and it then wakes up and recalculates how long it has to sleep now.

hyperlinks:

http://en.wikipedia.org/wiki/Daemon_%28computer_software%29

http://php.net/manual/en/function.pcntl-fork.php

http://www.php.net/manual/en/function.pcntl-signal.php


you can try gearman


This is what you could(I would) do:

  • Use Google's app engine Task Queue. It has a generous free quota(also pricing plane aren't that bad), it scales, uses webhooks. I think this is the easiest solution to implement.
  • beanstalkd.


On POSIX systems, there should be the at-daemon which is basically a one shot version of cron:

$ at 13:20 executeVeryImportantScript.php withPositionalParameters taken

which could be called via php's exec (or whatever is used to execute shell commands via php).

Reimplementing already existing solutions is Very Bad Practise ™:

  1. You need to implement it, which is not cost efficient
  2. You need to test the code
  3. You need to maintain the code


Here is a solution for Yii2 using MySQL. If you put the query/status update in a transaction, you can have multiple workers on different machines.

cron table
Field         | Type        
--------------+-------------
id            | int(11)     
execute_after | timestamp   
executed_at   | timestamp   
status        | int(11)     
progress      | int(11)     
action        | varchar(255)
parameter     | varchar(255)
result        | varchar(255)
Cron class
  /** This command waits for jobs to work on by polling the DB every 10s. TODO put this into Redis.
   * 
   */
  public function actionIndex()
  {
    do {
      $job = Cron::find()->where('execute_after < :now AND status = 0 ORDER BY id ASC', [':now'=>date(DATE_ATOM)])->one();
      if($job && method_exists($this, $job->action)){
        $job->status = 1;
        $job->save() or Yii::error($job->getErrors());
        $result = $this->{$job->action}($job, $job->parameter);
        $job->status = 2;
        $job->progress = 100;
        $job->executed_at = date(DATE_ATOM);
        $job->save() or Yii::error($job->getErrors());
      }
      sleep(10);
    } while (true);
  }

Then you can have tasks in the class like

function toggleStatus($job, $id) {

which do the work and update the progress of the job as it completes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜