Laravel --Jobs (同步\異步)消息隊列 Queue --晉升篇
在很多項目業務復雜到一定程度、項目大到一定程度,就都是一些重構、優化、升級等手段,讓項目更穩健;能抵擋更強的“風暴”。而
異步服務器則也是減輕服務器壓力,提高項目性能的一個常見手段之一,把一些實時性不強,而且量還比較大的業務可以異步來解決。臨近年底了,丟丟哥最近工作比較忙,博客更新少了點。見諒

本篇博客主要介紹 異步消息隊列 簡要的介紹下同步消息隊列
本篇博客為了更明確異步消息隊列和同步消息隊列的實現原理 以MySQL消息隊列為示例,但是在真正的項目中(如果沒有單獨的異步服務器,則建議使用Redis消息隊列)
一、簡介
Laravel 的隊列服務為不同的隊列后端系統提供了一套統一的 API 。隊列允許你將一個耗時的任務進行延遲處理,例如像 e-mail 發送。這能讓應用程序對頁面的請求有更快的響應。
二、配置
隊列的配置文件被保存在 config/queue.php 中。但是Laravel中優先選用.env的配置在這個文件內你可以找到包含在 Laravel 中的每一種隊列驅動連接設置。它們包含了數據庫、Beanstalkd、IronMQ、Amazon SQS、Redis 以及提供本機使用的 synchronous 驅動。
.env配置同步:

.env配置異步:

另外框架也提供了 null 這個隊列驅動用來丟棄隊列任務。
1.生成隊列數據庫表與失敗隊列數據庫表
本實例中是用群發email的實例,如果模仿,請配置自己的郵件服務
php artisan queue:table php artisan queue:failed-table php artisan migrate
2.創建Mysql數據(需要發郵件)

3.生成隊列任務
php artisan make:job SendUserEmail --queued
然后在項目的App\Jobs里面會生成一個SendUserEmail.php文件
接下來 我們再生成一個控制器UserController
php artisan make:controller UserController --resource
- 定義路由
routes.php
Route::resource('/user','UserController');
- 編寫控制器
UserController
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Jobs\CreateMessage; use App\Jobs\SendUserEmail; class UserController extends Controller { ... ... /** * 這個方法我們用來模擬發送消息隊列. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { // $datas = \DB::table('user')->where('status',1)->get(); foreach($datas as $data){ $job = (new SendUserEmail($data->name,$data->email)); $this->dispatch($job); } return redirect('/user'); }
- 編輯隊列文件
SendUserEmail.php
<?php namespace App\Jobs; use App\Jobs\Job; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Bus\SelfHandling; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Support\Facades\Mail; class SendUserEmail extends Job implements SelfHandling, ShouldQueue { use InteractsWithQueue, SerializesModels; protected $name; protected $email; /** * Create a new job instance. * * @return void */ public function __construct($name, $email) { // $this->name = $name; $this->email = $email; } /** * Execute the job. * * @return void */ public function handle() { // 如果參試大於三次 if ($this->attempts() > 3) { \Log::info($this->name.'郵件參試失敗過多'); }else{ // 每次進來休息3秒鍾 sleep(3); // 休息10秒鍾 //$this->release(10); $url = 'http://www.ydma.cn'; $title = '測試郵件'; $to = $this->email; // 郵件發送 $flag = Mail::send('email.test', ['name' => $this->name, 'url' => $url], function ($message) use ($to, $title) { // 發送 $message->to($to)->subject('【親愛的程序猿】' . $title); }); echo date('Y-m-d H:i:s')."\n".$to.'的郵件已發送...'; if($flag){ \Log::info($this->name.'郵件發送成功'); }else{ \Log::info($this->name.'郵件發送失敗'); } } } /** * 處理一個失敗的任務 * * @return void */ public function failed() { \Log::error($this->name.'隊列任務執行失敗'."\n".date('Y-m-d H:i:s')); } }
三、執行程序
1.我們env是設置的database (異步消息隊列)
2.開啟隊列監聽
php artisan queue:listen
3.或者 開啟后台監聽(不影響自己輸入其他命令)
php artisan queue:listen &
4.也能用work 后面參數是休息時間和嘗試次數
php artisan queue:work connection --daemon --sleep=3 --tries=3
5.訪問網址(這個網址是我自己本地的)

6.然后看我的Mysql的變化jobs表本來有8條隊列數據需要處理 
7.然后看終端監聽的變化

8.消息隊列被一條條的推送..反觀數據庫jobs的變化,發現被清空了,說明隊列執行完了 
而且頁面並不是等待郵件發完才跳轉,而是發送這個隊列命令后直接重定向到了user列表頁面(跳轉很快),這就是異步隊列的整個工作流程
當然如果你看了我之前的一片文章也可以做做全局SQL監聽,你就會在日志中發現,每執行一個隊列 job表里面就要執行4次命令增、刪、改、查,如果是10000條數據的隊列就是40000次的表操作,所以說database的消息隊列用也得當心,雖然是異步的,考慮的因素還是比較多的。
同步消息隊列
這個消息隊列,說實話丟丟哥我也是用得少,為什么呢?暫時並沒有發現它的應用場景的優勢。
與異步不同的是設置同步消息隊列 將.env或config/queue.php 里面的配置改成是 sync
然后執行頁面的時候發現頁面等待跳轉的時間很長,得所有的郵件發送完成后才會跳轉頁面(如果隊列中有任務執行失敗反復的參試 那這頁面應該肯定timeout了)
擴展思路
1.隊列有可能失敗,失敗的隊列會寫入到mysql的failed_jobs表里面:

2.那么如何讓這些失敗的隊列讓電腦后面自動去執行消息推送呢?也就是執行這些命令,怎么讓程序自動完成

3.如果是在一個服務器中用消息隊列,是不是一直要開常駐進程??那是不是有消耗?當異步到達一個程度的時候,是不是可以開服務器集群里面的異步服務器專門來做這個事??

希望我的博客對你們有所幫助,你的認可就是我最大的動力。。
https://www.blog8090.com/
本文為作者原創,允許轉載,轉載后請以鏈接形式說明文章出處. 如轉載但不標明來源,后果自負。
