摘要:配置項用于配置失敗隊列任務存放的數據庫及數據表。要使用隊列驅動,需要在配置文件中配置數據庫連接。如果應用使用了,那么可以使用時間或并發來控制隊列任務。你可以使用命令運行這個隊列進程。如果隊列進程意外關閉,它會自動重啟啟動隊列進程。
一、概述
在Web開發中,我們經常會遇到需要批量處理任務的場景,比如群發郵件、秒殺資格獲取等,我們將這些耗時或者高并發的操作放到隊列中異步執行可以有效緩解系統壓力、提高系統響應速度和負載能力。
二、配置文件我們仍然從配置文件開始,首先我們需要在配置文件中配置默認隊列驅動為Redis。lumen沒有配置文件,可以從laravel項目中拷貝一份config目錄過來。
隊列配置文件是config/queue.php:
return [ "default" => env("QUEUE_DRIVER", "sync"), "connections" => [ "database" => [ "driver" => "database", "table" => "jobs", "queue" => "default", "expire" => 60, ], "redis" => [ "driver" => "redis", "connection" => "default", "queue" => "default", "expire" => 60, ], ], "failed" => [ "database" => "mysql", "table" => "failed_jobs", ], ];
配置文件第一個配置項default用于指定默認的隊列驅動,修改.env中的QUEUE_DRIVER即可。
connections配置項包含了Laravel支持的所有隊列驅動,我們使用Redis驅動,所以需要配置redis項:connection對應config/database.php中redis的default配置;queue為默認隊列名稱;expire為隊列任務過期時間(秒)。這里我們可以保持其默認配置不變。
failed配置項用于配置失敗隊列任務存放的數據庫及數據表。這里我們需要按照自己的數據庫配置對其做相應修改。
要使用 redis 隊列驅動,需要在配置文件 config/database.php 中配置 Redis 數據庫連接。
如果 Redis 隊列連接使用 Redis Cluster(集群),隊列名稱必須包含 key hash tag,以確保給定隊列對應的所有 Redis keys 都存放到同一個 hash slot:
"redis" => [ "driver" => "redis", "connection" => "default", "queue" => "{default}", "retry_after" => 90, ],
注:對一般中小型應用推薦使用 Redis 作為隊列驅動。三、驅動預備知識
數據庫
要使用 database 隊列驅動,你需要數據表保存任務信息(比如失敗任務)。要生成創建這些表的遷移,可以在項目目錄下運行 Artisan 命令 queue:table,遷移被創建之后,可以使用 migrate 命令生成這些表:
php artisan queue:table php artisan queue:failed_jobs php artisan migrate
運行后生成failed_jobs、jobs、migrations三張表。
四、創建任務 1、生成任務類通常,所有的任務類都保存在 app/Jobs 目錄。laravel中 app/Jobs 不存在,在運行 Artisan 命令 make:job 的時候,它將會自動創建。你可以通過 Artisan CLI 來生成隊列任務類:
php artisan make:job ProcessPodcast
生成的類都實現了 IlluminateContractsQueueShouldQueue 接口, 告訴 Laravel 將該任務推送到隊列,而不是立即運行:
lumen中 app/Jobs目錄已經存在,由于不能執行artisan命令,直接復制目錄中的ExampleJob.php即可。該文件繼承Job.php 從而實現了ShouldQueue。
2、任務類結構任務類非常簡單,通常只包含處理該任務的 handle 方法,在任務被處理的時候調用,注意我們可以在任務的 handle 方法中進行依賴注入。Laravel 服務容器會自動注入這些依賴。
3、分發任務創建好任務類后,就可以通過任務自身的 dispatch 方法將其分發到隊列。dispatch 方法需要的唯一參數就是該任務的實例:
lumen中用法:
4、指定最大失敗次數指定隊列任務最大失敗次數的一種實現方式是通過 Artisan 命令 --tries 切換:
php artisan queue:work --tries=3
不過,你還可以在任務類自身定義最大失敗次數來實現更加細粒度的控制,如果最大失敗次數在任務中指定,則其優先級高于命令行指定的數值:
5、超時注:timeout 方法為 PHP7.1+ 和 pcntl 擴展做了優化。類似的,隊列任務最大運行時長(秒)可以通過 Artisan 命令上的 --timeout 開關來指定:
php artisan queue:work --timeout=30同樣,你也可以在任務類中定義該任務允許運行的最大時長(單位:秒),任務中指定的超時時間優先級也高于命令行定義的數值:
6、基于時間的嘗試次數除了定義在任務失敗前的最大嘗試次數外,還可以定義在指定時間內允許任務的最大嘗試次數,這可以通過在任務類中添加 retryUntil 方法來實現:
/** * Determine the time at which the job should timeout. * * @return DateTime */ public function retryUntil() { return now()->addSeconds(5); }注:還可以在隊列時間監聽器中定義 retryUntil 方法。7、頻率限制注:該功能要求應用可以與 Redis 服務器進行交互。如果應用使用了 Redis,那么可以使用時間或并發來控制隊列任務。該功能特性在隊列任務與有頻率限制的 API 交互時很有幫助,例如,通過 throttle 方法,你可以限定給定類型任務每 60 秒只運行 10 次。如果不能獲取鎖,需要將任務釋放回隊列以便可以再次執行:
Redis::throttle("key")->allow(10)->every(60)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); });注:在上面的例子中,上面的方法可能無法找到,但是直接復制即可使用(具體還不清楚,知道的大神可以留言指教)。key 可以是任意可以唯一標識你想要限定訪問頻率的任務類型的字符串。舉個例子,這個鍵可以基于任務類名和操作 Eloquent 模型的 ID 進行構建。
8、最大進程數量除此之外,還可以指定可以同時處理給定任務的最大進程數量。這個功能在隊列任務正在編輯一次只能由一個任務進行處理的資源時很有用。例如,使用 funnel 方法你可以給定類型任務一次只能由一個工作進程進行處理:
Redis::funnel("key")->limit(1)->then(function () { // Job logic... }, function () { // Could not obtain lock... return $this->release(10); });注:使用頻率限制時,任務在運行成功之前需要的最大嘗試次數很難權衡,因此,將頻率限制和基于時間的嘗試次數結合起來使用是個不錯的選擇。9、運行隊列進程Laravel 自帶了一個隊列進程用來處理被推送到隊列的新任務。你可以使用 queue:work 命令運行這個隊列進程。請注意,隊列進程開始運行后,會持續監聽隊列,直至你手動停止或關閉終端:
php artisan queue:work注:為了保持隊列進程 queue:work 持續在后臺運行,需要使用進程守護程序,比如 Supervisor 來確保隊列進程持續運行。10、運行隊列監聽器簡單處理可以使用 php artisan queue:work --daemon &
開始進行隊列監聽
laravel 包含了一個 Artisan 命令來運行推送到隊列中的任務的執行。你可以使用 queue:listen 命令來運行監聽器:php artisan queue:listen注意:queue:listen要比queue:work --daemon 性能差很多。你也可以指定監聽哪一個連接的隊列:
php artisan queue:listen connection-name
請記住,隊列進程是長生命周期的進程,會在啟動后駐留內存。若應用有任何改動將不會影響到已經啟動的進程。所以請在發布程序后,重啟隊列進程。可以通過 Aritisan 命令 queue:restart 來優雅地重啟隊列進程:
php artisan queue:restart該命令將在隊列進程完成正在進行的任務后,結束該進程,避免隊列任務的丟失或錯誤。由于隊列進程會在執行 queue:restart 命令后死掉,你仍然需要通過進程守護程序如 Supervisor 來自動重啟隊列進程。
注:隊列使用緩存來存儲重啟信號,所以在使用此功能前你需要驗證緩存驅動配置正確。五、配置 Supervisor安裝 Supervisor
Supervisor 是 Linux 系統中常用的進程守護程序。如果隊列進程 queue:work 意外關閉,它會自動重啟啟動隊列進程。在 Ubuntu 安裝Supervisor 非常簡單:
sudo apt-get install supervisor注:如果自己配置 Supervisor 有困難,可以考慮使用 Laravel Forge,它會為 Laravel 項目自動安裝并配置 Supervisor。配置 Supervisor
Supervisor 配置文件通常存放在 /etc/supervisor/conf.d 目錄,在該目錄下,可以創建多個配置文件指示 Supervisor 如何監視進程,例如,讓我們創建一個開啟并監視 queue:work 進程的 laravel-worker.conf 文件:
[program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command= php /home/forge/app.com/artisan queue:work redis --sleep=3 --tries=3 --daemon autostart=true autorestart=true user=forge numprocs=8 redirect_stderr=true stdout_logfile=/home/forge/app.com/worker.log在本例中,numprocs 指令讓 Supervisor 運行 8 個 queue:work 進程并監視它們,如果失敗的話自動重啟。當然,你需要修改 queue:work sqs 的 command 指令來映射你的隊列連接。
啟動 Supervisor
當成功創建配置文件后,需要刷新 Supervisor 的配置信息并使用如下命令啟動進程:
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start laravel-worker:*使用top 或者ps aux | grep php 命令可以看到啟動的php進程。
你可以通過 Supervisor 官方文檔獲取更多信息。在CentOS中配置稍微有些區別:
yum -y install python-setuptools easy_install supervisorsupervisor安裝完成后會生成三個執行程序:
supervisortd supervisor的守護進程服務(用于接收進程管理命令)
supervisorctl 客戶端(用于和守護進程通信,發送管理進程的指令)
echo_supervisord_conf 生成初始配置文件程序。將配置文件重定向到/etc/目錄下面
mkdir /etc/supervisor echo_supervisord_conf > /etc/supervisor/supervisord.conf默認配置文件在/etc/supervisor/supervisord.conf 。
編輯配置文件:找到最后一行,引入自定義配置文件;[include] ;files = conf.d/*.ini去掉[include]和files前面的“;” include生效,在/etc/supervisor/下創建conf.d文件夾,在其中添加類似ubuntu中配置文件。
mkdir conf.d啟動:
supervisord 啟動supervisor
supervisorctl 控制supervisord
啟動后會看到一堆信息,但是不影響。/usr/lib/python2.7/site-packages/supervisor/options.py:296: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security. "Supervisord is running as root and it is searching "可指定配置文件: supervisord -c /etc/supervisord.conf
每次修改配置后都需要重啟supervisor才能生效
supervisorctl reload監控狀態:
supervisorctl status
附一個sqs錯誤處理,redis方式不使用sqs
In SqsConnector.php line 26: Class "AwsSqsSqsClient" not found使用 composer 安裝:
composer require aws/aws-sdk-php-laravel本文參考:laravel學院
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28721.html
摘要:解決這句移到下方,可解決隊列錯誤發現異步有些不會處理,同問這個問題,目前沒有解決。開啟后,自動監聽任務,線程數決定刷新頻率。問題可使用重新生成在環境中也會有遇到,需要設置的和項目一致 持續更新。。。 這里收集了遇見的laravel 或則 lumen 錯誤 和解決方法。 controller或者model不存在 1. not found Class AppUserController ...
摘要:現在的提供了一種更易于使用和維護的計劃任務方式。注意事項建議開啟這樣會極大的加速類的加載。 lumen 為速度而生的 Laravel 框架 官網的介紹很簡潔,而且 lumen 確實也很簡單,我在調研了 lumen 相關組件(比如緩存,隊列,校驗,路由,中間件和最重要的容器)之后認為已經能夠滿足我目前這個微服務的需求了。 任務目標 showImg(https://segmentfault...
閱讀 1012·2021-11-23 10:11
閱讀 3854·2021-11-16 11:50
閱讀 921·2021-10-14 09:43
閱讀 2713·2021-10-14 09:42
閱讀 2710·2021-09-22 16:02
閱讀 1056·2019-08-29 10:57
閱讀 3378·2019-08-29 10:57
閱讀 2268·2019-08-26 13:52