2025-12-11 10:32:39 +08:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
2026-01-21 14:51:10 +00:00
|
|
|
|
"log"
|
2025-12-11 10:32:39 +08:00
|
|
|
|
"os"
|
|
|
|
|
|
"runtime"
|
2026-02-20 23:33:24 +08:00
|
|
|
|
"strconv"
|
2025-12-11 10:32:39 +08:00
|
|
|
|
"strings"
|
2026-01-21 14:51:10 +00:00
|
|
|
|
"time"
|
2025-12-11 10:32:39 +08:00
|
|
|
|
|
|
|
|
|
|
_ "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"
|
|
|
|
|
|
|
2026-01-21 14:51:10 +00:00
|
|
|
|
"github.com/shirou/gopsutil/v4/mem"
|
|
|
|
|
|
|
2025-12-11 10:32:39 +08:00
|
|
|
|
"blazing/modules/base/service"
|
2026-01-19 18:51:56 +08:00
|
|
|
|
blservice "blazing/modules/player/service"
|
2025-12-11 10:32:39 +08:00
|
|
|
|
"net/http"
|
|
|
|
|
|
_ "net/http/pprof"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-12-25 12:21:15 +08:00
|
|
|
|
// PprofWeb 启动pprof性能分析web服务
|
2026-02-20 23:33:24 +08:00
|
|
|
|
// PprofWeb 启动pprof web服务,仅重试2个端口保证监听成功
|
2025-12-11 10:32:39 +08:00
|
|
|
|
func PprofWeb() {
|
2026-02-20 23:33:24 +08:00
|
|
|
|
// 开启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
|
2025-12-11 10:32:39 +08:00
|
|
|
|
}
|
2025-12-25 12:21:15 +08:00
|
|
|
|
|
2026-02-20 23:33:24 +08:00
|
|
|
|
// 所有端口都失败时的兜底
|
2026-04-10 10:28:22 +08:00
|
|
|
|
errMsg := "[FATAL] 端口9909/9910均监听失败,pprof服务启动失败"
|
2026-02-20 23:33:24 +08:00
|
|
|
|
fmt.Println(errMsg)
|
|
|
|
|
|
// 可选:根据业务需求决定是否panic
|
|
|
|
|
|
// panic(errMsg)
|
|
|
|
|
|
}
|
2026-01-21 14:51:10 +00:00
|
|
|
|
func cleanup() {
|
2026-02-13 22:57:05 +08:00
|
|
|
|
fmt.Println("执行优雅清理资源...")
|
2025-12-11 10:32:39 +08:00
|
|
|
|
|
2026-03-16 22:30:12 +08:00
|
|
|
|
player.Mainplayer.Range(func(key uint32, value *player.ClientData) bool {
|
|
|
|
|
|
value.Player.Kick(true)
|
2025-12-11 10:32:39 +08:00
|
|
|
|
|
2026-01-25 17:36:40 +08:00
|
|
|
|
return false
|
2025-12-11 10:32:39 +08:00
|
|
|
|
})
|
2026-01-26 14:12:12 +00:00
|
|
|
|
//fight.Fightpool.ReleaseTimeout(0)
|
2026-02-13 22:57:05 +08:00
|
|
|
|
fmt.Println("资源清理完成,程序即将退出")
|
2026-01-21 14:51:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// signalHandlerForMain 主进程信号处理函数
|
|
|
|
|
|
func signalHandlerForMain(sig os.Signal) {
|
|
|
|
|
|
cleanup()
|
2025-12-11 10:32:39 +08:00
|
|
|
|
fmt.Println("MainProcess is shutting down due to signal:", sig.String())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 12:21:15 +08:00
|
|
|
|
// main 程序主入口函数
|
2025-12-11 10:32:39 +08:00
|
|
|
|
func main() {
|
2026-01-20 22:08:36 +00:00
|
|
|
|
// 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)
|
|
|
|
|
|
// }
|
2025-12-11 10:32:39 +08:00
|
|
|
|
//loadAccounts()
|
|
|
|
|
|
// if cool.IsRedisMode {
|
|
|
|
|
|
// go cool.ListenFunc(gctx.New())
|
|
|
|
|
|
// }
|
|
|
|
|
|
// 解析命令行参数
|
2026-03-02 18:34:20 +08:00
|
|
|
|
cool.Config.GameOnlineID = gcmd.GetOpt("id", "1").Uint32()
|
2026-02-20 23:33:24 +08:00
|
|
|
|
go Start() //注入service
|
|
|
|
|
|
// if cool.Config.GameOnlineID == 2 { //只分析1服务器的
|
|
|
|
|
|
// go PprofWeb()
|
|
|
|
|
|
// }
|
2026-03-02 23:59:15 +08:00
|
|
|
|
|
2026-02-03 00:50:16 +08:00
|
|
|
|
//go PprofWeb()
|
2026-01-21 14:51:10 +00:00
|
|
|
|
go monitorMemAndQuit()
|
2025-12-11 10:32:39 +08:00
|
|
|
|
fmt.Println("Process start, pid:", os.Getpid())
|
|
|
|
|
|
|
|
|
|
|
|
gproc.AddSigHandlerShutdown(
|
|
|
|
|
|
|
|
|
|
|
|
signalHandlerForMain,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
gproc.Listen()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 14:51:10 +00:00
|
|
|
|
const (
|
2026-01-21 20:46:05 +00:00
|
|
|
|
memThresholdRatio = 0.9 // 内存占用阈值70%
|
|
|
|
|
|
checkInterval = 10 * time.Second // 内存检测间隔,可按需调整
|
2026-01-21 14:51:10 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 监控内存,超阈值则优雅退出程序
|
|
|
|
|
|
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 {
|
2026-04-10 10:28:22 +08:00
|
|
|
|
log.Fatalf("内存占比达%.1f%%,超过90%%阈值,程序开始退出", usedRatio*100)
|
2026-01-21 14:51:10 +00:00
|
|
|
|
// ########## 可选:这里添加你的优雅清理逻辑 ##########
|
|
|
|
|
|
// 如:关闭数据库连接、释放文件句柄、保存业务状态、推送退出告警等
|
|
|
|
|
|
cleanup()
|
|
|
|
|
|
// 退出程序,返回非0码(方便进程管理工具识别并重启)
|
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
time.Sleep(checkInterval)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 12:21:15 +08:00
|
|
|
|
// loadAccounts 从CSV文件加载账号信息
|
2025-12-11 10:32:39 +08:00
|
|
|
|
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))
|
2026-01-01 19:57:39 +08:00
|
|
|
|
}
|