Skip to content

性能优化:Candidates、Overview、statusView 与 Monitoring 瓶颈 #18

Description

@Kherrisan

背景

当前扫描相关页面存在明显性能问题,慢点主要集中在 Candidates、Overview、statusView 和实时 Monitoring。根据浏览器抓包与运行时观察,瓶颈主要在 Node/PostgreSQL 侧的数据加载与聚合方式,而不是网络传输或 Cloudflare。

主要瓶颈

1. Candidates 没有在数据库分页

文件:packages/server/src/services/scan/api/candidate-records.ts:568

当前实现会先加载这个 job 的:

  • 所有 candidate
  • 所有 analysis result
  • 所有 verification result
  • 所有 triage result

然后在 Node 中做过滤、排序,最后才 slice() 出 20 条。数据量越大,响应越慢。

观测耗时:约 102 秒

2. Overview 查询了所有 task 的完整 output

文件:packages/server/src/services/scan/home-overview.ts:105

首页汇总会加载 organization 下所有 job 的 task,并且选择了:

  • output: tasks.output

首页统计基本不需要完整 task output。大量 JSON 从 PostgreSQL 传到 Node,是 scan.homeOverview 耗时约 17 秒的重要原因。

3. statusView 每次重新构造整个 job 状态

文件:packages/server/src/services/scan.ts:4628

当前实现每次都会同时加载所有 candidate 和三类结果,还会:

  • 构造完整 pipeline context
  • 获取每个 stage concurrency
  • 查询 BullMQ queue counts
  • 在 Node 中构建多个 Map 和聚合结果

观测耗时:单次刷新约 63.5 秒

4. Monitoring 重复完整扫描 JSONL

每个打开的网页都会独立创建 WebSocket,并且每 1.3 秒完整读取所有运行中 task 的 JSONL。首个 Monitoring 样本约 9.6 秒,同时持续占用 Node CPU。

5. 请求已经开始堆积

HAR 中出现:

  • scan.candidates101.97 秒
  • scan.terminalTasks99.84 秒
  • scan.one95.70 秒

后两个响应体只有约 1.8 KB5.8 KB,说明慢点不是网络传输,而是请求在 Node/PostgreSQL 中排队。

运行时证据

测试期间:

  • Vulseek Node CPU:103%
  • PostgreSQL CPU:89.5%
  • Node RSS:约 1.4 GB -> 2.08 GB
  • 容器内存:约 23.4 GB -> 24.4 GB

Cloudflare 不是主要瓶颈。HAR 中绝大部分时间都耗在等待服务端响应,实际接收响应只需很短时间。

Files 和 Projects 相对正常,说明慢点集中在扫描汇总、任务状态、Candidates 和实时 Monitoring。

建议优化方向

  • Candidates 改为数据库侧分页、过滤、排序,避免全量加载后在 Node 中 slice()
  • Overview 查询移除不必要的 tasks.output 读取,仅选择首页统计真正需要的字段
  • statusView 拆分为更细粒度的数据来源,避免每次全量重建 job 状态
  • 对 queue counts、stage concurrency、聚合结果做缓存或快照化
  • Monitoring 改成增量读取、游标式追踪或共享订阅,避免每个 WebSocket 周期性完整扫描 JSONL
  • 排查是否存在少数热点 SQL、缺失索引、无界 IN (...) 或 JSON 反序列化放大问题

验收标准

  • scan.candidates 在大 job 下不再进行 Node 侧全量分页
  • scan.homeOverview 不再加载首页统计不需要的完整 task output JSON
  • scan.statusView 响应时间显著下降,并避免重复构造全量 job 聚合状态
  • Monitoring 不再为每个前端连接重复完整扫描运行中 task 的 JSONL
  • 在相同测试数据下,页面请求不再出现接近 100 秒的排队等待

证据文件

  • /tmp/vulseek-perf/initial.har
  • /tmp/vulseek-perf/job-tabs.har

agent-browser 会话已关闭。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions