Files
bl/logic/main.go
昔念 d74652373c ```
refactor(socket): 更新广播和退出逻辑中的类型引用

更新socket服务器中广播功能和退出功能的代码,
将player.Player类型替换为player.ClientData类型,
并相应调整方法调用以适应新的数据结构。

feat(map): 添加LoadOrStore方法支持

在并发安全的swiss map中新增LoadOrStore方法,
提供原子性的加载或存储功能,增强map的操作能力。

refactor(login): 优化登录逻辑中的玩家获取方式

重构登录控制器中获取玩家对象的方式,
直接从
2026-03-16 22:30:12 +08:00

182 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"log"
"os"
"runtime"
"strconv"
"strings"
"time"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gproc"
"blazing/logic/service/player"
"blazing/cool"
"github.com/shirou/gopsutil/v4/mem"
"blazing/modules/base/service"
blservice "blazing/modules/player/service"
"net/http"
_ "net/http/pprof"
)
// PprofWeb 启动pprof性能分析web服务
// PprofWeb 启动pprof web服务仅重试2个端口保证监听成功
func PprofWeb() {
// 开启pprof跟踪
runtime.SetMutexProfileFraction(1)
runtime.SetBlockProfileRate(1)
// 定义2个重试端口主端口9909 + 备用端口9910
ports := []int{9909, 9910}
// 遍历端口尝试监听
for _, port := range ports {
addr := ":" + strconv.Itoa(port)
fmt.Printf("[INFO] 尝试启动pprof服务监听端口: %d\n", port)
// 尝试监听并处理错误
err := http.ListenAndServe(addr, nil)
// 只有端口被占用等致命错误才重试下一个端口
if err != nil {
fmt.Printf("[WARN] 端口%d监听失败: %v\n", port, err)
continue
}
// 监听成功则直接返回
return
}
// 所有端口都失败时的兜底
errMsg := fmt.Sprintf("[FATAL] 端口9909/9910均监听失败pprof服务启动失败")
fmt.Println(errMsg)
// 可选根据业务需求决定是否panic
// panic(errMsg)
}
func cleanup() {
fmt.Println("执行优雅清理资源...")
player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool {
value.Player.Kick(true)
return false
})
//fight.Fightpool.ReleaseTimeout(0)
fmt.Println("资源清理完成,程序即将退出")
}
// signalHandlerForMain 主进程信号处理函数
func signalHandlerForMain(sig os.Signal) {
cleanup()
fmt.Println("MainProcess is shutting down due to signal:", sig.String())
}
// main 程序主入口函数
func main() {
// item := model.NeweggConfig()
// item.GeneratedPetIDs = []model.GeneratedPetID{
// {PetID: 1, Prob: 0.01},
// {PetID: 2, Prob: 0.01},
// {PetID: 3, Prob: 0.01},
// {PetID: 4, Prob: 0.01},
// {PetID: 5, Prob: 0.01},
// {PetID: 6, Prob: 0.01},
// }
// item.MalePet = 1
// item.FemalePet = 2
// _, err := g.DB(item.GroupName()).Model(item.TableName()).FieldsEx("id").Data(item).Insert()
// if err != nil {
// panic(err)
// }
//loadAccounts()
// if cool.IsRedisMode {
// go cool.ListenFunc(gctx.New())
// }
// 解析命令行参数
cool.Config.GameOnlineID = gcmd.GetOpt("id", "1").Uint32()
go Start() //注入service
// if cool.Config.GameOnlineID == 2 { //只分析1服务器的
// go PprofWeb()
// }
//go PprofWeb()
go monitorMemAndQuit()
fmt.Println("Process start, pid:", os.Getpid())
gproc.AddSigHandlerShutdown(
signalHandlerForMain,
)
gproc.Listen()
}
const (
memThresholdRatio = 0.9 // 内存占用阈值70%
checkInterval = 10 * time.Second // 内存检测间隔,可按需调整
)
// 监控内存,超阈值则优雅退出程序
func monitorMemAndQuit() {
var memStats runtime.MemStats
for {
// 1. 获取系统总内存和可用内存
sysMem, err := mem.VirtualMemory()
if err != nil {
log.Printf("获取系统内存失败:%v\n", err)
time.Sleep(checkInterval)
continue
}
// 2. 获取Go进程当前堆内存占用进程实际使用的核心内存
runtime.ReadMemStats(&memStats)
procUsedMem := memStats.HeapInuse // 进程堆内存占用(字节)
sysTotalMem := sysMem.Total // 系统总内存(字节)
// 3. 计算进程内存占系统总内存的比例
usedRatio := float64(procUsedMem) / float64(sysTotalMem)
// 格式化输出MB方便查看
procUsedMB := procUsedMem / 1024 / 1024
sysTotalMB := sysTotalMem / 1024 / 1024
log.Printf("当前内存:进程占用%vMB / 系统总%vMB占比%.1f%%",
procUsedMB, sysTotalMB, usedRatio*100)
// 4. 超70%阈值,执行优雅退出
if usedRatio >= memThresholdRatio {
log.Fatalf("内存占比达%.1f%%超过90%阈值,程序开始退出", usedRatio*100)
// ########## 可选:这里添加你的优雅清理逻辑 ##########
// 如:关闭数据库连接、释放文件句柄、保存业务状态、推送退出告警等
cleanup()
// 退出程序返回非0码方便进程管理工具识别并重启
os.Exit(1)
}
time.Sleep(checkInterval)
}
}
// loadAccounts 从CSV文件加载账号信息
func loadAccounts() {
t1, _ := os.Getwd()
data, err := os.ReadFile(t1 + "/b.csv")
if err != nil {
panic(err)
}
lines := strings.Split(string(data), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
t := service.NewBaseSysUserService().GetEamil(line)
blservice.NewUserService(uint32(t.ID)).Info.Reg(t.Username, 0)
}
//fmt.Printf("加载 %d 个账号\n", len(accounts))
}