From b25f033939a177a098c726a5775d60f3d84f793b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:11:14 +0800 Subject: [PATCH] =?UTF-8?q?```=20refactor(socket):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E4=BF=9D=E5=AD=98=E9=94=81=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96panic=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除了ServerEvent.go中的sync.Once保存锁,因为可能存在重复保存问题, 同时将panic错误处理从fmt.Println改为使用cool.Logger.Error进行统一日志记录 feat(player): 优化踢人功能并添加超时机制 移除kick.go中的复杂异步超时逻辑 --- common/socket/ServerEvent.go | 8 ++--- common/socket/kick.go | 21 +----------- logic/controller/item_use.go | 2 +- logic/main.go | 2 +- logic/service/player/pack.go | 4 +-- logic/service/player/player.go | 22 +++++++++---- logic/service/player/save.go | 24 -------------- .../service/pet_fusion_material_service.go | 32 ++++++++----------- 8 files changed, 36 insertions(+), 79 deletions(-) diff --git a/common/socket/ServerEvent.go b/common/socket/ServerEvent.go index 9c01acf1c..753cb117a 100644 --- a/common/socket/ServerEvent.go +++ b/common/socket/ServerEvent.go @@ -65,11 +65,7 @@ func (s *Server) OnClose(c gnet.Conn, err error) (action gnet.Action) { v, _ := c.Context().(*player.ClientData) v.LF.Close() if v.Player != nil { - v.SaveL.Do(func() { //使用保存锁,确保在踢人和掉线的时候只保存一次 - - v.Player.Save() //保存玩家数据 - - }) + v.Player.Save() //保存玩家数据 } @@ -110,7 +106,7 @@ func (s *Server) OnTraffic(c gnet.Conn) (action gnet.Action) { if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值 // 1. 打印错误信息 - fmt.Println(context.TODO(), "panic 错误:", err) + cool.Logger.Error(context.TODO(), "panic 错误:", err) } }() diff --git a/common/socket/kick.go b/common/socket/kick.go index c36ca0f9e..9a1eeb5e6 100644 --- a/common/socket/kick.go +++ b/common/socket/kick.go @@ -4,7 +4,6 @@ import ( "blazing/common/socket/errorcode" "blazing/logic/service/common" "blazing/logic/service/player" - "blazing/modules/base/service" "fmt" "time" ) @@ -34,25 +33,7 @@ func (s *Server) KickPerson(a int) error { return nil } - // 1. 创建结果通道 - resultChan := make(chan error, 1) - - // 2. 启动 goroutine 执行踢人操作 - go func() { - err := player.KickPlayer(uint32(a)) - resultChan <- err - }() - - // 3. 用 select 监听结果和超时信号 - select { - case err := <-resultChan: - // 正常完成 - return err - case <-time.After(kickTimeout): - service.NewBaseSysLogService().RecordKick(uint32(a), fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout).Error()) - // 超时触发,返回自定义或内置超时错误 - return fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout) - } + return player.KickPlayer(uint32(a)) } // 参数不为0是强制踢出 diff --git a/logic/controller/item_use.go b/logic/controller/item_use.go index c5cf77da0..25d6289c3 100644 --- a/logic/controller/item_use.go +++ b/logic/controller/item_use.go @@ -67,7 +67,7 @@ func (h Controller) UsePetItemOutOfFight(data *item.C2S_USE_PET_ITEM_OUT_OF_FIGH result = &item.S2C_USE_PET_ITEM_OUT_OF_FIGHT{} currentPet.CalculatePetPane(false) copier.Copy(&result, currentPet) - + defer c.Service.Info.Save(*c.Info) return result, 0 } diff --git a/logic/main.go b/logic/main.go index 31802e5b2..e664e38ba 100644 --- a/logic/main.go +++ b/logic/main.go @@ -18,7 +18,6 @@ import ( "github.com/shirou/gopsutil/v4/mem" - "blazing/modules/base/service" blservice "blazing/modules/player/service" "net/http" @@ -80,6 +79,7 @@ func main() { // if cool.Config.PortBL == 1 || cool.Config.PortBL == 2 { //只分析1服务器的 // go PprofWeb() // } + go PprofWeb() go monitorMemAndQuit() fmt.Println("Process start, pid:", os.Getpid()) diff --git a/logic/service/player/pack.go b/logic/service/player/pack.go index 0ebb546c6..3178f3674 100644 --- a/logic/service/player/pack.go +++ b/logic/service/player/pack.go @@ -133,8 +133,8 @@ type ClientData struct { ERROR_CONNUT int Wsmsg *WsCodec Conn gnet.Conn - SaveL sync.Once //保存锁 - LF *lockfree.Lockfree[[]byte] + //SaveL sync.Once //保存锁 + LF *lockfree.Lockfree[[]byte] //SaveDone chan struct{} } diff --git a/logic/service/player/player.go b/logic/service/player/player.go index e501043dc..0951d45ee 100644 --- a/logic/service/player/player.go +++ b/logic/service/player/player.go @@ -7,7 +7,9 @@ import ( "blazing/logic/service/common" "blazing/logic/service/fight/info" "blazing/logic/service/space" + "fmt" "sync/atomic" + "time" "blazing/modules/base/service" @@ -224,27 +226,35 @@ func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) { } func (player1 *Player) Kick(qtype int) { - - //取成功,否则创建 - //player1.Save() //先保存数据再返回 + // 取成功,否则创建 + // player1.Save() //先保存数据再返回 head := common.NewTomeeHeader(1001, player1.Info.UserID) head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere) if qtype == 1 { head.Result = uint32(errorcode.ErrorCodes.ErrXinPlanSleepMode) } - //实际上这里有个问题,会造成重复保存问题 + // 实际上这里有个问题,会造成重复保存问题 player1.SendPack(head.Pack(nil)) CloseChan := make(chan struct{}) player1.MainConn.CloseWithCallback(func(c gnet.Conn, err error) error { - close(CloseChan) return nil }) - <-CloseChan + // --- 新增超时机制核心代码 --- + // 设定超时时间(可根据业务需求调整,这里以3秒为例) + const kickTimeout = 3 * time.Second + select { + case <-CloseChan: + // 正常流程:连接关闭回调已执行,CloseChan 被关闭 + case <-time.After(kickTimeout): + service.NewBaseSysLogService().RecordKick(uint32(player1.Info.UserID), fmt.Errorf("踢人操作超时(超时时间:%v)", kickTimeout).Error()) + // 超时处理:避免永久阻塞,可添加日志便于排查问题 + // 注意:这里不会中断 CloseWithCallback 的执行,仅解除当前协程的阻塞 + } } func (p *Player) Cheak(b error) { diff --git a/logic/service/player/save.go b/logic/service/player/save.go index 08e3ea896..6c1f2cfa3 100644 --- a/logic/service/player/save.go +++ b/logic/service/player/save.go @@ -22,30 +22,6 @@ func (p *Player) Save() { return } - // if p.FightC != nil { - - // //ov := make(chan struct{}) - // go func() { - - // defer func() { - // if err := recover(); err != nil { // 恢复 panic,err 为 panic 错误值 - // // 1. 打印错误信息 - - // cool.Logger.Error(context.TODO(), "panic 错误:", err) - - // } - // }() - // p.FightC.Over(p, info.BattleOverReason.PlayerOffline) //玩家逃跑,但是不能锁线程 - // }() - // //<-ov - // select { - // case <-p.FightC.GetOverChan(): //等待结束 - // case <-time.After(time.Second * 5): //等待5秒 - // cool.Logger.Error(context.TODO(), "战斗崩溃", p.Info.UserID) - - // } - - // } newtime := uint32(time.Now().Unix()) p.Info.TimeToday = p.Info.TimeToday + newtime - uint32(p.Logintime) //保存电池时间 diff --git a/modules/config/service/pet_fusion_material_service.go b/modules/config/service/pet_fusion_material_service.go index 1101c8bee..cd4306c7c 100644 --- a/modules/config/service/pet_fusion_material_service.go +++ b/modules/config/service/pet_fusion_material_service.go @@ -54,26 +54,20 @@ func (s *PetFusionMaterialService) Data(Material1 [4]uint32) int32 { "is_enable": 1, } m.Where(condition).Scan(&effect) - //这时候有可能效果是空的,那么这时候就再次查询默认的特性,保证每次必会生成一个数据库有的特性 - //也许这个时候的特性配方就是随机从数据库中查找一个特性 + if effect != nil { - // if effect == nil { - // effect2s := service.NewDictInfoService().GetData("effect") - // for _, v := range effect2s { - // return gconv.Uint32(v.Value) - // } - - // } - r := grand.Intn(4) - switch r { - case 0: - return int32(effect.Trait1Idx) - case 1: - return int32(effect.Trait2Idx) - case 2: - return int32(effect.Trait3Idx) - case 3: - return int32(effect.Trait4Idx) + r := grand.Intn(4) + switch r { + case 0: + return int32(effect.Trait1Idx) + case 1: + return int32(effect.Trait2Idx) + case 2: + return int32(effect.Trait3Idx) + case 3: + return int32(effect.Trait4Idx) + } } + return -1 }