Laravel作业大小限制已超过256kb(队列SQS aws)

时间:2017-07-07 21:45:29

标签: php laravel laravel-5 eloquent amazon-sqs

我在线搜索但我没有找到任何解决方案。 我正在使用带有SQS的laravel 5.2作为队列驱动程序。 我正在派遣一份工作,以便向100位用户发送电子邮件。 该作业收到“文章”模型和“用户”数组,每个用户都应该收到一封带有“文章”的电子邮件。

当它是10个用户时一切都OK。 当它是100个用户时,我从amazon SQS服务收到错误消息“400 bad request”,响应是:“原因:消息必须短于262144字节。” 我知道由于用户的数组,作业的请求太大了。

我想拆分用户的数组,以便将作业的请求大小减少到256kb以下。 我可以通过循环访问用户的数组来完成它,每当我达到接近256kb时,我将用文章和用户调度一个作业,然后我将继续运行数组中的其余用户。

  1. 在发送之前检查当前作业请求大小的方法是什么?
  2. 您有更好的解决方案吗?
  3. 非常感谢您提前 利奥。

2 个答案:

答案 0 :(得分:1)

我找到了解决问题的方法。 答案写在文档中:

  

由于作业正在使用的SerializesModels特征,Eloquent   在工作时,模型将被优雅地序列化和反序列化   处理。如果您的排队作业接受其中的Eloquent模型   构造函数,只有模型的标识符将被序列化   队列。

这意味着laravel只保存序列化雄辩模型的ID。像这样我们减少了调度作业的大小。 另一方面,在发送作业之前,我仍然不知道如何检查作业的大小。

修改+解决方案:

基本上处理它的最佳方法是派遣许多工作。我将用一个例子来解释。 假设我们在工作中有一个事件,我们想要通知所有工人。 处理它的最佳方法是使用event-> id调度一个作业(排队),然后在该作业内部循环工作者并使用$ worker-> id分派许多作业(队列)。 像这样,队列大小永远不会太大。 如果我们将为所有工人派遣一份工作,我可以达到1000s ids(工人ID),并且像这样我们将达到队列限制大小。

希望很清楚。 利奥尔。

答案 1 :(得分:1)

好的,您已经发现SerializesModels特征只需保存模型类和ID,有助于保持有效负载大小,以便在作业解析时从数据库中再次获取。

如果它仍然使作业太大,则Queue对象是在createObjectPayload方法中创建有效负载的对象。它受到保护,因此您可能无法从外部轻松访问它,但大多数有效负载仅为serialize(clone $job)。这将使您了解当前工作的大小。也许在作业类中创建一个方法,将用户添加到其内部Eloquent \ Collection,直到serialize($this)达到限制?

如果作业构造函数是

public function __construct(\Illuminate\Database\Eloquent\Collection $users, $maxSize)
{
    $this->users = new \Illuminate\Database\Eloquent\Collection();

    while (strlen(serialize(clone $this)) < $maxSize) {
        $this->users->push($users->shift());
    }
}

然后你这样称呼它:

// $usersToNotify is the collection with the users

$job = new YourJob($usersToNotify, $maxSize);

// Now the job has all users within the limit,
// and $usersToNotify has the remaining users.
相关问题