作者: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群组收到订阅消息进行过滤,发送到指定用户。
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
已经编译好的可执行文件在bin目录下
在window系统下编译成liunx可执行文件
#在项目目录下cmd执行命令
set GOOS=linux
set GOARCH=amd64
go build -o yunque main.go
# 简写
切换回编译.exe文件
SET GOOS=windows
./build.bat win
./build.bat linux
├——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 入口文件
用于推送广播,公众号文章,系统通知等
用于发送聊天信息
message MessageProto {
int64 id = 1;
#执行方法参数可选
string action = 2;
#消息内容
map<string,string> content = 3;
#发信人UID
string sender = 4;
# 收信人UID
string receiver = 5;
# 其他拓展
map<string,string> extra = 6;
# 标题可选
string title = 7;
# 发送时间 可选
int64 sendTime = 8;
# 图片地址 可选
string image=9;
}
message MessagesPubProto {
#收信人 uid 支持多个逗号隔开,例如1,2,3,4 可选
string Uid = 1;
# 服务器ID 支持多个 逗号隔开,可选
string Sid = 2;
# 用户多设备在线的某个设备id 可选
int64 Cid = 3;
#消息数组 支持多发 例如[MessageProto,MessageProto] 必选
repeated MessageProto msg = 4;
}
模型参考 sendbody
message SendBodyProto {
string key = 1;
int64 timestamp =2;
map<string,string> 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
}
此时客户端就可以收到消息
订阅频道 chat
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()
给用户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
enum SendActProto {
/**
* 单消息推送给所有人
*/
SENDALL = 0;
/**
* 单消息推送给用户集合
*/
SENDUIDS = 1;
/**
* 单消息推送给指定用户UID
*/
SENDUID = 2;
/**
* 单消息推送给指定用户UID下的某个设备ID
*/
SENDUIDDID = 3;
/**
* 单消息推送给指定链接设备ID
*/
SENDDID = 4;
/**
* 批量消息
*/
SENDLIST = 5;
/**
* 批量消息
*/
SENDOTHER = 6;
* 推消息给指定房间 推给房间时 uid升级为房间号
*/
SENDROOM = 7;
}
enum SendTypeProto {
/**
* 服务端端发送的消息体 用户接收的通用消息
*/
MESSAGE = 2;
/**
* 客户端发送的请求体 功能类消息
*/
SENT = 3;
/**
* 服务端端发送的响应体 功能类消息回复
*/
REPLY = 4;
}
proto包生成命令
protoc --go_out=plugins=grpc:. .\MessageProto.proto
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。