我想在 Laravel 中发送大量通知。
通知方法是 firebase,我正在使用 kutia-software-company/larafirebase 包作为 Not济。
目前,我大约有 10000 个 fcm,但我想将发送通知优化为 100000 个 fcm。
我实现了如下系统:
首先,我创建了一个可通知的类,如包中所述
<?php
namespace Vendor\Core\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Kutia\Larafirebase\Messages\FirebaseMessage;
class FirebasePushNotification extends Notification
{
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(protected $title, protected $message, protected array $fcmTokens = [])
{
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['firebase'];
}
public function toFirebase($notifiable)
{
return (new FirebaseMessage)
->withTitle($this->title)
->withBody($this->message)
->withPriority('high')
->asNotification($this->fcmTokens);
}
}
其次,创建通知作业:
<?php
namespace Vendor\PushNotification\Jobs;
use Vendor\Core\Notifications\FirebasePushNotification;
use Vendor\Customer\Contracts\UserDeviceInfo;
use Vendor\Customer\Contracts\Customer;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Notification;
class SendPushNotificationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Batchable;
public function __construct(public string $title, public string $body, public Customer $customer, public UserDeviceInfo $userDeviceInfo)
{
}
public function handle()
{
Notification::send($this->customer, new FirebasePushNotification($this->title, $this->body, [$this->userDeviceInfo->fcm]));
}
}
并使用
Bus::dispatch
将作业发送到队列:
$usersDeviceInfos = $usersDeviceInfos->with('customer')->get();
$bus = [];
for ($i = 0; $i < 100000; $i++){
foreach ($usersDeviceInfos as $usersDeviceInfo) {
$bus [] = new SendPushNotificationJob($data['notification_title'], $data['notification_body'], $usersDeviceInfo->customer, $usersDeviceInfo);
}
}
Bus::batch($bus)->name('push notification' . now()->toString())->dispatch();
目前,由于开发环境的原因,我只有一个fcm并使用循环来模拟10000,运行此代码需要一分多钟的时间,并且我会得到最大执行错误。
另外,请注意,我配置了我的队列,但它不是
sync
,我检查了这两个问题,但没有帮助:
希望找到一种更快的方法来批处理这些作业并将它们发送到队列
我找到了一个解决方案,可以在几秒钟内处理发送多达一百万个 fcm 的通知
我决定使用
kreait/laravel-firebase
并使用这里提到的多播
首先我对 fcms 进行分块,然后使用 A 作业并将它们分派到队列中。
这是解决方案的示例:
<?php
namespace Vendor\PushNotification\Jobs;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Laravel\Firebase\Facades\Firebase;
class SendPushNotificationJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, Batchable;
public function __construct(public string $title, public string $body, public array $fcmTokens)
{
}
public function handle()
{
$message = CloudMessage::fromArray(YOUR_DATA);
Firebase::messaging()->sendMulticast($message, $this->fcmTokens);
}
}
$chunks = $usersDeviceInfos->with('customer')->get()->pluck('fcm')->chunk(500);
foreach ($chunks as $chunk) {
dispatch(new SendPushNotificationJob($data['notification_title'], $data['notification_body'], $chunk->toArray()));
}