【问题标题】:Laravel job size limit is been exceeded 256kb (queue SQS aws)Laravel 作业大小限制已超过 256kb(队列 SQS aws)
【发布时间】:2017-07-07 21:45:29
【问题描述】:

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

当它是 10 个用户时,一切正常。 当它是 100 个用户时,我收到来自亚马逊 SQS 服务的错​​误消息“400 bad request”,响应是:“原因:消息必须短于 262144 字节。” 由于用户数组的原因,我了解到作业的请求太大。

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

  1. 在我们调度当前作业请求大小之前,有什么方法可以检查它?
  2. 您有更好的解决方案吗?

非常感谢您提前 狮子座。

【问题讨论】:

  • 是否有理由让您发送一份包含 100 篇文章的工作,而不是发送 100 个工作,每个工作包含 1 篇文章?这首先是队列系统的一大特点。
  • @CmdrSharp 我正在发送一项包含 100 个项目的作业(1 个包含 100 个用户的事件),以减少队列请求。每个 EVENT 都将运行在用户身上,并将 EMAIL 发送给 100 个用户中的同一个(取决于条件),所以最后我将发送 100 个工作来发送 EMAIL。 SO 1 个 EVENT 作业,包含 100 个用户和 100 个要发送电子邮件的作业。

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


【解决方案1】:

好的,您已经发现 SerializesModels trait 仅通过保存模型类和 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.

【讨论】:

  • 我不明白如何检查“serialize($this)”的大小,我怎么知道它什么时候达到了 256kb 的限制,然后才发送作业?谢谢!
  • 嘿@alepeino strlen() 不返回“大小”,而是返回“长度”。这对我来说仍然不是正确的答案。现在我通过将用户数组拆分为 100 个组来解决它,而不是如果我有 100,000 个用户,作业大小不会超过 256kb,但我有 1000 个作业在队列中。主要问题是如何检查请求的 kb 大小,然后我可以优化队列中的作业数。
  • @llioor 等等,但作业的大小(主要是)不是其有效负载的大小,您可以通过序列化获得吗?我在这里错过了什么?
  • "你用序列化得到哪个?" serialize() 将序列化对象作为字符串返回。 strlen() 返回序列化字符串“strlen(serialize(clone $this)”的长度。字符串的长度不等于他的字节大小。我想知道如何检查这个条件 while ($jobSizeInKb
  • @llioor 我不明白为什么不php.net/manual/en/function.strlen.php#118484。 (我知道这只会为您提供有效负载的大小,您必须考虑其他字段、标题等)
【解决方案2】:

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

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

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

编辑+解决方案:

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

希望很清楚。 利奥。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2014-06-29
    • 1970-01-01
    • 2016-09-13
    相关资源
    最近更新 更多