Files
bl/logic/main.go
昔念 79d4343cdc
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful
```
feat(common/cool): 更新GetClient函数支持端口参数

更新GetClient函数签名以接收端口参数,并修改客户端映射键的计算方式,
添加GetClientOnly函数用于仅通过uid获取客户端。

fix(common/rpc): 修复RPC调用中的客户端获取方法

将GetClient调用替换为GetClientOnly,确保正确的客户端获取逻辑。

refactor(logic/controller): 重命名Port字段为UID并优化道具列表处理

将Controller结构体中的Port字段重命名为UID以更好地反映其用途,
优化GetUserItemList函数中道具列表的初始化和填充逻辑。

perf(logic): 调整性能分析web服务启动位置

将PprofWeb服务从全局启动移至调试模式下启动,优化服务配置。

refactor(logic/server): 更新服务器UID生成逻辑

修改Maincontroller的UID字段设置方式,使用服务器ID和端口组合生成唯一标识。

refactor(logic/service/player): 移除未使用的导入并优化怪物生成

移除未使用的service导入,优化怪物生成逻辑中的地图数据访问。

feat(logic/service/space): 添加PitS缓存映射并重构空间初始化

添加新的PitS字段
2026-03-02 23:59:15 +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.Player) bool {
value.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))
}