我在线搜索但我没有找到任何解决方案。 我正在使用带有SQS的laravel 5.2作为队列驱动程序。 我正在派遣一份工作,以便向100位用户发送电子邮件。 该作业收到“文章”模型和“用户”数组,每个用户都应该收到一封带有“文章”的电子邮件。
当它是10个用户时一切都OK。 当它是100个用户时,我从amazon SQS服务收到错误消息“400 bad request”,响应是:“原因:消息必须短于262144字节。” 我知道由于用户的数组,作业的请求太大了。
我想拆分用户的数组,以便将作业的请求大小减少到256kb以下。 我可以通过循环访问用户的数组来完成它,每当我达到接近256kb时,我将用文章和用户调度一个作业,然后我将继续运行数组中的其余用户。
非常感谢您提前 利奥。
答案 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.