部署方式
完整 Docker 方案
CPA 版本
v7.1.19
CPA-Manager 版本
v1.3.3
问题描述
请求监控一直加载不出来,然后页面报超时,而且CPU和内存一直不释放,导致我的1核1G的小VPS卡死。
我按gpt给的方式改小了数据拉取的数量,但是结果又不准了,因为没完全统计。
我让gpt5.5看了一下,他说这么优化,您看下是否合理:
查了源码,结论很明确:请求监控卡,不是 SQLite 单点问题,而是 CPAM 的监控页设计成了“全量拉取 + 前端全量聚合 + 默认 5 秒刷新”。
核心链路是这样:
后端 /v0/management/usage 一次性从 SQLite 取最近 N 条事件
在 server.go (line 892):
events, err := s.store.RecentEvents(r.Context(), s.cfg.QueryLimit)
writeJSON(w, http.StatusOK, usage.BuildPayload(events))
而 QueryLimit 默认是 50000,在 config.go (line 86)。
SQLite 查询不是分页,也不是按时间范围查,是直接:
from usage_events
order by timestamp_ms desc, id desc
limit ?
在 store.go (line 758)。
原始索引只有 timestamp_ms,没有 (timestamp_ms desc, id desc) 组合索引,所以数据多时排序会更吃力。
后端 BuildPayload 把每条请求都塞进 apis -> models -> details 里返回,不是只返回汇总。
看 event.go (line 186)。
前端收到后,又把这个大 JSON 拆回明细数组。
在 usage.ts (line 304) 的 collectUsageDetailsWithEndpoint()。
然后前端对同一批 rows 重复扫描、排序、分组很多次。
在 useMonitoringData.ts (line 1909) 到 1947,依次算 summary、timeline、hourly、model、channel、failure、taskBuckets 等。
页面本体又继续算 accountRows、apiKeyRows、realtimeLogRows,在 MonitoringCenterPage.tsx (line 2241)。
最坑的是默认自动刷新是 5000ms。
在 accountOverviewState.ts (line 61)。
而 useInterval.ts (line 7) 只是普通 setInterval,没有“上一轮没结束就别开下一轮”的锁。也就是说,一旦一次刷新超过 5 秒,就会叠请求。
所以你那边会卡的真实原因是:
打开请求监控后,CPAM 每 5 秒可能拉一次大 usage 数据 + auth-files + openai-compatibility,然后前端和后端都在重复处理大量记录;1C/1G 机器一旦某轮超过 5 秒,刷新会重叠,CPU、SQLite、Docker 网络、WARP、CPA 管理接口一起被拖慢。
你之前看到 sub2api 也卡,大概率不是 CPAM 直接请求了 sub2api,而是同机资源被打满了:CPU load 飙高、Postgres/Redis/Docker DNS/WARP 都在同一台小机器上,旁边服务也跟着超时。
我们现在把 USAGE_QUERY_LIMIT=1000、pollIntervalMs=5000、batchSize=25、加组合索引,能止血。
但源码层面的根治是:
后端改成分页 + 服务端聚合,前端不要一次拿全量 details,也不要每 5 秒重复拉 auth-files。
优先级最高的改法是这三个:
/v0/management/usage/summary:SQLite 直接 count/sum/group by 返回统计。
/v0/management/usage/events?page&pageSize:明细分页。
自动刷新加 in-flight 锁:上一轮没结束,下一轮跳过。
这才是根治。现在这个请求监控页,数据一多必卡。
复现步骤
点击请求监控
关键配置
cpa:
image: eceasy/cli-proxy-api:latest
container_name: cpa
restart: unless-stopped
mem_limit: 384m
environment:
HTTP_PROXY: http://warp:1080
HTTPS_PROXY: http://warp:1080
ALL_PROXY: socks5h://warp:1080
http_proxy: http://warp:1080
https_proxy: http://warp:1080
all_proxy: socks5h://warp:1080
NO_PROXY: localhost,127.0.0.1,nginx-proxy,warp,cpa,cpa-manager,cpa-router,postgres,redis,sub2api
no_proxy: localhost,127.0.0.1,nginx-proxy,warp,cpa,cpa-manager,cpa-router,postgres,redis,sub2api
volumes:
- ./cpa/config.yaml:/CLIProxyAPI/config.yaml
- ./cpa/auth:/root/.cli-proxy-api
- ./cpa/logs:/CLIProxyAPI/logs
depends_on:
warp:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "env -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY -u http_proxy -u https_proxy -u all_proxy wget -q -O /dev/null http://127.0.0.1:8317/healthz"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
networks:
- net
cpa-manager:
image: seakee/cpa-manager:latest
container_name: cpa-manager
restart: unless-stopped
mem_limit: 256m
volumes:
- ./cpa-manager:/data
environment:
HTTP_ADDR: 0.0.0.0:18317
USAGE_COLLECTOR_MODE: auto
# Limit /v0/management/usage payload on 1C/1G hosts.
# Without this, CPAM defaults to 50000 and the monitoring page can time out.
USAGE_QUERY_LIMIT: 1000
USAGE_BATCH_SIZE: 25
USAGE_POLL_INTERVAL_MS: 5000
HTTP_PROXY: http://warp:1080
HTTPS_PROXY: http://warp:1080
ALL_PROXY: socks5h://warp:1080
http_proxy: http://warp:1080
https_proxy: http://warp:1080
all_proxy: socks5h://warp:1080
NO_PROXY: localhost,127.0.0.1,nginx-proxy,warp,cpa,cpa-manager,cpa-router,postgres,redis,sub2api
no_proxy: localhost,127.0.0.1,nginx-proxy,warp,cpa,cpa-manager,cpa-router,postgres,redis,sub2api
depends_on:
cpa:
condition: service_healthy
warp:
condition: service_healthy
networks:
- net
/status 返回内容
日志
截图
No response
检查清单
部署方式
完整 Docker 方案
CPA 版本
v7.1.19
CPA-Manager 版本
v1.3.3
问题描述
请求监控一直加载不出来,然后页面报超时,而且CPU和内存一直不释放,导致我的1核1G的小VPS卡死。
我按gpt给的方式改小了数据拉取的数量,但是结果又不准了,因为没完全统计。
我让gpt5.5看了一下,他说这么优化,您看下是否合理:
查了源码,结论很明确:请求监控卡,不是 SQLite 单点问题,而是 CPAM 的监控页设计成了“全量拉取 + 前端全量聚合 + 默认 5 秒刷新”。
核心链路是这样:
后端 /v0/management/usage 一次性从 SQLite 取最近 N 条事件
在 server.go (line 892):
events, err := s.store.RecentEvents(r.Context(), s.cfg.QueryLimit)
writeJSON(w, http.StatusOK, usage.BuildPayload(events))
而 QueryLimit 默认是 50000,在 config.go (line 86)。
SQLite 查询不是分页,也不是按时间范围查,是直接:
from usage_events
order by timestamp_ms desc, id desc
limit ?
在 store.go (line 758)。
原始索引只有 timestamp_ms,没有 (timestamp_ms desc, id desc) 组合索引,所以数据多时排序会更吃力。
后端 BuildPayload 把每条请求都塞进 apis -> models -> details 里返回,不是只返回汇总。
看 event.go (line 186)。
前端收到后,又把这个大 JSON 拆回明细数组。
在 usage.ts (line 304) 的 collectUsageDetailsWithEndpoint()。
然后前端对同一批 rows 重复扫描、排序、分组很多次。
在 useMonitoringData.ts (line 1909) 到 1947,依次算 summary、timeline、hourly、model、channel、failure、taskBuckets 等。
页面本体又继续算 accountRows、apiKeyRows、realtimeLogRows,在 MonitoringCenterPage.tsx (line 2241)。
最坑的是默认自动刷新是 5000ms。
在 accountOverviewState.ts (line 61)。
而 useInterval.ts (line 7) 只是普通 setInterval,没有“上一轮没结束就别开下一轮”的锁。也就是说,一旦一次刷新超过 5 秒,就会叠请求。
所以你那边会卡的真实原因是:
打开请求监控后,CPAM 每 5 秒可能拉一次大 usage 数据 + auth-files + openai-compatibility,然后前端和后端都在重复处理大量记录;1C/1G 机器一旦某轮超过 5 秒,刷新会重叠,CPU、SQLite、Docker 网络、WARP、CPA 管理接口一起被拖慢。
你之前看到 sub2api 也卡,大概率不是 CPAM 直接请求了 sub2api,而是同机资源被打满了:CPU load 飙高、Postgres/Redis/Docker DNS/WARP 都在同一台小机器上,旁边服务也跟着超时。
我们现在把 USAGE_QUERY_LIMIT=1000、pollIntervalMs=5000、batchSize=25、加组合索引,能止血。
但源码层面的根治是:
后端改成分页 + 服务端聚合,前端不要一次拿全量 details,也不要每 5 秒重复拉 auth-files。
优先级最高的改法是这三个:
/v0/management/usage/summary:SQLite 直接 count/sum/group by 返回统计。
/v0/management/usage/events?page&pageSize:明细分页。
自动刷新加 in-flight 锁:上一轮没结束,下一轮跳过。
这才是根治。现在这个请求监控页,数据一多必卡。
复现步骤
点击请求监控
关键配置
/status 返回内容
日志
截图
No response
检查清单