其中對隊列的使用使用的方法記錄一下, 方便以後查閱.
-
1
首先檢查自己的環境是否符合要求[其中我用php7是因爲我係統裏面有多個php版本]
php -v
composer --version
-
2
接着使用composer初始化一個基於laravel5.5版本的項目
composer create-project laravel/laravel laravel-queue --prefer-dist "5.5.*"
-
3
爲了演示隊列的使用,我們將使用基於數據庫驅動的隊列,但是真實項目建議使用redis或者rabbitmq或者fakfa等專業的隊列服務.修改項目中的.env配置文件
DB_HOST=數據庫主
DB_PORT=數據庫端
DB_DATABASE=數據庫
DB_USERNAME=數據庫用
DB_PASSWORD=數據庫密碼
QUEUE_DRIVER=database
並創建laravel-queue數據庫
CREATE DATABASE `laravel-queue` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
-
4
準備工作做好了,那我們就開始寫代碼了,我們使用laravel提供的腳手架生成處理隊列的任務類DemoQueue
php artisan make:job DemoQueue
這個時候會在你的項目下面多了一個Jobs目錄,最終生成的任務處理文件就在目錄下面
如: /xxx/laravel-queue/app/Jobs/DemoQueue.php
-
處理隊列的任務類,但是現在我們還沒有要處理的隊列,那麼我們接着使用laravel提供的腳手架生成隊列使用的數據庫
//查看laravel提供了那些腳手架功能
php artisan
//使用php artisan queue:table 生成數據隊列驅動的表結構
php artisan queue:table
//執行數據庫遷移也就是創建表
php artisan migrate
執行完上面的動作之後,如果你前面的數據配置正確,那麼你應該和我一樣會看到圖片上的效果
-
數據表也有,那麼模擬幾條隊列數據到隊列裏面去,那麼就隨便創建一個控制來模擬幾條數據到隊列服務裏面去.
//生成控制器
php artisan make:controller DemoController
//啓動一個內部虛擬服務器
php artisan serve
//配置web.php的請求路由
Route::get('demo','DemoController@demo');
//新開一個窗口用curl請求
curl -i localhost:8000/demo
如果不出意外的話,這個時候jobs表裏面就有了三條待處理的消息了
-
消費隊列,前面都好理解就是在消費隊列的時候,有幾個小坑大家要注意,因爲在消費隊列的時候誰都不能保證服務就一直在如期執行,總會發生點什麼意外.有人說可以用try catch捕獲,但是不是這樣的,即使你在DemoQueue裏面捕獲,你也拿回去不到異常信息, 跟蹤源碼發現,是在隊列的接口在進行了捕獲, 那我們先不考慮錯誤的情況, 就假如一切都很順利的執行了
//執行這個命令消費隊列
php artisan queue:work --queue=demo
-
但是你擔心的事情總會發生的,既然我們知道有些事情會發生那我們就應該提前做好對應的措施,這樣你就有更多的時間學習新的東西,剛纔我們在DemoQueue裏面定義了一個$tries 屬性, 隊列在處理次數達到這個值的時候還是沒有成功的話就會寫入到失敗的隊列表裏面去,那現在我們就去模擬一下隊列失敗的情況.
//在生成3條測試隊列的數據
curl -i localhost:8000/demo
//消費隊列
php artisan queue:work --queue=demo
這個時候我們看效果, 隊列在嘗試了三次之後失敗了,就把原來的隊列給刪除了,這個時候如果我們不及時處理的話,就會丟失數據.通過分析錯誤日誌我可以查到一個很重要的信息,那就是我們缺少一個failed_jobs表
-
那問題來了, 我們怎麼保存處理失敗的隊列那, 其實很簡單laravel的隊列服務提供了補救措施.
//生成failed_jobs表
php artisan queue:failed-table
//執行數據庫遷移
php artisan migrate
-
這下放心了, 有了保存隊列失敗的表,我們就不要擔心隊列丟失的問題了,再次生成模擬數據,進行隊列消費
//在生成3條測試隊列的數據
curl -i localhost:8000/demo
//消費隊列
php artisan queue:work --queue=demo
這次隊列消費還是失敗了,但是奇妙的是我們的失敗隊列被保存到了failed-table表裏面去了
-
即然我知道我們的隊列有問題, 那我們就應該去修復這個bug, 或許這個時候你想問有沒有一種方法,就是隊列處理失敗的時候給開發人員發送郵件通知開發人員緊急修復那?對你想的很對,laravel之所以很優雅就是很多設計都很人性化. laravel提供了一個failed方法,laravel的隊列會在達到最大重試次數還沒有處理成功後就會調用這個方法, 所以你可以可以在這個方法裏面寫發送郵件的邏輯給開發人員發送告警郵件.這個方法接收一個Exception 類型的參數.那我們去增加這個方法.
//在生成3條測試隊列的數據
curl -i localhost:8000/demo
//消費隊列
php artisan queue:work --queue=demo
從錯誤日誌裏面,我們可以看到failed方法被成功調用了, 所有你可以在這裏寫發送郵件的邏輯了.
-
對了, 其實在上一步的時候, 我們還是沒有把剛纔失敗的隊列給找回來, 好的馬上就要寫完了, 我們把剛纔失敗的隊列找回來, 接着我把我剛纔模擬的錯誤代碼去掉, 然後執行laravel提供的方法找回隊列, 找回來的隊列會重重新放到jobs表中.是不是我說的這樣我們可以試試.
//執行如下命令找回處理失敗的隊列
php artisan help queue:retry
後面可以跟failed-table表的id,如果跟id的話, 只會回覆對應id值的失敗隊列到jobs表中, 如果跟all的話全部失敗的隊列都會重新放回jobs表中
-
最後我們再次執行隊列消費的命令就可以消費剛纔失敗的隊列了.
//消費隊列
php artisan queue:work --queue=demo
到這裏,我們要說的隊列的正確使用的方法就到這裏了, 其中有幾個很重要的地方我們要總結一下
1.執行隊列的時候一定要加上--tries參數 最好也指定消費的隊列名稱和連接驅動,如果你不喜歡這樣做的話可以寫到DemoQueue裏面
如:/xxx/php /yyyy/artisan queue:work redis --sleep=3 --tries=3 --queue=zzz
2.除了這種方式laravel還提供一種Queue事件監聽的方式來處理失敗的隊列,這種方式大家可以自行嘗試.
-
我們學到了什麼?
一 .或許你看完這篇經驗,還是一頭霧水,那我建議你多看看laravel的手冊,總有一頭你會恍然大悟,會感慨laravel的設計如此的美妙.
二. 要學會總理解laravel隊列的設計思路, 如果我們的業務也有類似的場景,我們完全可以套用這種設計理念, 這也是我這篇經驗想表達的核心思想, 因爲只有理解了別人造的輪子的優點, 你纔可能造出來更好用輪子
三. 大神們請不拍磚,如果這篇經驗有幫助到你歡迎關注,歡迎點贊.
END