今天尝试用 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(状态信息不足)
关闭历史消息的选项就没有问题