CONNMIX 开发 WebSocket 视频弹幕
应用WebSocket制作一个单机版弹幕零碎非常简单,然而当单机性能达到瓶颈,须要扩大为集群部署时就会面临很多分布式问题,应用CONNMIX则无需放心这些问题,很少的代码即可实现一个高性能分布式WebSocket集群。
要求
- connmix >= v1.0.4
设计思路
- 客户端在ws连贯胜利后,订阅一个视频ID的通道
video:<videoid>
- 在发送弹幕的接口中,调用connmix任意节点的
/v1/mesh/publish
接口往对应video_id
发送实时弹幕,所有订阅该通道的ws客户端都将会收到音讯。 - 以上都是增量推送设计,全量通常都是在页面加载时通过一个全量api接口获取。
交互协定设计
- 当用户发送 100001@video 咱们在 lua 代码中就执行订阅 video:100001 通道。
- 前端切换视频时,可先发送勾销弹幕音讯,而后发送新的订阅弹幕音讯。
性能 | json格局 |
---|---|
订阅弹幕 | {"op":"subscribe","channel":"100001@video"} |
勾销弹幕 | {"op":"unsubscribe","channel":"100001@video"} |
弹幕事件 | {"event":"@video","data":{"uid":1001,"video_id":100001,"msg":"Hello,World!"}} |
胜利 | {"result":true} |
谬误 | {"code":1,"msg":"Error"} |
装置引擎
CONNMIX
https://connmix.com/docs/1.0/#/zh-cn/install-engine
批改配置
在 connmix.yaml
配置文件的 options
选项,批改websocket的url门路
options: - name: path value: /barrage-videos
CONNMIX 编码
批改 entry.websocket.lua
的 on_message
办法如下:
- 当承受到subscribe、unsubscribe音讯时,执行订阅/勾销订阅对应的通道
function on_message(msg) --print(msg) if msg["type"] ~= "text" then conn:close() return end local conn = mix.websocket() local data, err = mix.json_decode(msg["data"]) if err then mix_log(mix_DEBUG, "json_decode error: " .. err) conn:close() return end local op = data["op"] local channel_raw = data["channel"] local channel_table = mix.str_split(channel_raw, "@") if table.getn(channel_table) ~= 2 then mix_log(mix_DEBUG, "invalid channel: " .. channel_raw) conn:close() return end local video_id = channel_table[1] --Lua的table索引默认从1开始 local channel_type = channel_table[2] if op == "subscribe" and channel_type == "video" then local err = conn:subscribe("video:" .. video_id) if err then mix_log(mix_DEBUG, "subscribe error: " .. err) conn:close() return end end if op == "unsubscribe" and channel_type == "video" then local err = conn:unsubscribe("video:" .. video_id) if err then mix_log(mix_DEBUG, "unsubscribe error: " .. err) conn:close() return end end conn:send('{"result":true}')end
API 编码
接下来在现有零碎的框架中实现被动弹幕推送
- 能够在 spring、laravel 框架中写一个发送弹幕接口
- 该接口中验证完用户身份后,执行以下http申请实现推送
- 如果发送申请十分频繁,能够改用 websocket-api推送 晋升性能
curl --request POST 'http://127.0.0.1:6789/v1/mesh/publish' \--header 'Content-Type: application/json' \--data-raw '{ "c": "video:100001", "d": "{\"event\":\"@video\",\"data\":{\"uid\":1001,\"video_id\":100001,\"msg\":\"Hello,World!\"}}"}'
测试
应用 wstool 进行测试
- 连贯
ws://127.0.0.1:6790/barrage-videos
- 发送
{"op":"subscribe","channel":"100001@video"}
- 接管到
{"result":true}
- 执行 curl 被动推送
- 接管到
{"event":"@video","data":{"uid":1001,"video_id":100001,"msg":"Hello,World!"}}