laravel - Laravel:使用队列每小时发送 1000 封电子邮件
问题描述
我有一个表用户,有 5000 条记录(5000 个用户),在我的服务器中,我每小时只能发送 1000 封电子邮件。我如何使用队列每小时发送 1000 封电子邮件?或者如何让队列在循环内休眠?
电子邮件控制器:
class EmailController extends Controller
{
public function sendEmail(Request $request){
$event=(object)['content' => "Hello Laravel fans",'subject' => 'Test Email'];
$users=User::all();
App\Jobs\SendReminderEmail::dispatch($users,$event)
}
}
发送提醒电子邮件
class SendReminderEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $event;
public $email;
public $users;
public function __construct($users,$event)
{
$this->users = $users;
$this->event = $event;
}
public function handle()
{
foreach ($this->users as $user) {
Mail::to($user->email)->queue(new Reminder($this->event));
}
}
}
解决方案
Laravel 具有内置的节流功能,用于限速作业。从文档:
如果您的应用程序与 Redis 交互,您可能会按时间或并发限制排队的作业。当您的排队作业与同样受速率限制的 API 交互时,此功能可以提供帮助。例如,使用节流方法,您可以节流给定类型的作业,使其每 60 秒仅运行 10 次。如果无法获得锁,您通常应该将作业释放回队列,以便稍后重试:
Redis::throttle('key')->allow(10)->every(60)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); });
在你的情况下,这可能看起来像Redis::throttle(...)->allow(1000)->every(3600)->...
如果您不使用 Redis,另一种可能的特定于排队邮件的解决方案是添加延迟。同样,来自文档:
延迟消息队列
如果您希望延迟发送排队的电子邮件,您可以使用该
later
方法。作为它的第一个参数,该later
方法接受一个DateTime
指示何时发送消息的实例:$when = now()->addMinutes(10); Mail::to($request->user()) ->cc($moreUsers) ->bcc($evenMoreUsers) ->later($when, new OrderShipped($order));
使用此方法将要求您在将电子邮件分派到队列的循环期间计算每封电子邮件的延迟。例如,循环的每 1000 次迭代,您可以将延迟增加 1 小时。
如果您使用的是 Amazon SQS 队列服务,则适用于其他排队作业的最大延迟 15 分钟也可能适用于此处(我不确定这部分),在这种情况下,您将不得不提出另一个检查您是否超过速率限制并将作业释放回队列的解决方案。
推荐阅读
- java - 在列表视图中向下滚动时如何加载更多项目?
- c# - 如何在 Azure Service Fabric ASP.NET Core 有状态服务中获取 PartitionInfo?
- python - Python 播放“错误”声音而不是播放 .wav
- php - 我正在尝试使用 php 在 SQL Server 中显示行
- vb.net - .NET Mail 使用的文件
- python - python reverse_geocoder 包行为从shell到文件的变化
- node.js - 使用 Node.js 使用 Botframwork 创建统计图表?
- php - WordPress 中具有相同 WP_Query 的多个循环
- swift - Swift - 继承协议和将 Self 约束到协议之间的区别
- azure - 将 Azure 自动化中的集成模块安装到 VM 上