• 队列


    高性能离不开异步,异步离不开队列,而队列的内部都是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

  • 相关阅读:
    三元表达式 列表和字典推导式 函数对象 名称空间 作用域 global和nonlocal 函数装饰器 枚举对象
    函数参数 打散机制 字符串比较 返回值
    函数简介
    三种字符串的介绍 文件的读写
    字符编码
    数据类型及其常用方法 数据类型转换 可变与不可变 值拷贝与深浅拷贝
    流程控制 while和for循环
    变量命名规范 常量 输入和输出 注释 数据类型 运算符 逻辑运算符
    语言分类 编译型和解释型语言分析 环境变量 代码执行的方式 pip介绍 变量
    Python django tests
  • 原文地址:https://www.cnblogs.com/lengthuo/p/7277260.html
Copyright © 2020-2023  润新知