借助Laravel Broadcasting你可以使用上時下很熱的Websocket技術。
注意:請務必使用較新版本的 Laravel。Laravel在最近幾個版本進行過比較大的重構,比如路由從 app\Http\routes.php 拆分為到 routes 目錄下的多個文件,包括廣播在內的各個附加組件也都進行了重構並正式寫入文檔。所以網上有些教程(特別是入門教程)可能是根據舊版本來寫的,容易讓你迷惑。當安裝完Laravel后執行以下命令查看Laravel版本
php artisan --version
如果低於 5.4 請重新建立新版本的Laravel,具體方法在下面會詳細講解。
實例背景:
假設場景:
假設我們要使用laravel作為服務端做一個新聞推送系統。用戶打開頁面后不需要刷新頁面即可不斷的獲取到最新的新聞。
環境參數
Homestead 7.4.2
Laravel 5.5 (廣播機制在 5.4 以后進行了一次重構,並正式加入文檔,所以請務必使用 5.4 及其以上版本)
PHP 7.1
Redis 4.0.9 (Homestead 自帶redis)
————————————————
廣播架構
目前有兩種廣播機制可選:
pusher:laravel自帶方案,但是有使用限制,需要收費
Redis + socket.io:無限制
我們使用業界較流行的Redis + socket.io 方案 。
接下來你會信息爆炸似的接收到好幾個新名詞:
laravel-echo-server:使用 socket.io 機制實現的 broadcasting 服務端
laravel-echo:laravel-echo是 laravel broadcasting 的客戶端。注意,laravel-echo 並不是 laravel-echo-server 專屬的客戶端, laravel-echo 有兩種連接機制可以選:pusher 和 socket.io 。 而 laravel-echo-server 是開發出來專門用於 socket.io連接的服務端。如果你使用的是 pusher,那么不需要使用 laravel-echo-server ,但是你依然要使用 laravel-echo
Socket.IO:websocket 的一種nodejs實現。laravel-echo 如果要使用socket.io 則需要先安裝 socket.io-client。
Predis:redis客戶端的php實現,如果要使用redis作為廣播機制的實現,則需要先安裝 predis
Laravel Event:廣播事件類
Laravel Queue:廣播機制是基於queue機制來實現的
Redis Sub/Pub:Redis的訂閱機制。laravel-echo-server本質上只是一個Redis訂閱服務的訂閱者。
這幾樣東西配合起來的架構圖如下
根據這幅圖我們可以知道事件的廣播機制流程:
Laravel 通過 broadcasting 機制發布一個Event對象到Redis
Laravel Queue Worker 讀取該Event對象,並使用Redis的Sub/Pub機制將該 Event對象發布出去
laravel-echo-server 通過 Redis 的 Sub/Pub機制收聽到該 Event
由於 laravel-echo 使用 socket.io 跟 laravel-echo-server相連接。所以 laravel-echo 會通過socket.io將Event對象發送給laravel-echo
laravel-echo解析通過 socket.io接收到的 Event對象
廣播事件種類:
public:誰都可以收聽的廣播
private:只有指定用戶可以收到的廣播
presence:不僅可以收聽到跟你有關的廣播,還可以跟別的用戶互動,適合做聊天室
我們假設的場景是新聞推送系統,所以使用最簡單的public廣播就可以實現。接下來我們詳細的來講解如何將這些組件配置好,並連接起來。
我們按照廣播機制的流程來一步一步的設置廣播機制。
1、注冊 BroadcastServiceProvider,打開 config/app.php 找到 'provides' 屬性,將 BroadcastServiceProvider 前的注釋去掉
2、安裝redis(不改動的情況下安裝好后redis使用默認即可)
composer required predis/predis
3、配置.env文件
由於廣播機制是基於queue機制實現的。所以queue的存儲設置會直接決定廣播事件的存儲位置 BROADCAST_DRIVER=redis 設置queue為redis QUEUE_DRIVER=redis
4、建立事件(event)
php artisan make:event loginLogEvent
修改事件源碼增加廣播頻道:
/*增加對 ShouldBroadcast 的實現*/ class loginLogEvent implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $message; /** * Create a new event instance. * * @return void */ public function __construct($news_message) { $this->message = $news_message; } /** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */ public function broadcastOn() { return new Channel('loginLogEvent'); } }
5、增加廣播路由(routes\channels.php)
/*channel 方法接收兩個參數:頻道名稱和一個回調函數,該回調通過返回 true 或者 false 來表示用戶是否被授權監聽該頻道*/ Broadcast::channel('loginLogEvent',function ($user,$id) { return true; });
6、測試廣播:
1)編輯 routes/console.php ,增加 bignews 命令:
/*自定義命令*/ Artisan::command('bignews', function () { broadcast(new loginLogEvent(date('Y-m-d h:i:s A').": BIG NEWS!")); $this->comment("news sent");})->describe('Send news');
2)測試命令:
輸入:php artisan bignews
通過 redis-cli 查看當前redis中的數據,發現多出來一個queue對象,證明連接成功了,如果沒有,請檢查env配置中的queue配置是否正確
你還你可以在queue worker的執行界面看到該Event已經被檢測到,並通過Redis Sub/Pub機制傳播出去了
7:安裝並配置 laravel-echo-server
1)安裝
npm install -g laravel-echo-server
2)初始化 Socket 服務(切記在生產環境中,無論你什么時候使用它,都應該關掉你的開發者模式)
laravel-echo-server init
它會幫你在項目根目錄下生成 laravel-echo-server.json
3)啟動laravel-echo-server
啟動/停止 laravel-echo-server start/stop
啟動后,在新打開一個終端窗口,輸入 php artisan bignews 顯示如下證明廣播推送到了laravel-echo-server
8:端口映射:
因為laravel-echo-server使用的是 6001 端口,所以記得去 Homestead.yaml里面添加6001 端口的映射
使用命令:vagrant reload 重載生效
9、瀏覽器收聽廣播
1)安裝組件
/*由於前端使用的是 laravel-echo來收聽廣播,我們選擇的底層實現方式是socket.io。所以首先我們要在package.json中添加 laravel-echo 和 socket.io的依賴*/ npm i --save laravel-echo npm i --save socket.io-client
2)配置/resources/assets/js/bootstrap.js
import Echo from 'laravel-echo' /*使用 pusher window.Pusher = require('pusher-js'); window.Echo = new Echo({ broadcaster: 'pusher', key: 'your-pusher-key', cluster: 'mt1', encrypted: true }); */ /*使用 socket.io-client*/ window.io = require('socket.io-client'); window.Echo = new Echo({ broadcaster: 'socket.io', host:window.location.hostname+':6001' });
3) 重新編譯app.js 文件
注意:*默認使用 http:
//registry.npmjs.org在國內不穩定,如果出現404錯誤,可切換使用國內鏡像*
npm config set registry=
https://registry.npm.taobao.org
npm run dev
4) 建立測試文件
在resources\views\目錄下新建boradcast.blade.php 文件,放入以下內容
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>News Room</title> <link href="{{ mix('css/app.css') }}" rel="stylesheet"> </head> <body> <div class="content"> News Room </div> <script src="{{ mix('js/app.js') }}"></script> <script> /*收聽loginLogEvent通道內的loginLogEvent事件對象,將接收到的事件在控制台打印出來。*/ Echo.channel('loginLogEvent') .listen('loginLogEvent', (e) => { alert(JSON.stringify(e)); console.log(e.message); }); </script> </body>
5)在rotues/web.php 加入路由路徑
Route::view('broadcast','boradcast');
6)查看效果
啟動步驟:打開一個命令窗口啟動 : laravel-echo-server start
再打開一個窗口啟動隊列啟動隊列: php artisan queue:work
給隊列加內容: php artisan bignews
參考:https://blog.csdn.net/nsrainbow/article/details/80428769