为了防止超时 - 排队作业与分块结果有什么好处?

时间:2016-02-06 18:03:41

标签: laravel laravel-5

我的Laravel 5网站允许用户向其联系人发送电子邮件。我的问题是,它在循环通过大约50个联系人之后会超时。

我的流程概述:

  • 获取联系人列表
  • 构建电子邮件
  • 循环浏览联系人列表,并使用邮件服务向每封联系人发送电子邮件。
  • 将电子邮件详细信息返回给控制器以保存在数据库中。

Chunking很容易理解,但我对在队列中放置作业的机制并不熟悉。

为防止超时,我最好不要将联系人分块以限制循环的大小或将整个作业放在队列中?如果整个工作应该放在一个队列上 - 我仍然可以使用联系人吗?排队的作业是否仍然可以使用mail :: queue或者只是多余的?

循环代码:

public function sendIndividualEmail($members, $subject, $body, $file)
   {

     $view  = 'emails.memberMessage';

     //construct email details
     $mData = $this->emailConstructor($subject, $body);

     //check to see if there is an attachment, if so upload it.
     if (!is_null($file)){
            $uploadedFile = $this->attachment->saveAttachment($file);

            $mData['path'] = 'https://'.$_SERVER["HTTP_HOST"].'/uploads/attachments/'.$uploadedFile['filename'];
            $mData['display'] = $uploadedFile['display'];
        }


     foreach($members as $member){

                if (!empty($member->contact_email)){

                  //add member details here
                    $mData['email'] = $member->contact_email;
                    $mData['name'] = $member->contact_firstName;

                   //email member
                    $this->emailTo($view, $mData);
                    $mData['emailCount']++;
                }           

    }
    return $mData;
}

邮件服务:

public function emailTo($view, $mData)
 {

    Mail::queue($view, $mData, function($message) use ($mData)
    {
      $message->from($mData['from'], $mData['fromName']);
      $message->to($mData['email'], $mData['name'])->subject($mData['subject']);
      $message->getHeaders()->addTextHeader('X-MC-Metadata', $mData['meta']);
        if(array_key_exists('path', $mData)){
            $message->attach($mData['path'], array('as' => $mData['display']));
        }
    });
}

2 个答案:

答案 0 :(得分:2)

首先提出一些建议。 对它们进行分块将使用较少的计算能力,但不提供队列系统提供的灵活性。

分块场景--- 获取所有模型,将count(x)作为新的块存储块。 Foreach chunk as items 项目中的foreach项目 本期特价货品> doSomething的

- 分页 我可能会调整分页库来支持它。 I.E获得一个集合并对其进行分页,存储页码,并且一次只能创建一个页面记录?

- 事件观察者队列? 另一种技术是使用事件监听器系统。 你可以通过多种方式,只考虑何时发送电子邮件。

您的模型可能有像sent_mymail_email这样的列,或者如果发送了电子邮件(作业已完成),您可以使用mutator getSentMymailEmailAttribute()返回布尔值true。

然后,您将设置一个新事件或锁定现有事件。

请参阅:How Can I See All Laravel Events Being Fired

队列系统 - 队列系统将通过http请求从一个服务器接收事件和数据。然后将这些项目添加到需要完成的大型作业列表中。当事件出现时(轮到它),它将向您的系统上的某个地方发送http请求。然后,您的系统会解释任务是什么并完成任务,完成后,会将响应发送回队列系统(通常),通知系统已完成的任务。然后队列将继续执行下一个任务,发送请求......依此类推。

将此与块方法进行比较,您可以看到您的应用程序需要在两种方案中发送电子邮件,但是它不需要发送任务,接收任务或解释分块方法中的任务。< / p>

在分块方法中,您也有较少的移动部件,但是如果您希望能够扩展并将部分应用程序工作负载放在辅助系统或集群上以处理作业,那么您可能希望使用队列系统。

队列系统依赖于具有内置缺陷的第三方服务。例如,您无法为这些项目定义订单。

此博客文章解释说: http://cloudstacking.com/posts/amazon-sqs-gotchas.html

这是关于使用队列系统的另一篇不错的帖子: http://www.isixsigma.com/industries/retail/queuing-theory-and-practice-source-competitive-advantage/

简而言之,优势主要在于您能够扩展到处理大量这些请求,而对前端(应用程序)没有任何影响。

您可以在单独的系统或系统群集上运行这些作业,以推动不影响用户体验的服务器所需的工作。

答案 1 :(得分:0)

您可以对整个作业进行排队并仍然对邮件进行排队,我在我的应用程序中执行此操作并且不觉得它是多余的。它允许您将处理分解为可以彼此独立完成的逻辑步骤。例如,作业可以继续处理联系人和安排电子邮件,而无需等待他们发​​送。

虽然我自己没有这样做,但我相信你能够将联系人分块并仍在工作中使用队列。