wordpress cron作业是按顺序执行还是并行执行?

时间:2016-11-11 08:39:00

标签: php wordpress cron

我正在尝试限制从我的网站发送的电子邮件数量,以应对托管服务电子邮件的限制。 我正在使用cron作业以及在数据库中堆放电子邮件的指示器,以检查发送的电子邮件数量是否接近发送的最大电子邮件数量限制。

我这样做的方法是直接执行预定的进程,然后让它“休眠”一段时间(根据它在队列中的位置),然后发送电子邮件并登录数据库。 为了进一步解释我使用计划任务和“睡眠”的原因,请考虑以下场景:

  1. 用户尝试注册我的网站,并希望很快就会向他/她发送电子邮件。因此,如果超过电子邮件/分钟配额,我需要发送一条不同的消息:“我们的服务器很忙,请允许'x'分钟执行所需的任务”。
  2. 发送电子邮件的请求都是通过AJAX完成的。在进程中使用“sleep”不是一个选项,因为用户必须等待x分钟,直到“busy message”被回显。
  3. 我尝试使用ob_flush,flush ...等。组合来回应消息,然后服务器在后台处理所有内容,但这从未奏效。 AJAX调用总是在等待脚本结束以回显结果。
  4. 我需要使用单线程PHP语言进行多线程处理!作为一种解决方法,我使用了cron作业,其中每个堆积的电子邮件计划在time()执行(即直接触发预定作业),该电子邮件挂钩到发送电子邮件的同一功能。使用标志,该函数知道该请求是一个堆积的电子邮件,并使其“休眠”,直到重置电子邮件配额所​​需的时间。

  5. 问题:如果5个人几乎同时注册(虽然我们还有一个电子邮件堆),那么我们有5个cron作业,应该同时执行然后再睡一会儿(如果堆中的电子邮件数量已经大于电子邮件配额,则睡眠时间可能不同,然后发送电子邮件。但是,当我检查数据库中的日志时,我发现计划的作业是按顺序执行的,而不是并行执行的。有时会发生cron作业在另一个结束之前被解雇,但它们不会同时发射。

  6. 我知道wordpress cron的工作并不是真正的cron工作,一旦有人访问网站就会被解雇(我确保在发送注册请求以解雇所有计划任务后刷新页面),但他们似乎是我唯一的选择,因为我的托管服务器不允许访问服务器,也不允许安排cron作业。

    以下是执行上述代码的部分代码:

    //Test example to pile up emails, where quota is set to 2 emails every 30 seconds
    $Emails_Threshold = 2;
    $Threshold_Duration = 0.5*60;
    //Get email indicator info
    $Email_Info = $wpdb->get_row( 
    "SELECT * 
    FROM PileEmails 
    WHERE priority = -1 
    AND Status='New';"
    ,ARRAY_A);
    
    if ($sleep ==0 && $Queue_Info_id==0){ //Not a scheduled event
       //Check if there are queued emails
       $Queue_exist = $wpdb->get_row (
        $wpdb->prepare("
                        SELECT Status 
                        FROM PileEmails
                        WHERE Status='Queued';"
                        ,$mail_priority)
                    ,ARRAY_A);
      if (!empty($Queue_exist) || ($Email_Info['last_email_time']   > (time()-$Threshold_Duration))){
        if ($Email_Info['count_emails']>=$Emails_Threshold){
               //Code to Pile up
        }
      }else{ 
       //Reset email counter
      }
    }else{ 
    $wpdb->insert( "PileEmails",$Sleep_Info,$format);
    sleep(10); //10 seconds here just as an example
    }
    //Code to send emails
    

    当我尝试在超过配额后发送10封电子邮件时,我会登录数据库。

    MYSQL database logs

    请注意,时间戳在每个日志和下一个日志之间有10秒的差异,尽管它们应该同时被触发,每个日志都会休眠10秒,然后所有日志都会并行发送。

    所以我的问题是:为什么wordpress cron按顺序而不是并行地触发预定的作业?以及如何克服这个问题?

    非常感谢任何帮助。

3 个答案:

答案 0 :(得分:3)

如上所述,安装cron插件将有助于管理你的crons。

要回答您的问题,Wordpress使用“cron lock”defined('DOING_CRON')并在调用$lock = get_transient('doing_cron')方法时设置暂时spawn_cron

因此,如果您查看wp-includes/cron.php,您会看到Wordpress crons默认情况下不会同时运行,并且每60秒运行一次不会超过一次。

// don't run if another process is currently running it or more than once every 60 sec.
    if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time )
        return;

答案 1 :(得分:0)

如果您一次只能发送一两封电子邮件,这将很难解决。解决这个问题的一种更简单的方法可能是让WordPress使用SMTP电子邮件服务器,该服务器允许您需要发送的电子邮件的频率。只需在当前的托管服务提供商处添加新的电子邮件帐户即可。如果您不知道如何手动设置,那么就会有适合您的插件。

答案 2 :(得分:0)

当php从上到下运行时,所以当你使用wordpress schedule事件函数安排一个事件时,如下所示:

if (! wp_next_scheduled ( 'my_hourly_event' )) {
    wp_schedule_event(time(), 'hourly', 'my_hourly_event');
}


add_action('my_hourly_event', 'do_this_hourly');

function do_this_hourly() {
    // do something every hour
}

此函数do_this_hourly()将按照计划运行,但您将在该函数内编写的代码将仅逐个运行。

  1. 让我们举例说明发送给5个人的电子邮件,这样电子邮件就会逐个发送给他们。
  2. 时间戳由您正在使用的插入查询输入,timestampmail sent time之间没有连接,这是您为自己的日志创建的时间戳,因此您可以检查。
  3. 肯定会有一些区别:10秒,它也可以更少或更多,具体取决于服务器发送电子邮件和处理插入查询所花费的时间。

    将触发每个查询,并根据当时的时间(服务器时间)插入时间戳。