IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> CONNMIX 开发 WebSocket 用户消息中心 -> 正文阅读

[网络协议]CONNMIX 开发 WebSocket 用户消息中心

WebSocket 用户消息中心

使用websocket做消息中心,通常做法是采用kafka、redis等中间件搭配实现,使用CONNMIX则无需使用中间件,同时分布式集群能力也无需担忧用户量大增后带来的性能问题。

要求

设计思路

  • 客户端在ws连接成功后发送消息执行登录,使用lua调用业务api接口解析登录token数据中的uid,然后将uid保存到连接的context中。
  • 登录成功后发送消息订阅一个用户ID的通道 user:<uid>,该uid从context中取出。
  • 在发送用户消息的接口中,调用connmix任意节点的 /v1/mesh/publish 接口往对应 uid 发送实时消息,所有订阅该通道的ws客户端都将会收到消息。
  • 以上都是增量推送设计,全量通常都是在页面加载时通过一个全量api接口获取。

交互协议设计

  • 必须登录后才能执行订阅、取消订阅
  • 当用户发送 @user 我们在 lua 代码中就执行订阅 user:<uid> 通道。
功能json格式
登录{“op”:“auth”,“token”:“***”}
订阅用户消息{“op”:“subscribe”,“channel”:“@user”}
取消用户消息{“op”:“unsubscribe”,“channel”:“@user”}
用户消息事件{“event”:“@user”,“data”:{“uid”:1001,“msg”:“Hello,World!”}}
成功{“result”:true}
错误{“code”:1,“msg”:“Error”}

安装引擎

修改配置

connmix.yaml 配置文件的 options 选项,修改websocket的url路径

options:
  - name: path
    value: /message-center

CONNMIX 编码

修改 entry.websocket.luaon_message 方法如下:

  • 当消息为auth类型时,调用 auth_url 接口通过token获取到uid,并保存到context中
  • 当消息为subscribe、unsubscribe时,从context取出uid,执行订阅/取消订阅对应的通道
function on_message(msg)
    --print(msg)
    if msg["type"] ~= "text" then
        conn:close()
        return
    end

    local auth_url = "http://127.0.0.1:8000/websocket_auth" --填写解析token的api接口地址
    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 channel_type = channel_table[2]

    if op == "auth" then
        local token = data["token"]
        local resp, err = mix.http.request("POST", auth_url, {
            body = '{"token:"' .. token .. '"}'
        })
        if err then
            mix_log(mix_DEBUG, "http.request error: " .. err)
            conn:close()
            return
        end
        if resp.status_code ~= 200 then
            mix_log(mix_DEBUG, "http.request status_code: " .. resp["status_code"])
            conn:close()
            return
        end
        local body_table, err = mix.json_decode(resp["body"])
        if err then
            mix_log(mix_DEBUG, "json_decode error: " .. err)
            conn:close()
            return
        end
        conn:set_context_value("uid", body_table["uid"])
        return
    end

    local uid = conn:context_value("uid")

    if op == "subscribe" and channel_type == "user" then
        if uid == nil then
            conn:send('{"code":1,"msg":"Not Auth"}')
            return
        end
        local err = conn:subscribe("user:" .. uid)
        if err then
            mix_log(mix_DEBUG, "subscribe error: " .. err)
            conn:close()
            return
        end
    end

    if op == "unsubscribe" and channel_type == "user" then
        if uid == nil then
            conn:send('{"code":1,"msg":"Not Auth"}')
            return
        end
        local err = conn:unsubscribe("user:" .. uid)
        if err then
            mix_log(mix_DEBUG, "unsubscribe error: " .. err)
            conn:close()
            return
        end
    end

    conn:send('{"result":true}')
end

API 编码

在现有系统的框架中编写一个登录信息验证接口 /websocket_auth,用于ws登录获取用户uid

  • 接口入参:token
{"token":"***"}
  • 接口出参:uid
{"uid":1001}

在现有系统的框架中实现主动消息推送

  • 可以在 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": "user:1001",
    "d": "{\"event\":\"@user\",\"data\":{\"uid\":1001,\"msg\":\"Hello,World!\"}}"
}'

测试

使用 wstool 进行测试

  • 连接 ws://127.0.0.1:6790/message-center
  • 发送 {"op":"auth","token":"***"}
  • 接收到 {"result":true}
  • 发送 {"op":"subscribe","channel":"@user"}
  • 接收到 {"result":true}
  • 执行 curl 主动推送
  • 接收到 {"event":"@user","data":{"uid":1001,"msg":"Hello,World!"}}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:52:32  更:2022-09-13 11:53:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 3:31:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码