# 云雀通讯 云雀消息服务系统-websocket主服务 **Repository Path**: wokaixin/yunque-socket ## Basic Information - **Project Name**: 云雀通讯 云雀消息服务系统-websocket主服务 - **Description**: go语言websocket亿级通讯框架分布式高并发kafka推送或者redis 推送。分布式部署socket服务器。 本地i59300.单机测试收发消息5w/s - **Primary Language**: Go - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 2 - **Created**: 2023-08-20 - **Last Updated**: 2024-12-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: Go语言, WebSocket, Kafka, TCP, Redis ## README # 云雀通讯 云雀消息 云雀群聊 websocket消息服务端开源 作者:yichen email: 2782268022@qq.com ### 前言 # 云雀-消息服务系统 高并发分布式websocket推送消息服务 作者 yichen email 2782268022@qq.com ### 前言 >感受GO语言并发能力,边学边实验,写了这个实时通讯socket框架,目标实现千万级收发消息能力。 ### 主要用途 >消息推送,私聊,群聊 ### 特点 >云雀消息服务系统可以独立运行,用户端通过token建立连接,任何语言(java,php,python等)的业务服务端均可通过api接口给用户推送消息。 ### 设计思路 采用多个服务器集群组 >客户建立链接绑定 服务器集群组A 以下简称 A > >消息接收服务 服务器集群组B > 每个集群组都有自己的负载均衡 > >A 服务器与用户建立绑定 > >B 服务器消息接收转发消息到用户所在服务器。 > ### 代码以及示例地址 ### 云雀主服 服务端地址 云雀主服务 websocket 链接服务端地址: ``` https://gitee.com/wokaixin/yunque-socket.git ``` ### 文档地址 ``` https://gitee.com/wokaixin/yunque-socket/wikis/%E5%89%8D%E8%A8%80 ``` # 多语言推送调用实现 ### 云雀推消息业务实现 php版 ``` https://gitee.com/wokaixin/yunque-message-client-php ``` ### 云雀推消息业务实现 java版 ``` https://gitee.com/wokaixin/yunque-message-client-java ``` ### 云雀推消息业务实现 go版 ``` https://gitee.com/wokaixin/yunque-message-client-go ``` ### 云雀客户端实现测试例 移动端示例 uniapp vue3 兼容vue2 ``` git clone https://gitee.com/wokaixin/yunque-uniapp-vue3.git ``` ### 流程介绍 用户发启请求到A群组,A负载均衡,根据用户ip重定向到A群组内的服务器单元,绑定成功,返回用户所在服务器节点信息 用户发消息 到B群组,负载均衡到任意服务器处理消息逻辑,然后推送到C群组,由C群组广播给所有A节点服务器。 推送消息到用户 A群组收到订阅消息进行过滤,发送到指定用户。 ![img.png](https://foruda.gitee.com/images/1694998666103755139/0ce9ae06_1553456.png) ### 文档地址 https://gitee.com/wokaixin/yunque-socket/wikis/pages ### 代码仓库地址 https://gitee.com/wokaixin/yunque-socket ### # 环境部署 Golang go1.21.0 集群可选redis/kafka,单例内网调用http推送接口 redis * kafka * ### 编译 在window系统下编译成exe可执行文件 ``` go build -o ./bin/yunque.exe ./src/main.go #简写go build ``` ### 已经编译好的可执行文件 ```azure 已经编译好的可执行文件在bin目录下 ``` 在window系统下编译成liunx可执行文件 ``` #在项目目录下cmd执行命令 set GOOS=linux set GOARCH=amd64 go build -o yunque main.go # 简写 ``` 切换回编译.exe文件 ```markdown SET GOOS=windows ``` ## win下可使用build.bat 编译 ```azure ./build.bat win ./build.bat linux ``` # 目录结构 ```markdown │——bin 已编译好的可执行文件 │ │──config.yaml 基础配置文件 │ │──config-dev.yaml 环境配置文件(相同节点 会覆盖基础配置文件) │ │──yunque linux 环境下可运行程序 │ │──yunque.exe window 环境下可运行程序 │ └── │——db 数据结构调试参考 sql │——src 项目目录 ``` # src目录结构 ```markdown ├——api 接口目录 │ │─http http接口目录 │ │ └─controller │ │ │─admin HTTP推送接口 │ │ │─index 模拟注册登录接口 │ │ └─message 推送消息相关 │ │ │ │─subscribe 消息订阅推消息接口 │ │ └─admin 推送消息相关 │ │ │─kafka kafka推消息接口 │ │ └─redis redis推消息接口 │ │ │——config 配置目录 │ │──config.go 加载配置文件逻辑 │ └──env.go │——connection 各种连接类 │ │──pubKafka.go kefka客户端链接配置 │ │──pubRedis.go redis客户端链接配置 │ │──ws.go websocket链接配置 │ └──... │——global 全局 │——model 各种数据模型 │ │──protoModel 各种 proto数据模型 │ │ └─proto 各种proto 源文件 │ └──... │——router 路由配置 │——service 业务服务实现 │——task 任务目录 │ │──Purification 心跳相关 │——test 相关调试文件 │——utils 各种工具类 │——main.go 入口文件 │——build.bat 编译发布 │——fengelog 分割日志 计划任务脚本 │——start.sh linux环境 启动脚本 │——stop.sh linux 环境关闭脚本 ``` # 主要功能 ### 1 推送消息 用于推送广播,公众号文章,系统通知等 ### 2 聊天通讯 用于发送聊天信息 ### 消息模版如下 模型参考messageProto 结构 ```azure message MessageProto { int64 id = 1; #执行方法参数可选 string action = 2; #消息内容 map content = 3; #发信人UID string sender = 4; # 收信人UID string receiver = 5; # 其他拓展 map extra = 6; # 标题可选 string title = 7; # 发送时间 可选 int64 sendTime = 8; # 图片地址 可选 string image=9; } ``` ### 订阅推送消息模版(redis,kafka)通用 ```markdown message MessagesPubProto { #收信人 uid 支持多个逗号隔开,例如1,2,3,4 可选 string Uid = 1; # 服务器ID 支持多个 逗号隔开,可选 string Sid = 2; # 用户多设备在线的某个设备id 可选 int64 Cid = 3; #消息数组 支持多发 例如[MessageProto,MessageProto] 必选 repeated MessageProto msg = 4; } ``` ### 3 功能性推送 模型参考 sendbody ```azure message SendBodyProto { string key = 1; int64 timestamp =2; map data =3; } ``` 什么是功能性服务?如下: >1、请求登录授权; > >2、请求视频通话,后台收到请求后,推送邀请信息给受邀方,受邀方确定后,通知服务器,并建立新的链接地址推送给双方,双方开始通讯。 ### 订阅方式发送消息 注意配置 --topic chat 发送和接收必须统一 >redis ,kafka 都可以用来推消息 > >redis 推消息 和kafka 消息体类型统一 > >下面演示的是kafka推消息方法 > 发送给一位用户消息 ``` sub1 := service.Sub{Sid: "xxfd", Uid: "1084", Cid: idx} sub1.Act = ProtoModel.SendActProto_SENDUID sub1.Type = ProtoModel.DataTypeProto_MESSAGE sub1.Message(packetMessage()) err := sub1.SendKafka() if err != nil { return } ``` 发送给所有在线用户消息 ``` sub1 := service.Sub{Sid: "xxfd", Uid: "1084", Cid: idx} sub1.Act = ProtoModel.SendActProto_SENDALL sub1.Type = ProtoModel.DataTypeProto_MESSAGE sub1.Message(packetMessage()) err := sub1.SendKafka() if err != nil { return } ``` 此时客户端就可以收到消息 ### redis方法如下: 订阅频道 chat ```markdown sub1 := service.Sub{Sid: "xxfd", Uid: "1084", Cid: idx} sub1.Act = ProtoModel.SendActProto_SENDALL sub1.Type = ProtoModel.DataTypeProto_MESSAGE sub1.Message(packetMessage()) err := sub1.SendRedisPublish() ``` ### http 推消息接口 receiver=接收人uid sender=发送人uid 给用户uid=1074的用户发消息 api 127.0.0.1:8080/send post raw json ``` { "title": "标题", "receiver": "1074", "sender": "1078", "action": "chat", "id": 748, "content":{"text":"好吗","image":"","url":""}, "extra": {"avatar":"https://yrk.01film.cn/uploads/postImages/20220702/69177fa59244c4efad7b34bc8f551cf8.jpg","nickname":"小毛豆"}, "image":"https://yrk.01film.cn/uploads/postImages/20220702/69177fa59244c4efad7b34bc8f551cf8.jpg" } ``` ### 给所有人发消息 api 127.0.0.1:8080/send/all ``` { "title": "标题", "receiver": "1074", "sender": "1078", "action": "chat", "id": 748, "content":{"text":"好吗","image":"","url":""}, "extra": {"avatar":"https://yrk.01film.cn/uploads/postImages/20220702/69177fa59244c4efad7b34bc8f551cf8.jpg","nickname":"小毛豆"}, "image":"https://yrk.01film.cn/uploads/postImages/20220702/69177fa59244c4efad7b34bc8f551cf8.jpg" } ``` ### 推送多条消息 127.0.0.1:8080/send/sendList ``` 根据消息体的uid 进行遍历推送 [{消息体}] ``` ### 向多个用户发送一条消息 127.0.0.1:8080/send/toUids ``` 根据消息体的uid 进行遍历推送 {"message":{消息体},"uids":["uid1","uid2",...]} ``` ### 查看在线人信息 127.0.0.1:8080/getOnlineUser 测试 登录查看自己信息 这个不需要。用户所有功能应该放到web逻辑服务器,本服务器之作通讯 维护链接状态,不作业务处理相关功能。 127.0.0.1:8080/login/getUserinfo ### 发送消息 支持的几种方式参考如下枚举类 ```markdown enum SendActProto { /** * 单消息推送给所有人 */ SENDALL = 0; /** * 单消息推送给用户集合 */ SENDUIDS = 1; /** * 单消息推送给指定用户UID */ SENDUID = 2; /** * 单消息推送给指定用户UID下的某个设备ID */ SENDUIDDID = 3; /** * 单消息推送给指定链接设备ID */ SENDDID = 4; /** * 批量消息 */ SENDLIST = 5; /** * 批量消息 */ SENDOTHER = 6; * 推消息给指定房间 推给房间时 uid升级为房间号 */ SENDROOM = 7; } ``` ### 消息功能枚举类 ```markdown enum SendTypeProto { /** * 服务端端发送的消息体 用户接收的通用消息 */ MESSAGE = 2; /** * 客户端发送的请求体 功能类消息 */ SENT = 3; /** * 服务端端发送的响应体 功能类消息回复 */ REPLY = 4; } ``` proto包生成命令 ``` protoc --go_out=plugins=grpc:. .\MessageProto.proto ```