今天嘗試用 centrifugo 來作一個在聊天室,之前用workerman作過,相對來講 workerman的配置就顯得複雜多了,須要本身搭建PHP環境,html
而 centrifugo 就清爽多了,官網下載二進制單文件直接運行,得益於go語言,centrifugo 的性能應該是大於workerman的,git
但也得提醒一下,從github上看centrifugo是 2018年末纔開始的,目前還在快速更新中,穩定性有必定風險。github
測試系統: Debian 9web
下載二進制文件:json
https://github.com/centrifugal/centrifugo/releases後端
添加執行權限api
chmod a+x centrifugo
生成配置文件 config.json文件服務器
./centrifugo genconfig
內容大體這樣的websocket
{ "secret": "16bfd798-4f9f-4362-98e8-d88cb4997db2", "admin_password": "18d34296-f9c2-4c65-a04a-118cbe020481", "admin_secret": "e6adffc9-e54f-41ef-a487-3b172ea962db", "api_key": "3fe2e20a-af48-48d1-9aab-51ae88d92c5e" }
啓動 centrifugosocket
./centrifugo -c config.json
前臺採用 centrifugo的js客戶端,下載地址: https://github.com/centrifugal/centrifuge-js
經過文檔得知,要連接到centrifugo服務器,須要一個jwt的token,打開 https://jwt.io/,準本生成一個測試用的jwtToken
PAYLOAD框框裏面去掉 name和iat,只保留sub一項,否則連不上,我猜想是centrifugo 不支持
(文檔裏面確實寫了支持exp,info的,實測不行)
VERIFY SIGNATURE 框框裏面補充config.json文件裏面的secret字段值
這個時候 左邊 Encoded框框 裏面的一串密文就是咱們要用到的
嫌麻煩能夠直接使用我生成好的兩個(使用的前提是你的config.js secret字段要跟個人同樣):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIn0.GvmVuP_7yADlqHk6fB7Tcq2V5EGY98PQw3EkX3DbBmQ
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyIn0.ZOIIW5dReDRHEWkBakTJn0-cn0JFL6MIcrkOtElevRk
爲了接下來的測試方便,我先配置一下config文件的經常使用選項:
{ "admin": true, # 開啓管理員後臺 "posrt": 8000, # 端口 "debug": true, # 開啓debug模式 "presence": true, # 開啓系統狀態信息 "history_size": 100, # 歷史消息保存條數,0不保存 "history_lifetime": 600, # 歷史消息保存秒數 0 保存 "secret": "16bfd798-4f9f-4362-98e8-d88cb4997db2", "admin_password": "18d34296-f9c2-4c65-a04a-118cbe020481", "admin_secret": "e6adffc9-e54f-41ef-a487-3b172ea962db", "api_key": "3fe2e20a-af48-48d1-9aab-51ae88d92c5e", "publish": true # 容許客戶端直接發佈消息到centrifugo通道中,不通過咱們本身的服務器,方便沒有後端的狀況下測試 }
測試的html文件是這樣的:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>socktest</title> <script src="./centrifuge.min.js"></script> </head> <body> <button onclick="init()">鏈接</button> <button onclick="closeit()">關閉鏈接</button> <button onclick="publish()">發送消息</button> <button onclick="subscribe()">訂閱頻道</button> <button onclick="unsubscribe()">取消訂閱</button> <button onclick="history()">拉取歷史消息</button> </body> </html> <script> // js 代碼 </script>
js代碼:
function init() { // 初始化 centrifugo 客戶端 window.centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket'); // 設置 token centrifuge.setToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyIn0.ZOIIW5dReDRHEWkBakTJn0-cn0JFL6MIcrkOtElevRk"); // 監聽鏈接事件 centrifuge.on('connect',function(context) { console.log(context) }) // 監聽斷開鏈接事件 centrifuge.on('disconnect', function(context) { console.log(context) }); // 啓動鏈接 centrifuge.connect(); } // 發佈消息到通道 function publish () { centrifuge.publish("news", {"input": "hello-publish"}).then(function(res) { console.log(res); }, function(err) { console.log('publish error', err); }); } // 訂閱頻道 function subscribe() { // 監聽頻道內的消息 var callbacks = { "publish": function(message) { console.log(message); }, "join": function(message) { console.log(message); }, "leave": function(message) { console.log(message); }, "subscribe": function(context) { console.log(context); }, "error": function(errContext) { console.log(err); }, "unsubscribe": function(context) { console.log(context); } } window.subscription = centrifuge.subscribe("news", callbacks); } // 取消訂閱 function unsubscribe() { subscription.unsubscribe(); subscription.removeAllListeners(); } // 查看歷史消息 function history() { subscription.history().then(function(message) { console.log(message); }, function(err) { console.log(err); }); } // 關閉鏈接 function closeit() { centrifuge.disconnect(); }
測試流程,開兩個窗口,兩個窗口的token不同,打開調試工具的日誌界面,
第一個窗口先點擊鏈接,而後訂閱頻道,第二個窗口一樣,
這個時候在第一個窗口點擊發送消息,看另一個窗口有沒有接收到消息
centrifugo 提供了一個簡易的後臺面板:http://www.testserver.com:8000
測試過程當中遇到一個問題:若是開啓歷史消息,開兩個客戶端測試時發現有個客戶端沒法發送消息,提示insufficient state(狀態信息不足)
關閉歷史消息的選項就沒有問題