廣播系統(tǒng)廣播系統(tǒng)指的是什么呢?在這里我們說(shuō)的廣播系統(tǒng)其實(shí)就是配合 WebSocket 實(shí)現(xiàn)的即時(shí)更新接口。什么意思呢?比如說(shuō)在你的購(gòu)物 App 上,如果訂單狀態(tài)發(fā)生了變化,比如賣(mài)家發(fā)貨了,那么馬上就會(huì)收到一條通知信息。當(dāng)然,App 上使用的不是 WebSocket ,而是不同平臺(tái)的推送機(jī)制,但它也是一種廣播通知機(jī)制。如果你對(duì) Redis 比較了解的話,也可以這么理解:它和 Redis 中的 Pub/Sub 也非常像,前端 SUBSCRIBE 監(jiān)聽(tīng)頻道,后端向頻道里 PUBLISH 數(shù)據(jù),就是這么個(gè)過(guò)程。 在 Web 頁(yè)面開(kāi)發(fā)的領(lǐng)域,現(xiàn)在 WebSocket 可以說(shuō)已經(jīng)相當(dāng)于是事實(shí)標(biāo)準(zhǔn)了。之前我們?nèi)绻诤笈_(tái)做上一個(gè)廣播通知功能的話,都是使用 Ajax 去輪詢請(qǐng)求,但現(xiàn)在這么做的人已經(jīng)不多了,畢竟 WebSocket 是更加可靠和高效的選擇。至于說(shuō)為什么 WebSocket 更好,這不在我們討論的范圍內(nèi),大家可以自行查閱相關(guān)的資料。 今天的內(nèi)容就是簡(jiǎn)單的搭起廣播系統(tǒng)的環(huán)境即可,源碼不多說(shuō)了,因?yàn)閺V播系統(tǒng)實(shí)際上是使用了我們之前學(xué)習(xí)過(guò)的隊(duì)列和事件來(lái)實(shí)現(xiàn)的。而且它也牽涉到一些前端相關(guān)的內(nèi)容,這一塊對(duì)于我來(lái)說(shuō)并沒(méi)有太深度的研究,所以大家看看就好哈。(說(shuō)實(shí)話:實(shí)力不允許啊~~~~) 服務(wù)端配置默認(rèn)情況下,Laravel 框架中的廣播功能是關(guān)閉的。現(xiàn)在我們需要先去打開(kāi)廣播服務(wù)提供者,它就在 config/app.php 中。 將 providers 中的這個(gè)服務(wù)提供者的注釋打開(kāi),我們就可以使用廣播相關(guān)的組件了。然后我們還需要進(jìn)行一些配置。廣播相關(guān)的配置在 config/broadcasting.php 中。 在這個(gè)配置文件中,我們可以看到有許多不同的廣播連接驅(qū)動(dòng)。pusher 是官方文檔上推薦的,但是,注意這里有但是了哦。這玩意需要去它的官網(wǎng)上注冊(cè)之后拿到 key 了才能使用。而在這們?nèi)粘5氖褂弥?,其?shí)更多的會(huì)使用 redis+socket.io 這種搭配。不過(guò)問(wèn)題就來(lái)了,在 Laravel8 相關(guān)的文檔中,關(guān)于 redis 和 socket.io 的內(nèi)容基本上沒(méi)了。所以我們需要去參考 Laravel6 以及更低版本的文檔。這個(gè)大家在查閱的需要注意哦。 那么接下來(lái)我們就使用 Redis 來(lái)配置,因此,我們需要在 .env 中將 BROADCAST_DRIVER 設(shè)置為 Redis 。 通過(guò)以上的配置,廣播相關(guān)的配置就完成了。接下來(lái)我們需要定義一個(gè)事件,并使用隊(duì)列去消費(fèi)它,前面沒(méi)說(shuō)錯(cuò)吧?廣播在服務(wù)端就是通過(guò)事件和隊(duì)列來(lái)處理的。 我們新定義的這個(gè)事件,需要實(shí)現(xiàn) ShouldBroadcast 接口,然后實(shí)現(xiàn)一個(gè) broadcastOn() 方法。在這個(gè)方法中,返回一個(gè) Channel 實(shí)例,它就是我們要指定廣播的頻道。在這里我們直接給了一個(gè)頻道名稱(chēng)為 messages 。另外,在這個(gè)事件類(lèi)中,我們定義了一個(gè)公共屬性用于接收構(gòu)造函數(shù)傳來(lái)的參數(shù),在廣播事件中,公共屬性是可以廣播到前端去的。 接下來(lái),我們定義一個(gè)路由用于觸發(fā)廣播事件。 在這個(gè)路由中,直接使用 broadcast() 工具函數(shù),傳遞參數(shù)為實(shí)例化的 Messages 事件對(duì)象,給它的構(gòu)造函數(shù)傳遞了一條數(shù)據(jù)。 接下來(lái),我們?cè)L問(wèn)這個(gè)路由,然后到 redis 的隊(duì)列中就可以看到一條數(shù)據(jù)。
安裝完成后進(jìn)行初始化。 在初始化時(shí)選項(xiàng)的內(nèi)容都是很簡(jiǎn)單的英文啦,相信各位大佬的英文水平是沒(méi)問(wèn)題的。然后我們找到在當(dāng)前目錄下生成的 laravel-echo-server.json 文件,修改 devMode 為 ture 。最后運(yùn)行起來(lái)這個(gè)服務(wù)。 這時(shí),我們運(yùn)行起隊(duì)列監(jiān)控,然后再請(qǐng)求一下廣播路由,會(huì)看到 laravel-echo-server 服務(wù)的命令行下面已經(jīng)對(duì)剛剛的事件進(jìn)行了廣播。 至此,服務(wù)端的工作全部完成。 客戶端配置接下來(lái)就是客戶端的配置,也就是我們前端的配置,在進(jìn)行配置前,你需要先安裝相應(yīng)的 npm 庫(kù)。 很明顯,前端對(duì)應(yīng)的是需要一個(gè) socket.io 的客戶端組件和一個(gè) laravel-echo 組件。安裝完成之后,需要去修改一下 resources/assets/js/bootstrap.js 。在這個(gè)文件中,已經(jīng)包含了一套注釋的 Echo 配置,我們需要打開(kāi)注釋并修改成下面這樣。 注意,注意,注意,重要的事情說(shuō)三遍,現(xiàn)在這里是有坑的哦,我們將在后面解決。大家可以先按這樣修改。 修改完成之后,我們需要使用 Laravel 默認(rèn)的 mix 工具來(lái)編譯一下前端代碼,最后需要加載的文件實(shí)際上是 public/js/app.js ,直接使用下面的命令行進(jìn)行編譯即可。 執(zhí)行完編譯之后,我們就可以寫(xiě)一個(gè)前端頁(yè)面來(lái)進(jìn)行測(cè)試了。在這個(gè)頁(yè)面中,直接引用 app.js 文件即可。 Echo 對(duì)象就是我們?cè)谏厦娴?bootstrap.js 中定義的那個(gè) window.Echo 對(duì)象。在具體的頁(yè)面中,我們直接去調(diào)用它的 channel() 方法,給一個(gè)指定的頻道名稱(chēng),然后監(jiān)聽(tīng)這個(gè)頻道中的具體事件,也就是我們?cè)?Laravel 中定義的事件類(lèi)名。在監(jiān)聽(tīng)的回調(diào)函數(shù)中,我們打印返回的結(jié)果。 最后,定義一個(gè)路由來(lái)顯示這個(gè)頁(yè)面。 好了,前端相關(guān)的配置也全部完成了?,F(xiàn)在打開(kāi)這個(gè)頁(yè)面吧。 socket.io 問(wèn)題相信你已經(jīng)打開(kāi)了我們剛剛定義的頁(yè)面,同時(shí)要保證隊(duì)列消費(fèi)和 laravel-echo-server 也正在運(yùn)行,這時(shí)頁(yè)面上會(huì)不停的輪詢一個(gè)類(lèi)似于下面這樣的請(qǐng)求。 在你的請(qǐng)求中參數(shù)可能和我的不一樣,但如果看到這個(gè)請(qǐng)求一直在發(fā),并且 console 里沒(méi)有報(bào)錯(cuò)的話,說(shuō)明你的前端配置是沒(méi)有問(wèn)題的。但是,這時(shí)你可以去試試刷新發(fā)送廣播的頁(yè)面,這邊應(yīng)該還是無(wú)法收到推送過(guò)來(lái)的消息。這是為什么呢? 好吧,這個(gè)坑其實(shí)我也找了半天才了解到大概的原因,那就是我們?cè)谏厦嫱ㄟ^(guò) npm 安裝的 socket.io-client 版本太高了。我這里查看 package.json 的話是 4.4 版本的,而 laravel-echo-server 這邊只支持到 2.x 版本。所以我們需要降低版本,最簡(jiǎn)單的方式是注釋掉 bootstrap.js 中引入 socket.io 的那一行。 然后在前端頁(yè)面上直接引用一個(gè)低版本的 socket.io 。 接下來(lái)重新編譯 mix 。 現(xiàn)在你再打開(kāi)我們的前端測(cè)試頁(yè)面,就可以看到一個(gè) WebSocket 連接已經(jīng)建立了,之前那個(gè) http 連接也不會(huì)一直輪詢了。這種情況,才是正常的情況。 好了,去刷新一下廣播頁(yè)面發(fā)送廣播吧,然后來(lái)到測(cè)試頁(yè)面看看 Console 中是不是有輸出了。
總結(jié)開(kāi)心不開(kāi)心,爽不爽,搞了半天總算把這個(gè)廣播系統(tǒng)調(diào)通了吧。相信你的付出一定會(huì)帶來(lái)收獲。整個(gè)廣播系統(tǒng)非常復(fù)雜,僅在后端就有事件、隊(duì)列的應(yīng)用,而且還開(kāi)了一個(gè) node.js 服務(wù)。而在前端還要注意 socket.io 的版本問(wèn)題。具體的源碼我也就不分析了,畢竟僅對(duì)于 Laravel 框架來(lái)說(shuō),無(wú)非就是事件和隊(duì)列的組合應(yīng)用。而前端的實(shí)力確實(shí)還達(dá)不到分析庫(kù)源碼的級(jí)別,所以這里也就不獻(xiàn)丑了。 如果你的系統(tǒng)中有類(lèi)似的通知需求,完全可以考慮使用這套廣播系統(tǒng)來(lái)實(shí)現(xiàn)了,多少還是比輪詢的功能要強(qiáng)大許多,大家多多嘗試就能體會(huì)到好處。最后我再引用一張某位大佬畫(huà)的廣播系統(tǒng)的關(guān)系圖。
參考文檔: https:///docs/laravel/8.5/broadcasting/10382 https:///docs/laravel/6.x/broadcasting/5159 https://blog.csdn.net/nsrainbow/article/details/80428769 https:///laravel/t/52388 |
|
|
來(lái)自: 硬核項(xiàng)目經(jīng)理 > 《待分類(lèi)》