refactor(common): 使用 sync.Map 优化全局客户端映射

将 common/cool/global.go 中的 Clientmap 从普通 map 替换为 sync.Map,
以提高并发安全性。同时迁移相关操作函数至 cool 包中统一管理。

更新了 rpc 和 service 层代码,确保正确调用新的客户端管理方法。
在 InfoService 中新增 Kick 方法用于处理用户踢出逻辑。
```
This commit is contained in:
2025-12-09 02:48:41 +08:00
parent 75bdacbd11
commit 2598dee881
6 changed files with 97 additions and 35 deletions

View File

@@ -4,6 +4,7 @@ import (
"blazing/common/utils"
"context"
"reflect"
"sync"
"time"
"github.com/antlabs/cronex"
@@ -11,6 +12,9 @@ import (
sensitive "github.com/zmexing/go-sensitive-word"
)
// 定义改为sync.Map
var Clientmap sync.Map
// ar Limiter = ratelimit.New(100) // per second
// var Limiter = limit.New()
var ctx = context.TODO()

25
common/cool/rpc.go Normal file
View File

@@ -0,0 +1,25 @@
package cool
// 存值示例
func AddClient(id uint16, client *ClientHandler) {
// 普通mapClientmap[id] = client
Clientmap.Store(id, client) // sync.Map存值
}
// 取值示例
func GetClient(id uint16) (*ClientHandler, bool) {
// 普通mapclient, ok := Clientmap[id]
val, ok := Clientmap.Load(id) // sync.Map取值
if !ok {
return nil, false
}
// 类型断言确保value是*ClientHandler
client, ok := val.(*ClientHandler)
return client, ok
}
type ClientHandler struct {
KickPerson func(uint32) error //踢人,这里是返回具体的logic
QuitSelf func(int) error //关闭服务器进程
Broadcast func(string) int //全服广播,返回的是在线人数
}

View File

@@ -31,7 +31,7 @@ func GetServerInfoList() []ServerInfo {
}
tt.Port = v.Port
t, ok := getClient(v.Port)
t, ok := cool.GetClient(v.Port)
if ok {
cool.Loger.Info(context.TODO(), "服务器假踢人")

View File

@@ -3,7 +3,6 @@ package rpc
import (
"blazing/common/data/share"
"blazing/cool"
"sync"
"blazing/modules/base/service"
"context"
@@ -19,33 +18,6 @@ import (
var rpcport = gconv.String(cool.Config.RPC)
// 定义改为sync.Map
var Clientmap sync.Map
// 存值示例
func addClient(id uint16, client *ClientHandler) {
// 普通mapClientmap[id] = client
Clientmap.Store(id, client) // sync.Map存值
}
// 取值示例
func getClient(id uint16) (*ClientHandler, bool) {
// 普通mapclient, ok := Clientmap[id]
val, ok := Clientmap.Load(id) // sync.Map取值
if !ok {
return nil, false
}
// 类型断言确保value是*ClientHandler
client, ok := val.(*ClientHandler)
return client, ok
}
type ClientHandler struct {
KickPerson func(uint32) error //踢人,这里是返回具体的logic
QuitSelf func(int) error //关闭服务器进程
Broadcast func(string) int //全服广播,返回的是在线人数
}
// Define the server handler
type ServerHandler struct{}
@@ -59,7 +31,7 @@ func (h *ServerHandler) Kick(ctx context.Context, userid uint32) error {
return fmt.Errorf("user not found", err)
}
cl, ok := getClient(useid1)
cl, ok := cool.GetClient(useid1)
if ok {
err := cl.KickPerson(userid) //实现指定服务器踢人
if err != nil {
@@ -74,16 +46,16 @@ func (h *ServerHandler) RegisterLogic(ctx context.Context, id, port uint16) erro
cool.Loger.Debug(context.Background(), "注册logic服务器", id, port)
//TODO 待修复滚动更新可能导致的玩家可以同时在旧服务器和新服务器同时在线的bug
revClient, ok := jsonrpc.ExtractReverseClient[ClientHandler](ctx)
revClient, ok := jsonrpc.ExtractReverseClient[cool.ClientHandler](ctx)
if !ok {
return fmt.Errorf("no reverse client")
}
t, _ := blservice.NewLoginServiceService().GetServerID(id)
aa, ok := getClient(t)
aa, ok := cool.GetClient(t)
if ok && aa != nil { //如果已经存在且这个端口已经被存过
aa.QuitSelf(0)
}
addClient(port, &revClient)
cool.AddClient(port, &revClient)
//Refurh()
return nil
@@ -92,7 +64,7 @@ func (h *ServerHandler) RegisterLogic(ctx context.Context, id, port uint16) erro
func StartServer() {
// create a new server instance
rpcServer := jsonrpc.NewServer(jsonrpc.WithReverseClient[ClientHandler](""))
rpcServer := jsonrpc.NewServer(jsonrpc.WithReverseClient[cool.ClientHandler](""))
rpcServer.Register("", &ServerHandler{})
cool.Loger.Debug(context.Background(), "jsonrpc server start", rpcport)

View File

@@ -0,0 +1,38 @@
package admin
import (
"blazing/cool"
"blazing/modules/blazing/service"
"context"
"github.com/gogf/gf/v2/frame/g"
)
type PlayerController struct {
*cool.Controller
}
func init() {
var task_info_controller = &PlayerController{
&cool.Controller{
Prefix: "/admin/sun/player",
Api: []string{"Add", "Delete", "Update", "Info", "List", "Page"},
Service: service.NewInfoService(0),
},
}
// 注册路由
cool.RegisterController(task_info_controller)
}
type KickReq struct {
g.Meta `path:"/kick" method:"POST"`
ID uint32 `json:"id"`
}
func (c *PlayerController) Kick(ctx context.Context, req *KickReq) (res *cool.BaseRes, err error) {
res = &cool.BaseRes{}
service.NewUserService(0).Info.Kick(uint32(req.ID))
return
}

View File

@@ -1,10 +1,12 @@
package service
import (
"blazing/common/data/share"
"blazing/common/data/xmlres"
"blazing/cool"
"blazing/modules/blazing/model"
"context"
"time"
"github.com/gogf/gf/v2/os/glog"
@@ -79,7 +81,9 @@ func (s *InfoService) Personself() *model.PlayerInfo {
//每天login时候检查重置时间然后把电池任务挖矿重置
//挖矿需要单独存,因为防止多开挖矿
tt.LastResetTime = gtime.Now()
//每天login时候检查重置时间然后把电池任务挖矿重置
//挖矿需要单独存,因为防止多开挖矿
tt.Data.TimeToday = 0 //重置电池
for i := 400; i < 500; i++ { //每日任务区段
tttL, ok := xmlres.TaskMap[i]
@@ -106,6 +110,25 @@ func (s *InfoService) Personself() *model.PlayerInfo {
ret := tt.Data
return &ret
}
func (s *InfoService) Kick(id uint32) {
cool.Loger.Info(context.TODO(), "服务器收到踢人")
useid1, err := share.ShareManager.GetUserOnline(id)
if err != nil {
return
}
cl, ok := cool.GetClient(useid1)
if ok {
err := cl.KickPerson(id) //实现指定服务器踢人
if err != nil {
return
}
}
}
func (s *InfoService) Save(data model.PlayerInfo) {