首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建/使用具有Laravel队列的php类的单个实例

如何创建/使用具有Laravel队列的php类的单个实例
EN

Stack Overflow用户
提问于 2019-07-12 23:04:12
回答 1查看 359关注 0票数 1

抱歉,时间太长了,但我不知道该怎么表达我的顾虑。

我使用了Laravel5.8和php 7.2。*我有一个php类,如下所示:

代码语言:javascript
复制
class PushNotificationsJob implements ShouldQueue

这是用来发送推送通知到移动设备,目前工作良好,好的大部分。有了苹果的限制,他们不希望你一遍又一遍地连接和断开连接,如果你在短时间内这么做了太多次,他们就会返回拒绝服务(DOS)。因此,两个设计问题中的第一个问题是,我需要能够保存一个curl连接,以便一遍又一遍地使用。现在我连接,发送通知,然后断开连接。问题在于,决定何时需要发送通知的事件是不可预测的,也无法控制。我现在面临的第二个设计问题是,我确实需要创建一个表,其中包含每种通知类型的移动设备记录。我需要这样做的主要原因是,我需要推迟发送特定类型的通知,直到我有15秒的时间,而不需要再次将该通知类型发送到该移动设备。因此,我会遇到的问题是,如果每次我排队来运行PushNotificationsJob类时,它运行的是一个不同的实例,那么我最终可能会有两个实例同时运行,这两个实例都可能查询相同的记录,并且在只发送一次通知时都发送相同的通知。

当然,我使用队列的原因是为了卸载从主线程发送通知的过程,这样就不会减慢对客户端的响应。

我有一种感觉,人谁不明白为什么这样做会提出不适用的选项,所以我会在这里添加细节,以防你需要更多的信息。正在发生的事情是,我有相机(1,000多个),当他们检测到运动并上传到我的服务器时,他们正在拍照。我无法控制他们什么时候检测到运动和上传。当相机通过REST上传照片时,我需要查找相机的所有者并向他们发送通知。(还有其他事情会导致通知被发送,但这是最好的例子),所以问题是相机可能有1张照片或50张照片要上传。用户希望尽快收到通知。如果相机有超过1张照片要上传,通常只需5-8秒就能上传下一张照片。因此,我想要做的是推迟15秒发送第一个通知,但是如果在发送第一个通知之前上传了另一张照片,那么我希望将通知的计时器重置15秒。因此,一旦相机超过15秒没有上传一张照片,那么我会发送一个通知,而不是50。

我的想法是,如果我能够以某种方式创建一个在另一个线程中运行的类的实例,并且每次我需要发送推送通知时,我都会调用一些方法来告诉这个类是它们的活动,从而“唤醒”这个类。然后,它可以重新查询表,并处理那些“准备好”要发送的记录。这将解决这两个问题,这个实例可以保持一个与Apple的单独的卷曲连接,而且由于只有一个实例,所以它可以自由地查询记录、处理和删除,而不必担心与另一个执行相同事情的实例发生冲突。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-13 02:10:15

这很有趣,我喜欢这个概念。

如何设置队列工作人员?如果您正在使用主管来管理您的员工,那么这应该是一个长期运行的过程。这就是为什么在对代码库进行更改时必须调用artisan queue:restart的原因。大家都知道,我忘记了这件事,结果把我的头发扯掉了,不知道为什么变化不起作用。

由于这个事实,我想您可以将一个单例绑定到服务容器,并在需要工作时调用它。CURL连接将存储在单例中,您可以在服务提供者中注册它。创建新连接的唯一时间是队列工作人员死掉并重新启动。

当然,您需要解决这个问题,以便它只在队列工作器上运行,而不是每次启动应用程序时都运行.。

编辑:我添加了一个检查,以确保应用程序在创建连接和绑定单例之前从控制台运行(就像队列工作人员一样)。我不知道如何只为队列工作人员这样做,但是如果我发现了,我会告诉你的。目前,您只需要知道其他工匠的命令。

App/Providers/AppServiceProvider.php

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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);
    }
}

当然,如果不希望连接重叠,则需要确保主管只运行一个队列工作器,因为我认为文档在默认配置中列出了8个工作人员。

只是一个额外的注意事项,您可能希望通过调度程序偶尔触发队列的重新启动,以确保您不会在此过程中占用过多的内存。

我希望这给你一些想法和好运!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57014874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档