• CONNMIX 开发 WebSocket 视频弹幕


    CONNMIX 开发 WebSocket 视频弹幕

    使用WebSocket制作一个单机版弹幕系统非常简单,但是当单机性能达到瓶颈,需要扩展为集群部署时就会面临很多分布式问题,使用CONNMIX则无需担心这些问题,很少的代码即可完成一个高性能分布式WebSocket集群。

    要求

    设计思路

    • 客户端在ws连接成功后,订阅一个视频ID的通道 video:
    • 在发送弹幕的接口中,调用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.yaml 配置文件的 options 选项,修改websocket的url路径

    options:
      - name: path
        value: /barrage-videos
    
    • 1
    • 2
    • 3

    CONNMIX 编码

    修改 entry.websocket.luaon_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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    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!\"}}"
    }'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试

    使用 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!"}}
  • 相关阅读:
    前缀表达式和后缀表达式 - C++代码
    计网 | 一文解析TCP协议所有知识点
    天星金融消保课堂开讲,金融健康意识再提升
    图观引擎V3.3.4 功能更强、操作更便捷!最新升级一睹为快
    GoldenEye
    Swift -- 数组高阶函数
    使用 Service 把前端连接到后端
    R语言结构方程模型(SEM)在生态学领域中的实践应用
    软考 -- 计算机学习(2)
    MySQL数据库UDF提权学习
  • 原文地址:https://blog.csdn.net/onanying/article/details/126608655