Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta323 #328

Merged
merged 7 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions botgo/dto/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ type WebsocketAP struct {
SessionStartLimit SessionStartLimit `json:"session_start_limit"`
}

// WebsocketAP wss 单个接入点信息
type WebsocketAPSingle struct {
URL string `json:"url"`
ShardCount uint32 `json:"shards"` //最大值 比如是4个分片就是4
ShardID uint32 `json:"shard_id"` //从0开始的 0 1 2 3 对应上面的
SessionStartLimit SessionStartLimit `json:"session_start_limit"`
}

// SessionStartLimit 链接频控信息
type SessionStartLimit struct {
Total uint32 `json:"total"`
Expand Down
2 changes: 2 additions & 0 deletions botgo/session_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ var defaultSessionManager SessionManager = local.New()
type SessionManager interface {
// Start 启动连接,默认使用 apInfo 中的 shards 作为 shard 数量,如果有需要自己指定 shard 数,请修 apInfo 中的信息
Start(apInfo *dto.WebsocketAP, token *token.Token, intents *dto.Intent) error
// 自己指定具体的shard
StartSingle(apInfo *dto.WebsocketAPSingle, token *token.Token, intents *dto.Intent) error
}
30 changes: 30 additions & 0 deletions botgo/sessions/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ func (l *ChanManager) Start(apInfo *dto.WebsocketAP, token *token.Token, intents
return nil
}

// Start 启动指定的分片 session manager 适合想要手动指定目前分片的开发者(分片较少)
func (l *ChanManager) StartSingle(apInfo *dto.WebsocketAPSingle, token *token.Token, intents *dto.Intent) error {
defer log.Sync()
if err := manager.CheckSessionLimitSingle(apInfo); err != nil {
log.Errorf("[ws/session/local] session limited apInfo: %+v", apInfo)
return err
}
startInterval := manager.CalcInterval(apInfo.SessionStartLimit.MaxConcurrency)
log.Infof("[ws/session/local] will start %d sessions and per session start interval is %s",
apInfo.ShardCount, startInterval)

// 只启动一个分片

session := dto.Session{
URL: apInfo.URL,
Token: *token,
Intent: *intents,
LastSeq: 0,
Shards: dto.ShardConfig{
ShardID: apInfo.ShardID,
ShardCount: apInfo.ShardCount,
},
}

time.Sleep(startInterval)
go l.newConnect(session)

return nil
}

// newConnect 启动一个新的连接,如果连接在监听过程中报错了,或者被远端关闭了链接,需要识别关闭的原因,能否继续 resume
// 如果能够 resume,则往 sessionChan 中放入带有 sessionID 的 session
// 如果不能,则清理掉 sessionID,将 session 放入 sessionChan 中
Expand Down
8 changes: 8 additions & 0 deletions botgo/sessions/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,11 @@ func CheckSessionLimit(apInfo *dto.WebsocketAP) error {
}
return nil
}

// CheckSessionLimit 检查链接数是否达到限制,如果达到限制需要等待重置
func CheckSessionLimitSingle(apInfo *dto.WebsocketAPSingle) error {
if apInfo.ShardCount > apInfo.SessionStartLimit.Remaining {
return errs.ErrSessionLimit
}
return nil
}
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ type Settings struct {
LinkPic string `yaml:"link_pic"`
MusicPrefix string `yaml:"music_prefix"`
DisableWebui bool `yaml:"disable_webui"`
ShardCount int `yaml:"shard_count"`
ShardID int `yaml:"shard_id"`
}

// LoadConfig 从文件中加载配置并初始化单例配置
Expand Down
34 changes: 28 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ func main() {
if err != nil {
log.Fatalln(err)
}
fmt.Printf("分片建议\n")
fmt.Printf("建议的分片数量:%d\n", wsInfo.Shards)
fmt.Printf("每 24 小时可创建 Session 数:%d\n", wsInfo.SessionStartLimit.Total)
fmt.Printf("目前还可以创建的 Session 数:%d\n", wsInfo.SessionStartLimit.Remaining)
fmt.Printf("重置计数的剩余时间(ms):%d\n", wsInfo.SessionStartLimit.ResetAfter)
fmt.Printf("每 5s 可以创建的 Session 数:%d\n", wsInfo.SessionStartLimit.MaxConcurrency)

// 定义和初始化intent变量
var intent dto.Intent = 0
Expand All @@ -204,12 +210,28 @@ func main() {

// 启动session manager以管理websocket连接
// 指定需要启动的分片数为 2 的话可以手动修改 wsInfo
go func() {
wsInfo.Shards = 1
if err = botgo.NewSessionManager().Start(wsInfo, token, &intent); err != nil {
log.Fatalln(err)
}
}()
if conf.Settings.ShardCount == 1 {
go func() {
wsInfo.Shards = 1
if err = botgo.NewSessionManager().Start(wsInfo, token, &intent); err != nil {
log.Fatalln(err)
}
}()
log.Printf("不使用分片,所有信息都由当前gensokyo处理...\n")
} else {
go func() {
wsInfoSingle := &dto.WebsocketAPSingle{
URL: wsInfo.URL,
ShardCount: uint32(conf.Settings.ShardCount),
ShardID: uint32(conf.Settings.ShardID),
SessionStartLimit: wsInfo.SessionStartLimit,
}
if err = botgo.NewSessionManager().StartSingle(wsInfoSingle, token, &intent); err != nil {
log.Fatalln(err)
}
}()
log.Printf("使用%d个分片,当前是第%d个分片,比如:[0,4],代表分为四个片,当前链接是第 0 个片,业务稍后应该继续多开gensokyo,可在不同的服务器和ip地址 shard 为[1,4],[2,4],[3,4]的链接,才能完整接收和处理事件。\n", conf.Settings.ShardCount, conf.Settings.ShardID)
}

// 启动多个WebSocket客户端的逻辑
if !allEmpty(conf.Settings.WsAddress) {
Expand Down
2 changes: 2 additions & 0 deletions template/config_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ settings:
idmap_pro : false #需开启hash_id配合,高级id转换增强,可以多个真实值bind到同一个虚拟值,对于每个用户,每个群\私聊\判断私聊\频道,都会产生新的虚拟值,但可以多次bind,bind到同一个数字.数据库负担会变大.
send_delay : 300 #单位 毫秒 默认300ms 可以视情况减少到100或者50
disable_webui: false #禁用webui
shard_count: 1 #分片数量 默认1
shard_id: 0 #当前分片id 默认从0开始,详细请看 https://bot.q.qq.com/wiki/develop/api/gateway/reference.html

title : "Gensokyo © 2023 - Hoshinonyaruko" #程序的标题 如果多个机器人 可根据标题区分
custom_bot_name : "Gensokyo全域机器人" #自定义机器人名字,会在api调用中返回,默认Gensokyo全域机器人
Expand Down
Loading