必须手动实现/metrics接口:新建MetricsController继承beego.Controller,显式注册beego.Get("/metrics", (*MetricsController).Get),仅返回cpu_usage_percent、mem_used_mb、goroutines_count三类轻量指标,跨平台调用gopsutil需分条件处理并设超时,开头强制校验X-Api-Key防止未授权访问。

Beego 本身不提供开箱即用的 CPU/内存监控 HTTP 接口,但可通过内置 beego.BeeApp 和 runtime/syscall 等标准库组合实现,且必须手动注册路由、避免暴露敏感指标到公网。
如何用 beego.Controller 实现 /metrics 接口
Beego 没有像 Prometheus 那样的原生指标端点,但你可以写一个普通 Controller 返回 JSON 格式的系统指标。关键不是“有没有”,而是“怎么安全地暴露”。
- 不要复用
beego.Admin(v2 已移除该模块),它早已废弃且无权限控制 - 在
controllers/metrics.go中定义新 Controller,继承web.Controller - 路由必须显式注册,例如
beego.Get("/metrics", (*MetricsController).Get),不能依赖自动扫描 - 返回内容建议只含
cpu_usage_percent、mem_used_mb、goroutines_count这三类轻量指标,避免调用runtime.ReadMemStats频繁触发 GC 扫描
获取 CPU 和内存数据时的典型错误
直接调用 runtime.NumCPU() 或 runtime.GOMAXPROCS(0) 只返回配置值,不是实时负载;而用 syscall.Sysinfo 在 Windows 下不可用——跨平台必须分条件处理。
- Linux/macOS:用
github.com/shirou/gopsutil/v3/cpu+github.com/shirou/gopsutil/v3/mem,但注意CPU.Percent需要两次采样间隔,首次调用返回 0 - Windows:
gopsutil的cpu.Times在某些版本会 panic,应加 recover 包裹 - 内存计算别直接用
Mem.VirtualMemory().Used,它包含缓存,线上更关注Mem.Available或Mem.Used - Mem.Cached - 所有系统调用必须设超时(如 context.WithTimeout),防止监控接口卡死整个 HTTP server
为什么不能把监控路由放在默认控制器里
Beego 的 Router 是全局注册,一旦写成 beego.Router("/status", &controllers.MainController{}),就等于把所有 HTTP 方法(包括 POST/PUT)都映射过去,而 MainController 的 Get 方法可能没做鉴权,攻击者能直接 curl 就拿到指标。
- 务必单独建
MetricController,且Get方法开头强制校验f.Ctx.Input.Header("X-Api-Key") - 避免使用
f.Redirect或f.StopRun以外的跳转逻辑,防止重定向泄露内部路径 - 不要在该接口里调用
orm.Debug = true或打印完整 error stack,日志中也需脱敏(如隐藏/proc路径) - 如果部署在 Kubernetes,可配合
livenessProbe复用该接口,但响应体必须精简(
真正难的不是读取 CPU 百分比,而是让这个接口在高并发下不拖慢主业务、不被滥用、不成为信息泄露入口。每行采集代码背后,都要想清楚它在 prod 环境跑 1000 次/秒时的表现。


















