• 队列


    高性能离不开异步,异步离不开队列,而队列的内部都是Producer-Comsumer模式的原理。

    队列配置文件存放在 config/queue.php

     queue 配置文件中的每个连接配置示例都有一个 queue 属性。当新的队列任务被添加到指定的连接时,该配置项的值就是默认监听的队列(名称)。换种说法,如果你没有指派特别的队列名称,那么 queue 的值,也是该任务默认添加到的队列(名称):

    // 以下的任务将被委派到默认队列...
    dispatch(new Job);
    
    // 以下任务将被委派到 "emails" 队列...
    dispatch((new Job)->onQueue('emails'));
    

    将高优先级的任务委派到high(高优先级)队列,从而让它优先执行。

    php artisan queue:work --queue=high,default

    Redis

    要使用 redis 队列驱动,修改.env文件queue

    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => '{default}',
        'retry_after' => 90,
    ],

     Redis: predis/predis ~1.0  composer下载redis包

    创建任务

    php artisan make:job SendReminderEmail
    

    生成的类都实现了 IlluminateContractsQueueShouldQueue 接口, 告诉 Laravel 将该任务推送到队列,而不是立即运行。 (等本人把这个接口整明白了之后会回来重新修改这个地方)

    
      
        public function handle() //参数会依赖注入,具体参考容器
        {
            // 处理业务
        }

    分发任务到队列中 dispatch(new ProcessPodcast($podcast));
     

    延时分发

    $job = (new ProcessPodcast($pocast))
                        ->delay(Carbon::now()->addMinutes(10));
    
    dispatch($job);

    自定义队列和连接

    分发到指定的队列

    $job = (new ProcessPodcast($podcast))->onQueue('processing');
    
            dispatch($job);

    分发到指定的连接

    如果你使用了多个连接来管理队列,那么可以分发任务到指定的连接。请在任务实例中使用 onConnection 方法来指定连接:

      $job = (new ProcessPodcast($podcast))->onConnection('sqs');
    
      dispatch($job);

    当然,你可以同时使用 onConnection 和onQueue 方法来指定任务的连接和队列:

    $job = (new ProcessPodcast($podcast))
                    ->onConnection('sqs')
                    ->onQueue('processing');
    

    指定最大失败次数/超时时间

    最大失败次数

    指定队列任务最大失败次数的一种实现方式是通过 Artisan 命令 --tries 切换:

    php artisan queue:work --tries=3
    

    不过,你还可以在任务类自身定义最大失败次数来实现更加细粒度的控制,如果最大失败次数在任务中指定,则其优先级高于命令行指定的数值:

        public $tries = 5;
    

    超时

    类似的,队列任务最大运行时长(秒)可以通过 Artisan 命令 --timeout 来指定:

    php artisan queue:work --timeout=30
    

    同样,你也可以在任务类中定义该任务允许运行的最大时长(单位:秒),任务中指定的超市时间优先级也高于命令行定义的数值:

      public $timeout = 120;

    处理错误 如果任务在处理的时候有异常抛出,则该任务将会被自动释放回队列以便再次尝试执行。任务会持续被释放直到尝试次数达到应用允许的最大次数。最大尝试次数通过 Artisan 命令 queue:work 上的 --tries 开关来定义。此外,该次数也可以在任务类自身上定义。关于运行队列监听器的更多信息可以在下面看到。

    4、运行队列进程

    Laravel 包含了一个队列进程用来处理被推送到队列的新任务。你可以使用 queue:work 命令运行队列进程。请注意,队列进程开始运行后,会持续监听队列,直至你手动停止或关闭终端:

    php artisan queue:work
    

    注:为了保持队列进程 queue:work 持续在后台运行,需要使用进程守护程序,比如 Supervisor 来确保队列进程持续运行。

    请记住,队列进程是长生命周期的进程,会在启动后驻留内存。若应用有任何改动将不会影响到已经启动的进程。所以请在发布程序后,重启队列进程

    指定连接和队列

    队列进程同样可以自定义连接和队列。传递给 work 命令的连接名需要与 config/queue.php 中定义的某个连接相配置:

    php artisan queue:work redis
    

    你可以自定义将某个队列进程指定某个连接来管理。举例来说,如果所有的邮件任务都是通过 redis 连接上的 emails 队列处理,那么可以用以下命令来启动单一进程只处理单一队列:

    php artisan queue:work redis --queue=emails
    

    资源注意事项

    后台队列进程不会再处理每个任务前重启框架,因此你需要在每次任务完成后释放所有重量级的资源。例如,如果你在使用 GD 库处理图片,需要在完成的时候使用 imagedestroy 来释放内存。

    队列优先级

    有时候你需要区分任务的优先级。比如,在配置文件config/queue.php 中,你可能定义 redis 连接的默认 queue 为 low。 可是,偶尔需要将任务分发到高优先级 high , 可以这么做:

    dispatch((new Job)->onQueue('high'));
    

    如果期望所有 high 高优先级的队列都将先于low 低优先级的任务执行,可以像这样启动队列进程:

    php artisan queue:work --queue=high,low
    

    队列进程 & 部署

    前文已经提到队列进程是长生命周期的进程,在重启以前,所有源码的修改并不会对其产生影响。所以,最简单的方法是在每次发布新版本后重新启动队列进程。你可以通过 Aritisan 命令 queue:restart 来优雅地重启队列进程:

    php artisan queue:restart
    

    该命令将在队列进程完成正在进行的任务后,结束该进程,避免队列任务的丢失或错误。由于队列进程会在执行 queue:restart 命令后死掉,你仍然需要通过进程守护程序如 Supervisor 来自动重启队列进程。

    任务过期和超时

    任务执行时间

    在配置文件 config/queue.php 中,每个连接都定义了 retry_after 项。该配置项的目的是定义任务在执行以后多少秒后释放回队列。如果retry_after 设定的值为 90, 任务在运行 90 秒后还未完成,那么将被释放回队列而不是删除掉。毫无疑问,你需要把 retry_after 的值设定为任务执行时间的最大可能值

    队列进程超时

    队列进程 queue:work 可以设定超时 --timeout 项。该 --timeout 控制队列进程执行每个任务的最长时间,如果超时,该进程将被关闭。各种错误都可能导致某个任务处于“冻结”状态,比如 HTTP 无响应等。队列进程超时就是为了将这些“冻结”的进程关闭:

    php artisan queue:work --timeout=60
    

    配置项 retry_after 和 Aritisan 参数项 --timeout 不同,但目的都是为了确保任务的安全,并且只被成功的执行一次。

    进行休眠时间

    当任务在队列中有效时,进程会持续处理任务,没有延迟。不过,我们可以使用 sleep 配置项来指定没有新的有效任务产生时的休眠时间:

    php artisan queue:work –sleep=3

    处理失败任务

    不可避免会出现失败的任务。不必担心,Laravel 很容易设置任务允许的最大尝试次数,若是执行次数达到该限定,任务会被插入到 failed_jobs 表, 要创建一个 failed_jobs 表的迁移,可以使用 queue:failed-table 命令

    php artisan queue:failed-table
    php artisan migrate
    

    然后,运行队列进程时,通过 --tries 参数项来设置队列任务允许的最大尝试次数,如果没有指定 --tries 选项的值,任务会被无限期重试:

    php artisan queue:work redis --tries=3
    

    清理失败的任务

    你可以在任务类中定义 failed 方法, 从而允许你在失败发生时执行指定的动作,比如发送任务失败的通知,记录日志等。导致任务失败的 Exception 会被传递到 failed 方法:

     public function failed(Exception $e)
        {
            // 发送失败通知, etc...
        }

    重试失败的任务

    要查看已插入到 failed_jobs 数据表中的所有失败任务,可以使用 Artisan 命 queue:failed

    php artisan queue:failed
    

    该命令将会列出任务ID,连接,队列和失败时间,任务ID可用于重试失败任务,例如,要重试一个ID为5的失败任务,要用到下面的命令

    php artisan queue:retry 5
    

    要重试所有失败任务,使用如下命令即可:

    php artisan queue:retry all
    

    如果你要删除一个失败任务,可以使用queue:forget命令:

    php artisan queue:forget 5
    

    要删除所有失败任务,可以使用queue:flush命令

    php artisan queue:flush

  • 相关阅读:
    JavaScript中的this指向
    JQ延迟对象
    JavaScript事件简述
    1.0 HTML/CSS 优化--《高效前端》学习笔记
    浏览器工作原理(学习笔记)
    this 绑定例外之间接引用
    全局函数是否存在闭包?
    nuxt + vue-i18n 踩坑记录
    继承(学习笔记) —— 《高级教程》
    三、函数作用域和块作用域(学习笔记)—— 《你不知道的JavaScript》
  • 原文地址:https://www.cnblogs.com/lengthuo/p/7277260.html
Copyright © 2020-2023  润新知