refactor(socket): 移除重复保存锁并优化panic错误处理 移除了ServerEvent.go中的sync.Once保存锁,因为可能存在重复保存问题, 同时将panic错误处理从fmt.Println改为使用cool.Logger.Error进行统一日志记录 feat(player): 优化踢人功能并添加超时机制 移除kick.go中的复杂异步超时逻辑
This commit is contained in:
@@ -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)
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -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是强制踢出
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) //保存电池时间
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user