2016-11-11 50 views
11

我想限制从我的网站发送的电子邮件数量,以应对托管服务电子邮件的限制。 我正在使用cron作业和堆放数据库中的电子邮件的指示符来检查发送的电子邮件数量是否接近发送的最大电子邮件数量限制。是按顺序还是并行执行wordpress cron作业?

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

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

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

我知道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按顺序触发预定的作业,而不是并行?以及如何克服这个问题?

任何帮助,非常感谢。

+0

或许我应该指出的是,我在编译上面的代码中面临的一个WordPress的问题: 当你犯了一个WordPress的cron作业“睡眠”,这意味着每当有人在一次访问您的网站将再次执行它睡觉...即如果计划任务没有完成,wordpress会再次重新启动它,因为它仍然会看到cron作业。 我认为这是wordpress人应该修复的东西,没有人期望cron作业在非常接近的时间间隔内被执行超过一次。 –

+0

显然,wordpress在他们的网站上说:“请注意,安排一个事件发生在同名现有事件10分钟之后才会被忽略,除非您将$ args的唯一值传递给每个预定事件。”意味着wordpress会不允许在10分钟内不止一次地“调度”相同的脚本,同时它也应该防止在一定的时间跨度内多次执行相同的脚本。 –

+0

我会建议先安装一个cron管理插件,以便您可以轻松查看何时以及哪些cron正在发射,或者在此处创建您自己的https://developer.wordpress.org/plugins/cron/simple-testing/ –

回答

3

如前所述,安装cron插件将有助于管理您的cron。

为了回答你的问题,Wordpress使用“cron lock”defined('DOING_CRON'),并在spawn_cron方法被调用时设置一个瞬态$lock = get_transient('doing_cron')

所以,如果你看看wp-includes/cron.php你会发现默认情况下Wordpress cron不会同时运行,并且每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

有趣! 所以基本上,如果我更改cron.php代码,我应该能够同时触发cron作业。我确实使用了一个cron管理插件,它确实显示出所有的cron作业正在运行(尽管实际上只有一个作业正在运行) –

+1

我相信是这样的,我最初的想法是克隆WP的本地cron方法并对它们进行一些:) –

0

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

+0

谢谢为您的答复....在代码中的“2电子邮件门槛”只是一个例子...阈值是每5分钟约20封电子邮件....是的,当然可以使用其他SMTP服务器,允许更高的电子邮件发送频率....但这只是避免了这个问题......我主要是想知道wordpress cron是如何运作的,而我正在使用电子邮件问题作为研究案例。 –

+0

嗨!对不起,如果你认为我避免了你的问题。如果你有太多的注册信息,你必须对电子邮件进行排序,那么你应该进行这么多的访问,以至于你可以不断地运行wp-cron。我只需设置一个cron作业,以便每分钟运行一次,然后选择最近发送的两封电子邮件,发送它们,然后在其上设置一个标记以表示它们已发送。当然,如果您几个小时没有访问您的网站,那么电子邮件可能会延迟。但是,如果您使用的是wp cron,那么任何类型的排队都会出现这种情况。 – aurora

0

由于PHP运行从上到下,所以当你使用WordPress的日程安排事件的功能安排一个事件,如下:

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之间没有任何连接,这是您为自己的日志创建的时间戳,因此您可以检查。

确定我会有一些差异:e 10秒,它也可以更少或更大,这取决于服务器发送电子邮件和处理插入查询的时间。

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