mirror of
https://gh-proxy.org/https://github.com/klinsmaya/new-api.git
synced 2026-11-08 01:17:09 +08:00
* fix(middleware): 过载哨兵改用容器口径并加入连续性与新鲜度判定 checkSystemPerformance 依赖 common.SystemStatus,而 updateSystemStatus 用 cpu.Percent(0,false) 与 mem.VirtualMemory() 采样,两者都是宿主机口径 (/proc/stat、/proc/meminfo),不具备 cgroup 感知。容器化部署下度量的是 宿主机而非本进程:容器配额 2 核时 /proc/stat 仍暴露宿主机全部核心,同节点 其它工作负载会把该值推高,导致正常 relay 流量被 503 system_cpu_overloaded 拒绝。同时该判定对单次采样即时生效,瞬时尖峰即可熔断。 本次调整: - 新增 common/container_usage.go:优先按容器 cgroup 配额计算自身 CPU 与内存 占用(v2 cpu.max/cpu.stat/memory.max/memory.current,兼容 v1),容器口径 不可用时回退宿主机口径; - 过载判定要求连续 3 次采样(约 15 秒)超阈值,任一采样回落即恢复; - 采样超过 30 秒未刷新时哨兵不再熔断,避免状态陈旧误伤流量; - 中间件改为消费采样结果中的过载标记,错误码与 503 语义不变。 验证:go build ./...、go test ./common/... ./middleware/... 通过;新增 容器口径与判定行为单测。 * fix(monitor): correct container CPU and memory overload detection --------- Co-authored-by: seefs001 <[email protected]>
50 lines
1.4 KiB
Go
50 lines
1.4 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/QuantumNous/new-api/common"
|
|
"github.com/QuantumNous/new-api/relaykit/types"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// SystemPerformanceCheck 检查系统性能中间件
|
|
func SystemPerformanceCheck() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// 仅检查 Relay 接口 (/v1, /v1beta 等)
|
|
// 这里简单判断路径前缀,可以根据实际路由调整
|
|
path := c.Request.URL.Path
|
|
if strings.HasPrefix(path, "/v1/messages") {
|
|
if err := checkSystemPerformance(); err != nil {
|
|
c.JSON(err.StatusCode, gin.H{
|
|
"error": err.ToClaudeError(),
|
|
})
|
|
c.Abort()
|
|
return
|
|
}
|
|
} else {
|
|
if err := checkSystemPerformance(); err != nil {
|
|
c.JSON(err.StatusCode, gin.H{
|
|
"error": err.ToOpenAIError(),
|
|
})
|
|
c.Abort()
|
|
return
|
|
}
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// checkSystemPerformance 检查系统性能是否超过阈值
|
|
func checkSystemPerformance() *types.NewAPIError {
|
|
// 过载标记在采样侧完成:CPU / 内存按容器 cgroup 配额计算,并要求连续多次
|
|
// 超阈值;判定时再按当前阈值复核,并忽略过期采样。
|
|
overload := common.CheckSystemOverload(common.GetSystemStatus(), common.GetPerformanceMonitorConfig(), time.Now())
|
|
if overload == nil {
|
|
return nil
|
|
}
|
|
return types.NewErrorWithStatusCode(overload, types.ErrorCode(overload.Code), http.StatusServiceUnavailable)
|
|
}
|