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

Laravel job size limit is been exceeded 256kb (queue SQS aws)

我在网上搜索过,但没有找到解决我的问题的方法。 我使用 laravel 5.2 和 SQS 作为队列驱动程序。 我正在分派一项工作,以便向 100 位用户发送电子邮件。 该作业接收 "Article" 模型和 "User"(s) 的数组,每个用户应该收到一封包含 "article".

的电子邮件

当是10个用户的时候就OK了。 当它是 100 个用户时,我收到来自亚马逊 SQS 服务的错​​误消息“400 错误请求”,响应是:"Reason: Message must be shorter than 262144 bytes." 我了解到由于用户的数组,作业的要求太大了。

我想拆分用户的数组,以便将作业的请求大小减少到 256kb 以下。 我可以通过遍历用户的数组来做到这一点,每次我达到接近 256kb 时,我都会分派一篇文章和用户的工作,然后我将继续 运行 遍历数组中的其余用户。

  1. 在派发之前检查当前作业请求大小的方法是什么?
  2. 您有更好的解决方案吗?

非常感谢您 狮子座

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

Because of the SerializesModels trait that the job is using, Eloquent models will be gracefully serialized and unserialized when the job is processing. If your queued job accepts an Eloquent model in its constructor, only the identifier for the model will be serialized onto the queue.

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

编辑+解决方案:

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

希望已经清楚了。 里尔.

好的,您已经发现 SerializesModels 特性通过保存模型 class 和 id 来帮助保持较低的负载大小,以便在作业执行时再次从数据库中获取正在解决。

如果它仍然使作业太大,则队列对象是在 createObjectPayload 方法中创建有效负载的对象。它受到保护,因此您可能无法从外部轻松访问它,但大部分有效负载只是 serialize(clone $job)。这将使您了解工作的当前规模。也许在作业 class 中创建一个方法,将用户添加到其内部 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.