在不少項目業務複雜到必定程度、項目大到必定程度,就都是一些重構、優化、升級等手段,讓項目更穩健;能抵擋更強的「風暴」。而
異步服務器
則也是減輕服務器壓力,提升項目性能的一個常見手段之一,把一些實時性不強,並且量還比較大的業務能夠異步
來解決。臨近年末了,丟丟哥最近工做比較忙,博客更新少了點。見諒php
異步消息隊列
簡要的介紹下同步消息隊列本篇博客爲了更明確異步消息隊列
和同步消息隊列
的實現原理 以MySQL
消息隊列爲示例,可是在真正的項目中(若是沒有單獨的異步服務器,則建議使用Redis
消息隊列)css
Laravel
的隊列服務爲不一樣的隊列後端系統提供了一套統一的 API
。隊列容許你將一個耗時的任務進行延遲處理,例如像 e-mail
發送。這能讓應用程序對頁面的請求有更快的響應。mysql
隊列的配置文件被保存在 config/queue.php
中。可是Laravel
中優先選用.env
的配置在這個文件內你能夠找到包含在 Laravel
中的每一種隊列驅動鏈接設置。它們包含了數據庫、Beanstalkd、IronMQ、Amazon SQS、Redis 以及提供本機使用的 synchronous 驅動。laravel
.env配置同步:sql
.env配置異步:數據庫
另外框架也提供了 null 這個隊列驅動用來丟棄隊列任務。後端
本實例中是用羣發email的實例,若是模仿,請配置本身的郵件服務
服務器
php artisan queue:table php artisan queue:failed-table php artisan migrate
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/
本文爲做者原創,容許轉載,轉載後請以連接形式說明文章出處. 如轉載但不標明來源,後果自負。