# 云雀-消息服务系统-socket主服务 **Repository Path**: hcy00_admin/yunque-socket ## Basic Information - **Project Name**: 云雀-消息服务系统-socket主服务 - **Description**: go语言websocket亿级通讯框架分布式高并发kafka推送或者redis 推送。分布式部署socket服务器。 本地i59300.单机测试收发消息5w/s - **Primary Language**: Go - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-10-25 - **Last Updated**: 2023-10-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # socket消息服务 作者:yichen email: 2782268022@qq.com ### 前言 >都说GO语言并发能力很强,最近抽出时间,边学边实验,写了这个实时通讯socket框架,目标实现【每秒完成千万级】收发消息能力。哪里设计的不对,还忘遇到高手给与指点。 ### 设计思路 采用多个服务器集群组 >客户链接 服务器集群组A 以下简称 A > >消息接收服务 服务器集群组B > >消息推送 服务器群组C > > 每个集群组都有自己的负载均衡 > >A 每台服务器绑定用户50万人,大概要20台可以支持1000万人 > >B 每台服务器处理 5000个消息接收,约2000台服务器,可以完成秒1000w。 > >C 消息订阅服务器,每台每秒处理1万次发送业务,每次发送1000条数据,约1台服务器,1秒可以完成1000万条数据发布。 > ### 流程介绍 用户发启请求到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 yunque.exe main.go #简写go build ``` 在window系统下编译成liunx可执行文件 ``` #在项目目录下cmd执行命令 set GOOS=linux set GOARCH=amd64 go build -o yunque main.go # 简写 ``` 切换回编译.exe文件 ```markdown SET GOOS=windows ``` # 目录结构 ```markdown ├——api 接口目录 │ │─http http接口目录 │ │ └─controller │ │ │─admin HTTP推送接口 │ │ │─index 模拟注册登录接口 │ │ └─message 推送消息相关 │ │ │ │─subscribe 消息订阅推消息接口 │ │ └─admin 推送消息相关 │ │ │─kafka kafka推消息接口 │ │ └─redis redis推消息接口 │ │ │——config 配置目录 │ └──config.yaml 配置文件 │——connection 连接目录 │ │──pubKafka.go kefka客户端链接配置 │ │──pubRedis.go redis客户端链接配置 │ │──ws.go websocket链接配置 │ └──... │——global 全局定义 │——model 模型 │ │──ProtoModel proto模型类目录 │ │──redis.go redis客户端链接配置 │ │──ws.go websocket链接配置 │ └──... │——router 路由配置 │——service 业务服务实现 │——test 相关调试文件 │——utils 其他工具 │——main.go 入口文件 ``` # 主要功能 ### 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 发消息 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; } ``` ### 消息功能枚举类 ```markdown enum SendTypeProto { /** * 服务端端发送的消息体 用户接收的通用消息 */ MESSAGE = 2; /** * 客户端发送的请求体 功能类消息 */ SENT = 3; /** * 服务端端发送的响应体 功能类消息回复 */ REPLY = 4; } ``` proto包生成命令 ``` protoc --go_out=plugins=grpc:. .\MessageProto.proto ```