很抱歉,这个时间太长了,但不确定如何解决我的问题。
我正在使用Laravel 5.8和php 7.2。* 我有一个像这样的php类:
class PushNotificationsJob implements ShouldQueue
这用于将推送通知发送到移动设备,并且在大多数情况下目前运行良好。 由于Apple的限制,他们不希望您一遍又一遍地连接和断开连接,如果您在短时间内执行了太多次,他们将返回拒绝服务(DOS)。因此,两个设计问题中的第一个是我需要能够保存卷曲连接以供反复使用。现在我连接,发送通知,然后断开连接。问题在于,指示何时需要发送通知的事件是不可预测的,也无法控制。我现在遇到的第二个设计问题是我确实需要创建一个表,其中包含每种通知类型的每个移动设备的记录。我需要执行此操作的主要原因是,我需要将发送某种类型的通知的时间推迟到15秒,而无需再次将该通知类型发送给该移动设备。因此,我遇到的问题是,如果每次我排队运行PushNotificationsJob类时,它都运行一个不同的实例,那么我可能最终会同时运行两个实例,并且两者都可以查询相同的记录,并且在发送时都发送相同的通知应该只发送一次。
当然,我使用队列的原因是减轻了从主线程发送通知的过程,因此它不会减慢对客户端的响应。
我有一种感觉,如果人们不了解为什么这种方法会起作用,那么他们会建议一些不适用的选项,因此,如果您需要其他信息,我会在此处添加详细信息。发生的事情是我有几千个摄像头,当它们检测到运动并上传到我的服务器时正在拍照。我无法控制他们何时检测到运动并上载。当相机通过REST API上传照片时,我需要提供该相机的所有者并向他们发送通知。 (还有其他一些因素会导致发送通知,但这是最好的例子),因此问题是相机可能有1张照片或50张照片要上传。用户希望尽快收到通知。如果相机要上传的照片多于1张,通常只需要5-8秒即可上传下一张照片。因此,我想做的是将第一条通知的发送时间延迟15秒,但是如果在发送第一条通知之前上传了另一张照片,那么我想将通知的计时器重设15秒。因此,一旦照相机超过15秒而没有上传照片,那么我会发送一条通知而不是50。
我的想法是,如果我能够以某种方式创建在另一个线程中运行的Class的单个实例,并且每次需要发送“推送通知”时,我都会通过调用某种方法来告诉它来“唤醒”该类他们是活动。然后,它可以重新查询表并处理那些“准备好”要发送的记录。这将解决这两个问题,该实例可以保持与Apple的单个curl连接,并且由于只有一个实例,它可以自由地查询记录并进行处理并在完成后删除,而不必担心与执行该操作的另一个实例冲突。同样的事情。
答案 0 :(得分:1)
这很有趣,我喜欢这个概念。
您如何设置队列工作者?如果您使用主管来管理您的工作人员,那么这应该是一个长期运行的过程。这就是为什么每次更改代码库都必须调用artisan queue:restart
的原因。众所周知,我忘记了这一点,最终想知道为什么更改无效,因此将头发撕掉了。
由于这个事实,我想您可以将单例绑定到服务容器并在需要工作时调用它。 CURL连接将存储在单例中,您可以在服务提供商中注册。创建新连接的唯一时间是队列工作器是否死亡并重新启动。
当然,您需要解决此问题,使其仅从队列工作器运行,而不是每次启动应用程序时都运行。
编辑:在创建连接并绑定单例之前,我添加了一项检查以确保应用程序正在从控制台运行(就像队列工作器一样)。我不知道如何仅对队列工作者执行此操作,但是如果我发现了,我会通知您。目前,您只需要了解其他工匠命令即可。
App / Providers / AppServiceProvider.php
use App;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
// make sure we're running from the console
// and not every time the app is booted
if (App::runningInConsole()) {
// create your connection
$connection = new YourCurlConnection();
$this->app->singleton('App\Support\PushNotificationHelper', function ($app) use ($connection) {
return new App\Support\PushNotificationHelper($connection);
});
}
}
}
App \ Support \ PushNotificationHelper.php
class PushNotificationHelper
{
// your CURL instance
protected $connection;
public function __construct($connection)
{
// store via dependency injection
$this->connection = $connection;
}
public function sendNotification($message)
{
// send notification using stored connection
}
}
App / Jobs / PushNotificationsJob.php
class PushNotificationsJob implements ShouldQueue
{
protected $message;
public function __construct($message)
{
$this->message = $message;
}
public function handle()
{
$message = $this->message;
// get the singleton
$helper = app('App\Support\PushNotificationHelper');
// send the message using the singleton
$helper->sendNotification($message);
}
}
当然,如果您不希望重叠的连接,则需要确保 supervisor 仅运行一个队列工作程序,因为我认为文档在默认配置中列出了八个工作程序。
还有一点需要注意的是,您可能希望偶尔通过调度程序触发队列的重新启动,以确保您不会在此过程中占用过多的内存。
我希望这能给您一些想法和好运!