這篇文章主要給大家介紹了關於Laravel構建即時應用的一種實現方法,即時通訊在我們日常的開發中經常會遇到,本文通過範例程式碼介紹的非常詳細,需要的朋友們可以參考借鑒,下面隨著小編來一起學習學習吧。
即時互動的應用
大家應該都有所體會,在現代的 Web 應用程式中很多情境都需要運用到即時通訊,比如說最常見的支付回調,與三方登入。這些業務情境都基本需要遵循以下流程:
在過去,為了實現這種即時通訊,能讓用戶端正確響應處理結果,最為常用的技術就是輪詢,因為 HTTP 協議的單向性,用戶端只能一遍一遍的主動詢問服務端的處理結果。這種方式有顯見的缺陷,佔用服務端資源不說,還不能即時獲得服務端處理結果。
現在,我們可以使用 WebSocket 通訊協定來處理即時互動,它是一種雙向協議,允許服務端主動推送資訊到用戶端。本篇我們將藉助 Laravel 強大的事件系統來構建即時的互動。你將需要用到以下知識:
Laravel Event
Redis
Socket.io
Node.js
Redis
在開始之前,我們需要開啟一個 redis 服務,並在 Laravel 應用中進行配置啟用,因為在整個流程中,我們需要藉助 redis 的訂閱和發布機制來實現即時通訊。
Redis 是一個開源高效的索引值對儲存系統。它通常作為一個資料結構伺服器來儲存索引值對,它可以支援字串,散列,列表,集合和有序結合。在 Laravel 中使用 Redis 你需用通過 Composer 來安裝 predis/predis 包檔案。
配置
Redis 在應用中的設定檔儲存在 config/database.php,在這個檔案中,你可以看到一個包含了 Redis 服務資訊的 redis 數組:
'redis' => [ 'cluster' => false, 'default' => [ 'host' => '127.0.0.1', 'port' => 6379, 'database' => 0, ],]
如果你修改了 redis 服務的連接埠,請保持設定檔中的連接埠一致。
Laravel Event
這裡我們需要藉助 Laravel 強大的事件廣播能力:
廣播事件
很多現代化的應用中,會使用 Web Sockets 來實現即時互動的使用者介面。當一些資料在服務端變更時,一條訊息會通過 WebSocket 串連來傳遞到用戶端進行處理。
為了協助你構建這種類型的應用。Laravel 使通過 WebSocket 串連進行廣播事件變的非常簡單。Laravel 允許你廣播事件來共用事件的名稱到你的服務端和用戶端的 JavaScript 架構。
配置
所有的事件廣播配置選項都被儲存在 config/broadcasting.php 設定檔中。Laravel 附帶了幾種可用的驅動如 Pusher,Redis,和 Log,我們將使用 Redis 作為廣播驅動,這裡需要依賴 predis/predis 類庫。
由於預設的廣播驅動使用的是 pusher,所以我們需要在 .env 檔案中設定 BROADCAST_DRIVER=redis。
我們建立一個 WechatLoginedEvent 事件類別用來在使用者掃描登入後進行廣播:
<?phpnamespace App\Events;use App\Events\Event;use Illuminate\Queue\SerializesModels;use Illuminate\Contracts\Broadcasting\ShouldBroadcast;class WechatLoginedEvent extends Event implements ShouldBroadcast{ use SerializesModels; public $token; protected $channel; /** * Create a new event instance. * * @param string $token * @param string $channel * @return void */ public function __construct($token, $channel) { $this->token = $token; $this->channel = $channel; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return [$this->channel]; } /** * Get the name the event should be broadcast on. * * @return string */ public function broadcastAs() { return 'wechat.login'; }}
其中你需要注意 broadcastOn 方法應返回一個數組,它表示所需廣播的頻道,而 broadcastAs 返回的是一個字串,它表示廣播所觸發的事件,Laravel 預設的是返回事件類別的全類名,這裡是 App\Events\WechatLoginedEvent.
最重要的是你需要手動的讓該類實現 ShouldBroadcast 契約。Laravel 在建置事件時,已經自動添加了該命名空間,該契約只約束 broadcastOn 方法。
事件完成接下來就是觸發事件了,簡單的一行代碼就可以:
event(new WechatLoginedEvent($token, $channel));
這個操作會自動的觸發事件的執行並將資訊廣播出去。該廣播操作底層藉助了 redis 的訂閱和發布機制。
RedisBroadcaster 會將事件中的允許公開訪問的資料通過給定的頻道發布出去。如果你想對公開的資料擁有更多的控制,你可以在事件中添加 broadcastWith 方法,它應該返回一個數組:
/** * Get the data to broadcast. * * @return array */ public function broadcastWith() { return ['user' => $this->user->id]; }
Node.js 和 Socket.io
對於發布出去的資訊,我們需要一個服務來對接,讓其能對 redis 的發布能夠進行訂閱,並且能把資訊以 WebSocket 通訊協定轉寄出去,這裡我們可以借用 Node.js 和 socket.io 來非常方便的構建這個服務:
// server.jsvar app = require('http').createServer(handler);var io = require('socket.io')(app);var Redis = require('ioredis');var redis = new Redis();app.listen(6001, function () { console.log('Server is running!') ;});function handler(req, res) { res.writeHead(200); res.end('');}io.on('connection', function (socket) { socket.on('message', function (message) { console.log(message) }) socket.on('disconnect', function () { console.log('user disconnect') })});redis.psubscribe('*', function (err, count) {});redis.on('pmessage', function (subscrbed, channel, message) { message = JSON.parse(message); io.emit(channel + ':' + message.event, message.data);});
這裡我們使用 Node.js 引入 socket.io 服務端並監聽 6001 連接埠,借用 redis 的 psubscribe 指令使用萬用字元來快速的批量訂閱,接著在訊息觸發時將訊息通過 WebSocket 轉寄出去。
Socket.io 用戶端
在 web 前端,我們需要引入 Socket.io 用戶端開啟與服務端 6001 連接埠的通訊,並訂閱頻道事件:
// client.jslet io = require('socket.io-client')var socket = io(':6001') socket.on($channel + ':wechat.login', (data) => { socket.close() // save user token and redirect to dashboard})
至此整個通訊閉環結束,開發流程看起來就是這樣的:
總結