From 7a87bfa089b8dccc9f753ffb11d52aafbd7162d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Tue, 15 Jul 2025 12:14:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor(common):=20=E9=87=8D=E6=9E=84=20common?= =?UTF-8?q?=20=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 global.go 文件 - 更新 player.go 中的玩家数据存储方式 - 删除 session.go 文件 - 调整 rpc.go 中的 RPC 客户端方法 - 更新 ServerEvent.go 中的会话管理 - 调整 controller 中的 Maincontroller 结构 - 更新 login.go 中的用户登录逻辑 - 调整 service 中的玩家数据获取方式 - 更新 admin/login.go 和 login.go 中的会话管理 --- common/{core => cool}/global.go | 12 +- common/data/cache/cache.go | 181 ++++++++++++++++++++++ common/data/entity/player.go | 6 +- common/data/session/session.go | 45 ------ common/rpc/rpc.go | 6 +- common/socket/ServerEvent.go | 3 +- logic/controller/controller.go | 8 +- logic/controller/login.go | 5 +- logic/server.go | 4 +- logic/service/login/LoginSidInfo.go | 4 +- logic/service/service.go | 8 +- modules/blazing/controller/admin/login.go | 4 +- modules/blazing/service/login.go | 2 - 13 files changed, 208 insertions(+), 80 deletions(-) rename common/{core => cool}/global.go (79%) create mode 100644 common/data/cache/cache.go delete mode 100644 common/data/session/session.go diff --git a/common/core/global.go b/common/cool/global.go similarity index 79% rename from common/core/global.go rename to common/cool/global.go index f1599b674..261bd6e80 100644 --- a/common/core/global.go +++ b/common/cool/global.go @@ -1,16 +1,17 @@ -package core +package cool import ( - "fmt" + "context" "sync" + "github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/util/gconv" "github.com/yitter/idgenerator-go/idgen" ) var ( - Mainplayer sync.Map //玩家数据 - Maincmdcache sync.Map //命令缓存 + Mainplayer sync.Map //玩家数据 + CmdCache sync.Map //命令缓存 ) func init() { @@ -25,7 +26,6 @@ func init() { // 保存参数(务必调用,否则参数设置不生效): idgen.SetIdGenerator(options) newId := idgen.NextId() - - fmt.Println(newId, "初始化雪花算法") + glog.Debug(context.Background(), "初始化雪花算法", newId) } diff --git a/common/data/cache/cache.go b/common/data/cache/cache.go new file mode 100644 index 000000000..f96d4d8f6 --- /dev/null +++ b/common/data/cache/cache.go @@ -0,0 +1,181 @@ +package cache + +import ( + "blazing/cool" + "context" + "fmt" + "strings" + "time" + + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/os/gcache" + "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/util/gconv" +) + +var ( + // ErrCacheMiss 表示缓存未命中 + ErrCacheMiss = gerror.New("缓存未找到") + // ErrTypeConvert 表示类型转换失败 + ErrTypeConvert = gerror.New("缓存值类型转换失败") +) + +// CacheStore 泛型缓存存储 +type CacheStore[T any] struct { + manager *gcache.Cache // 缓存管理器 + prefix string // 缓存键前缀 +} + +// NewSessionStore 创建会话缓存实例 +func NewSessionStore() *CacheStore[uint32] { + return &CacheStore[uint32]{ + manager: cool.CacheManager, + prefix: "blazing:session:", + } +} + +// NewUserOnlineStore 创建用户在线状态缓存实例 +func NewUserOnlineStore() *CacheStore[uint32] { + return &CacheStore[uint32]{ + manager: cool.CacheManager, + prefix: "blazing:useronline:", + } +} + +// 生成带前缀的缓存键 +func (s *CacheStore[T]) formatKey(key string) string { + return s.prefix + strings.TrimSpace(key) +} + +// Get 通过键获取缓存值 +func (s *CacheStore[T]) Get(ctx context.Context, key string) (T, error) { + var zero T + result, err := s.manager.Get(ctx, s.formatKey(key)) + if err != nil { + return zero, gerror.Wrapf(err, "获取缓存失败,键: %s", key) + } + if result.IsEmpty() { + return zero, ErrCacheMiss + } + + // 使用 ConvertWithRefer 进行类型转换 + value := gconv.ConvertWithRefer(result.Val(), zero) + + // 类型断言检查转换结果 + converted, ok := value.(T) + if !ok { + return zero, gerror.Wrapf( + ErrTypeConvert, + "键: %s,缓存值实际类型: %T,期望类型: %T", + key, result.Val(), zero, + ) + } + + return converted, nil +} + +// Set 设置缓存值并带有效期 +func (s *CacheStore[T]) Set(ctx context.Context, key string, value T, duration time.Duration) error { + err := s.manager.Set(ctx, s.formatKey(key), value, duration) + if err != nil { + return gerror.Wrapf(err, "设置缓存失败,键: %s,值: %v", key, value) + } + fmt.Printf("[INFO] 缓存操作 [%s] 键: %s 值: %v 有效期: %v\n", + s.prefix, key, value, duration) + return nil +} + +// Del 删除缓存 +func (s *CacheStore[T]) Del(ctx context.Context, key string) error { + _, err := s.manager.Remove(ctx, s.formatKey(key)) + if err != nil { + return gerror.Wrapf(err, "删除缓存失败,键: %s", key) + } + fmt.Printf("[INFO] 删除缓存 [%s] 键: %s 成功\n", s.prefix, key) + return nil +} + +// Contains 检查缓存是否存在 +func (s *CacheStore[T]) Contains(ctx context.Context, key string) (bool, error) { + exists, err := s.manager.Contains(ctx, s.formatKey(key)) + if err != nil { + return false, gerror.Wrapf(err, "检查缓存是否存在失败,键: %s", key) + } + return exists, nil +} + +// GetOrSet 获取缓存值,如果不存在则设置默认值 +func (s *CacheStore[T]) GetOrSet(ctx context.Context, key string, defaultValue T, duration time.Duration) (T, error) { + var zero T + result, err := s.manager.GetOrSet(ctx, s.formatKey(key), defaultValue, duration) + if err != nil { + return zero, gerror.Wrapf(err, "获取或设置缓存失败,键: %s", key) + } + + // 类型转换 + value := gconv.ConvertWithRefer(result.Val(), zero) + converted, ok := value.(T) + if !ok { + return zero, gerror.Wrapf( + ErrTypeConvert, + "键: %s,缓存值实际类型: %T,期望类型: %T", + key, result.Val(), zero, + ) + } + + return converted, nil +} + +// SessionManager 会话管理器 +type SessionManager struct { + sessionStore *CacheStore[uint32] // 会话缓存 + userOnlineStore *CacheStore[uint32] // 用户在线状态缓存 +} + +// NewSessionManager 创建会话管理器 +func NewSessionManager() *SessionManager { + return &SessionManager{ + sessionStore: NewSessionStore(), + userOnlineStore: NewUserOnlineStore(), + } +} + +// GetSession 通过会话ID获取用户ID +func (m *SessionManager) GetSession(sessionID string) (uint32, error) { + return m.sessionStore.Get(context.Background(), sessionID) +} + +// SaveSession 保存会话信息 +func (m *SessionManager) SaveSession(sessionID string, userID uint32) error { + return m.sessionStore.Set(gctx.New(), sessionID, userID, time.Hour*24) +} + +// DeleteSession 删除会话 +func (m *SessionManager) DeleteSession(sessionID string) error { + return m.sessionStore.Del(gctx.New(), sessionID) +} + +// SessionExists 检查会话是否存在 +func (m *SessionManager) SessionExists(sessionID string) (bool, error) { + return m.sessionStore.Contains(context.Background(), sessionID) +} + +// SetUserOnline 设置用户在线状态 +func (m *SessionManager) SetUserOnline(userID uint32, serverID uint32) error { + return m.userOnlineStore.Set(gctx.New(), gconv.String(userID), serverID, 0) +} + +// GetUserOnline 获取用户在线状态 +func (m *SessionManager) GetUserOnline(userID uint32) (uint32, error) { + return m.userOnlineStore.Get(context.Background(), gconv.String(userID)) +} + +// DeleteUserOnline 删除用户在线状态 +func (m *SessionManager) DeleteUserOnline(userID uint32) error { + return m.userOnlineStore.Del(gctx.New(), gconv.String(userID)) +} + +// UserOnlineExists 检查用户在线状态是否存在 +func (m *SessionManager) UserOnlineExists(userID uint32) (bool, error) { + return m.userOnlineStore.Contains(context.Background(), gconv.String(userID)) +} diff --git a/common/data/entity/player.go b/common/data/entity/player.go index 1a7b720a9..fc7dff3ec 100644 --- a/common/data/entity/player.go +++ b/common/data/entity/player.go @@ -1,7 +1,7 @@ package entity import ( - "blazing/common/core" + "blazing/cool" "github.com/panjf2000/gnet/v2" ) @@ -48,10 +48,8 @@ func (p *Player) SendPack(b []byte) error { func ConutPlayer() int { - // v := reflect.ValueOf(&core.Mainplayer).Elem().FieldByName("m").Elem() - // return int(v.FieldByName("count").Int()) count := 0 - core.Mainplayer.Range(func(key, value interface{}) bool { + cool.Mainplayer.Range(func(key, value interface{}) bool { count++ return true // 继续遍历 }) diff --git a/common/data/session/session.go b/common/data/session/session.go deleted file mode 100644 index 82fe700b7..000000000 --- a/common/data/session/session.go +++ /dev/null @@ -1,45 +0,0 @@ -package session - -import ( - "blazing/cool" - "context" - "fmt" - "strings" - "time" - - "github.com/gogf/gf/v2/os/gctx" -) - -var sessionprx = "blazing:session:" - -// GetSession 通过给定的键从缓存中获取会话数据。 -// 该函数主要执行以下操作: -// 1. 使用 strings.Trim 移除输入字符串 t1 两端的空格,得到 t2。 -// 2. 调用 cool.CacheManager.Get 方法,在上下文为 context.Background() 的情况下,使用 t2 作为键从缓存中获取数据。 -// 参数: -// -// t1 - 用于获取会话数据的键字符串。 -func GetSession(t1 string) (userid uint32, err error) { - // 移除输入键两端的空格,以确保键的格式一致性。 - t2 := strings.Trim(t1, " ") - - // 从缓存中获取与键 t2 关联的数据。这里假设 cool.CacheManager 已经初始化,并且 Get 方法可用。 - // 此处不处理 err,可能是因为上层调用者期望处理这个错误,或者在特定上下文中,错误被视为可接受。 - t, err := cool.CacheManager.Get(context.Background(), sessionprx+t2) - - userid = t.Uint32() - return -} -func SaveSession(session string, userid string) error { - - err := cool.CacheManager.Set(gctx.New(), sessionprx+strings.Trim(session, " "), userid, time.Hour*24) - // gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`)) - //t, err := cool.CacheManager.Contains(context.Background(), strings.Trim(session, " ")) - - fmt.Println("前端获取", session, err) - // if t { - // return nil - // } - - return err -} diff --git a/common/rpc/rpc.go b/common/rpc/rpc.go index 0fcb44e50..138c16453 100644 --- a/common/rpc/rpc.go +++ b/common/rpc/rpc.go @@ -108,8 +108,6 @@ func StartClient(port uint16, callback any) *struct { Kick func(int32) error RegisterLogic func(int32) error - UserLogin func(int32, int32) error - UserLogout func(int32, int32) error } { closer1, err := jsonrpc.NewMergeClient(context.Background(), "ws://"+rpcaddr, "", []interface{}{ @@ -141,6 +139,6 @@ var RPCClient struct { RegisterLogic func(int32) error //注册服务器消息 - UserLogin func(int32, int32) error //用户登录事件 - UserLogout func(int32, int32) error //用户登出事件 + // UserLogin func(int32, int32) error //用户登录事件 + // UserLogout func(int32, int32) error //用户登出事件 } diff --git a/common/socket/ServerEvent.go b/common/socket/ServerEvent.go index f61726b88..bdcf456b8 100644 --- a/common/socket/ServerEvent.go +++ b/common/socket/ServerEvent.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "time" + "blazing/common/data/cache" "blazing/common/data/entity" "github.com/gogf/gf/v2/os/glog" @@ -48,7 +49,7 @@ func (s *Server) OnClose(c gnet.Conn, _ error) (action gnet.Action) { t := v.GetPlayer() if t != nil { glog.Debug(context.Background(), t.UserID, "断开连接") - + cache.NewSessionManager().DeleteUserOnline(t.UserID) //设置用户登录服务器 } //} diff --git a/logic/controller/controller.go b/logic/controller/controller.go index 7e1568cb4..fde5ff28e 100644 --- a/logic/controller/controller.go +++ b/logic/controller/controller.go @@ -1,7 +1,6 @@ package controller import ( - "blazing/common/core" "blazing/common/data/entity" "blazing/common/socket/handler" "blazing/cool" @@ -23,14 +22,11 @@ import ( var Maincontroller = NewController() //注入service // 分发cmd逻辑实现Controller type Controller struct { - //connected int64 //统计连接数 Port uint32 RPCClient struct { Kick func(int32) error RegisterLogic func(int32) error - UserLogin func(int32, int32) error - UserLogout func(int32, int32) error } } @@ -110,7 +106,7 @@ func init() { //默认初始化扫描 } glog.Debug(context.Background(), "注册方法", func_cmd, method.Name) // fmt.Println(methodValue.Interface().(func(gnet.Conn, handler.TomeeHeader))) - _, ok := core.Maincmdcache.LoadOrStore(func_cmd, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache + _, ok := cool.CmdCache.LoadOrStore(func_cmd, methodValue) //TODO 待实现对不同用户初始化方法以取消全局cmdcache if ok { //方法已存在init glog.Error(context.Background(), "方法已存在init,不会初始化后面的方法", func_cmd) @@ -163,7 +159,7 @@ func getcmd(t reflect.Type) uint32 { // 遍历结构体方法并执行RECV_cmd func Recv(c gnet.Conn, data handler.TomeeHeader) { - tt, ok := core.Maincmdcache.Load(data.CMD) + tt, ok := cool.CmdCache.Load(data.CMD) if !ok { glog.Error(context.Background(), data.CMD, "cmd未注册") diff --git a/logic/controller/login.go b/logic/controller/login.go index bb3c6a29f..ff4b99692 100644 --- a/logic/controller/login.go +++ b/logic/controller/login.go @@ -1,6 +1,7 @@ package controller import ( + "blazing/common/data/cache" "blazing/logic/service" "blazing/logic/service/login" "encoding/hex" @@ -15,9 +16,9 @@ func (h *Controller) Login(data login.LoginSidInfo, c gnet.Conn) []byte { //这 if tt := data.CheakSession(); tt { //说明sid正确 h.RPCClient.Kick(int32(data.Head.UserID)) //先踢人 - h.RPCClient.UserLogin(int32(h.Port), int32(data.Head.UserID)) //初始化用户登录 + // h.RPCClient.UserLogin(int32(h.Port), int32(data.Head.UserID)) //初始化用户登录 service.SetPlayer(c, data.Head.UserID) - + cache.NewSessionManager().SetUserOnline(data.Head.UserID, h.Port) //设置用户登录服务器 } t1, _ := hex.DecodeString("0000045D37000003E9000186A600000000000186A6683F89CF6E69656F0000000000000000000000000008000F00000000000000000000000000000000000000000000000000000001000001DB0000018B000000000000A8C000000000000000000000000000000000000000080001388000000001000000017FFFFFFF00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000000000000000000000000000000000064000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001FFFFFFFF000000004E4F4E4F0000000000000000000000000000000000000001000000010000000100000001000000010000000100000001000000000003030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030000000100000064000000000000000000000000000000000000001F000000000000006400000000000093F4000093F4000000D5000000F7000000AD00000088000000920000008C0000009C00000000000000000000000000000000000000000000000000000004000027900000001B00004E6200000014000028380000002800004E3E0000002368493DC60000000000000000000000000000000000000000000100000000000000A937000007D1000186A600000000000186A66E69656F00000000000000000000000000000000000000000000000F0000000000000000000001DB0000018B0000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000001000000000000000000000000000000000000000000000000000000000000000000000000") diff --git a/logic/server.go b/logic/server.go index 301f7898d..d718ea2be 100644 --- a/logic/server.go +++ b/logic/server.go @@ -72,8 +72,8 @@ func Start(serverid uint32) { } // go func() { - t := rpc.StartClient(uint16(serverid), controller.Maincontroller) - + t := rpc.StartClient(uint16(port), controller.Maincontroller) + //TODO 待实现掉线重新连接login controller.Maincontroller.RPCClient = *t //将RPC赋值Start controller.Maincontroller.Port = serverid //赋值服务器ID //}() diff --git a/logic/service/login/LoginSidInfo.go b/logic/service/login/LoginSidInfo.go index b4c5b5596..58ea6f69b 100644 --- a/logic/service/login/LoginSidInfo.go +++ b/logic/service/login/LoginSidInfo.go @@ -1,7 +1,7 @@ package login import ( - "blazing/common/data/session" + "blazing/common/data/cache" "blazing/common/socket/handler" "encoding/hex" "fmt" @@ -21,7 +21,7 @@ func (l *LoginSidInfo) CheakSession() bool { //g.Dump(tt) t1 := hex.EncodeToString(l.Sid) - t, err := session.GetSession(t1) + t, err := cache.NewSessionManager().GetSession(t1) if err != nil { return false } diff --git a/logic/service/service.go b/logic/service/service.go index a06a36400..0a4ad757d 100644 --- a/logic/service/service.go +++ b/logic/service/service.go @@ -1,10 +1,10 @@ package service import ( - "blazing/common/core" "blazing/common/data/entity" "blazing/common/socket/errorcode" "blazing/common/socket/handler" + "blazing/cool" "github.com/panjf2000/gnet/v2" ) @@ -18,7 +18,7 @@ func GetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优 return clientdata.GetPlayer() } var player *entity.Player - if player1, ok := core.Mainplayer.Load((userid)); ok { + if player1, ok := cool.Mainplayer.Load((userid)); ok { player = player1.(*entity.Player) //取成功,否则创建 clientdata.SetPlayer(player) } @@ -29,7 +29,7 @@ func GetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优 func KickPlayer(userid uint32) { //踢出玩家 //TODO 返回错误码 //var player *entity.Player - if player1, ok := core.Mainplayer.Load((userid)); ok { + if player1, ok := cool.Mainplayer.Load((userid)); ok { player := player1.(*entity.Player) //取成功,否则创建 head := handler.NewTomeeHeader() head.Result = uint32(errorcode.ErrorCodes.ErrAlreadyLoggedIn) @@ -52,7 +52,7 @@ func SetPlayer(c gnet.Conn, userid uint32) *entity.Player { //TODO 这里待优 entity.WithUserID(userid), //注入ID entity.WithConn(c), //注入conn ) - core.Mainplayer.Store(userid, player) + cool.Mainplayer.Store(userid, player) clientdata.SetPlayer(player) //= player diff --git a/modules/blazing/controller/admin/login.go b/modules/blazing/controller/admin/login.go index ce94e31f5..73b07a6d4 100644 --- a/modules/blazing/controller/admin/login.go +++ b/modules/blazing/controller/admin/login.go @@ -1,7 +1,7 @@ package admin import ( - "blazing/common/data/session" + "blazing/common/data/cache" "blazing/cool" baseservice "blazing/modules/base/service" "blazing/modules/blazing/service" @@ -77,7 +77,7 @@ func (c *BlazingController) GetSession(ctx context.Context, req *SessionReq) (re res.Session = retsid - if err := session.SaveSession(sid, gconv.String(accountID)); err != nil { + if err := cache.NewSessionManager().SaveSession(sid, gconv.String(accountID)); err != nil { res.Code = 400 res.Msg = err.Error() } diff --git a/modules/blazing/service/login.go b/modules/blazing/service/login.go index 8e5a8e68e..2b6758d15 100644 --- a/modules/blazing/service/login.go +++ b/modules/blazing/service/login.go @@ -54,8 +54,6 @@ func (s *LoginService) SetServerID(OnlineID uint32, Port uint16, t *struct { Kick func(int32) error RegisterLogic func(int32) error - UserLogin func(int32, int32) error - UserLogout func(int32, int32) error }) error { m := cool.DBM(s.Model).Where("online_id", OnlineID)