一、概述在web开发中,我们经常会遇到需要批量处理任务的场景,比如邮件群发、秒杀资格获取等,我们把这些耗时或者高并发的操作放在异步执行在队列中可以有效缓解系统压力,提高系统响应速度和负载能力。2.配置文件我们还是从配置文件入手。首先,我们需要在配置文件中配置默认??的队列驱动为Redis。Lumen没有配置文件,可以从laravel项目中拷贝一个config目录。队列配置文件是config/queue.php:return['default'=>env('QUEUE_DRIVER','sync'),'connections'=>['database'=>['driver'=>'database','表'=>'工作','队列'=>'默认','过期'=>60,]],'redis'=>['驱动程序'=>'redis','连接'=>'默认','queue'=>'default','expire'=>60,],],'failed'=>['database'=>'mysql','table'=>'failed_jobs',],];配置文件第一个配置项default用于指定默认队列驱动,修改.env中的QUEUE_DRIVER即可。connections配置项包含Laravel支持的所有队列驱动。我们使用的是Redis驱动,所以需要配置redis项:connection对应config/database.php中redis的默认配置;queue是默认的队列名称;expire是队列任务过期时间(秒)。这里我们可以保持其默认配置不变。失败配置项用于配置失败队列任务存放的数据库和数据表。这里需要根据自己的数据库配置进行修改。使用redis队列驱动需要在配置文件config/database.php中配置Redis数据库连接。如果Redis队列连接使用RedisCluster(集群),队列名必须包含keyhashtag,以保证给定队列对应的所有Rediskey都存储在同一个hashslot中:'redis'=>['driver'=>'redis','connection'=>'default','queue'=>'{default}','retry_after'=>90,],注意:建议一般小程序使用Redis作为队列驱动中型应用程序。3、驱动准备知识库需要一个数据库队列来驱动,需要一个数据表来保存任务信息(比如失败的任务)。要生成创建这些表的迁移,您可以在项目目录中运行Artisan命令queue:table。migration创建完成后,可以使用migrate命令生成这些表:phpartisanqueue:tablephpartisanqueue:failed_jobsphpartisanmigrate生成failed_jobs、jobsafterrunning、migrations三个表。四、创建任务1、生成任务类通常,所有的任务类都存放在app/Jobs目录下。app/Jobs在laravel中不存在,它会在运行make:jobArtisan命令时自动创建。可以通过ArtisanCLI生成队列任务类:phpartisanmake:jobProcessPodcast生成实现了Illuminate\Contracts\Queue\ShouldQueue接口的类,告诉Laravel将任务推送到队列而不是立即运行:app/中lumen的作业目录已存在。由于无法执行artisan命令,复制目录下的ExampleJob.php即可。该文件继承自Job.php,实现了ShouldQueue。2.任务类结构任务类很简单,通常只包含处理任务的handle方法,在处理任务时调用。注意,我们可以在任务的handle方法中进行依赖注入。Laravel服务容器会自动注入这些依赖项。3.分发任务创建任务类后,可以通过任务本身的dispatch方法分发到队列中。dispatch方法唯一需要的参数是任务的实例:lumen中的用法:4.指定最大失败次数一种实现指定队列任务最大失败次数的方法是通过Artisan命令切换--tries:phpartisanqueue:work--tries=3不过,你也可以在任务类本身定义最大失败次数,以实现更细粒度的控制。如果任务中指定了最大失败次数,则其优先级高于命令行指定的值:addSeconds(5);}注意:你也可以在队列时间监听器中定义retryUntil方法。7.频率限制注意:此功能需要应用程序能够与Redis服务器进行交互。如果您的应用程序使用Redis,您可以使用时间或并发来控制排队的任务。当排队任务与具有速率限制的API交互时,此功能很有用,例如,使用throttle方法,您可以将给定类型的任务限制为每60秒仅运行10次。如果无法获取到锁,则需要将任务释放回队列,以便再次执行:Redis::throttle('key')->allow(10)->every(60)->then(function(){//作业逻辑。..},function(){//无法获得锁...return$this->release(10);});注意:在上面的例子中,上面的方法可能找不到,但是可以直接复制使用(具体不清楚,知道的大神可以留言指教)。key可以是唯一标识您要限制访问的任务类型的任何字符串。例如,这个键可以根据任务类名和对其进行操作的Eloquent模型的ID来构造。8.最大进程数除此之外,您还可以指定可以同时处理给定任务的最大进程数。当排队的任务正在编辑一次只能由一个任务处理的资源时,此功能很有用。例如,使用漏斗方法,您可以让给定类型的作业一次仅由一个工作进程处理:Redis::funnel('key')->limit(1)->then(function(){//作业逻辑...},function(){//无法获得锁...return$this->release(10);});注意:当使用速率限制时,任务在成功运行之前需要的最大尝试次数是一个艰难的权衡,因此,频率限制和基于时间的尝试相结合是一个不错的选择。9.运行队列进程Laravel自带一个队列进程来处理新推入队列的任务。您可以使用queue:work命令运行队列进程。请注意队列进程开始运行后,它会持续监控队列,直到你手动停止或关闭终端:phpartisanqueue:work注意:为了保持队列进程queue:work在后台运行,你需要使用进程守护进程,例如Supervisor确保队列进程保持运行。简单处理可以使用phpartisanqueue:work--daemon&10。运行队列侦听器以启动队列监控。Laravel包含一个Artisan命令来运行推送到队列的任务的执行。您可以使用queue:listen命令来运行监听器:phpartisanqueue:listen注意:queue:listen的性能比queue:work--daemon差很多。你也可以指定监听哪个连接队列:phpartisanqueue:listenconnection-name请记住,队列进程是一个长期存在的进程,启动后会驻留在内存中。对应用程序的任何更改都不会影响已经启动的进程。所以请在释放程序后重新启动队列进程。可以通过Aritisan命令queue:restart优雅地重启队列进程:phpartisanqueue:restart该命令会在队列进程完成正在进行的任务后结束进程,避免队列任务丢失或出错。由于queue进程在执行queue:restart命令后会死掉,所以还是需要通过进程守护进程如Supervisor来自动重启queue进程。注意:队列使用缓存来存储重启信号,因此在使用此功能之前需要验证缓存驱动程序是否正确配置。五、配置Supervisor安装SupervisorSupervisor是Linux系统中常用的进程守护进程。如果队列进程queue:work意外关闭,它会自动重启启动队列进程。在Ubuntu上安装Supervisor非常简单:sudoapt-getinstallsupervisor注意:如果你自己配置Supervisor有困难,可以考虑使用LaravelForge,它会自动为Laravel项目安装和配置Supervisor。配置SupervisorSupervisor的配置文件通常存放在/etc/supervisor/conf.d目录中。在这个目录下,可以创建多个配置文件来指示Supervisor如何监控进程。例如,让我们创建一个laravel-启动并监控queue:work进程worker.conf文件:[program:laravel-worker]process_name=%(program_name)s_%(process_num)02dcommand=php/home/forge/app.com/artisanqueue:workredis--sleep=3--tries=3--daemonautostart=trueautorestart=trueuser=forgenumprocs=8redirect_stderr=truestdout_logfile=/home/forge/app.com/worker.log在这个例子中,numprocs指令告诉Supervisor运行8个queue:work进程并在它们失败时监控它们自动重启。当然,您需要修改queue:worksqs的命令指令来映射您的队列连接。启动Supervisor当配置文件创建成功后,需要刷新Supervisor的配置信息,使用以下命令启动进程:sudosupervisorctlrereadsudosupervisorctlupdatesudosupervisorctlstartlaravel-worker:grepphp命令查看启动的php进程。您可以从Supervisor官方文档中获取更多信息。CentOS中的配置略有不同:yum-yinstallpython-setuptoolseasy_installsupervisorsupervisor安装完成后会生成三个执行程序:supervisortdsupervisor的守护服务(用于接收进程管理命令)supervisorctlclient(用于与进程通信)daemonprocess,发送指令来管理进程)echo_supervisord_conf生成程序的初始配置文件。将配置文件重定向到/etc/目录mkdir/etc/supervisorcho_supervisord_conf>/etc/supervisor/supervisord.conf默认的配置文件是/etc/supervisor/supervisord.conf。编辑配置文件:找到最后一行,导入自定义配置文件;[include];files=conf.d/*.ini去掉“;”在[include]和files前面,include生效,在/etc/supervisor/.d文件夹下创建conf,在里面添加一个类似ubuntu的配置文件。mkdirconf.dstart:supervisordstartsupervisorsupervisorctlcontrolsupervisord启动后会看到一堆信息,但不影响。/usr/lib/python2.7/site-packages/supervisor/options.py:296:UserWarning:Supervisord正在以root身份运行,它正在默认位置(包括其当前工作目录)中搜索其配置文件;您可能希望指定一个“-c”参数来指定配置文件的绝对路径以提高安全性。'Supervisordisrunningasrootanditissearching'可以指定一个配置文件:supervisord-c/etc/supervisord.conf每次配置修改后supervisorctlreload需要重启才能生效supervisorctlreload监控状态:supervisorctlstatusattachesasqserror处理,redis方法不使用sqsInSqsConnector.phpline26:Class'Aws\Sqs\SqsClient'notfound使用composer安装:composerrequireaws/aws-sdk-php-laravel本文参考:laravelacademy
