扫描分析快照¶
扫描分析页面原先在每次请求时聚合全部 observation。该行为在 Elasticsearch 成为扫描事实源后, 会因高基数 composite aggregation 而明显变慢。现在可以将统计改为后台快照:扫描事实仅保留在 Elasticsearch,分析接口只读取 PostgreSQL 中的紧凑统计事实。
升级步骤¶
升级后的默认配置是 mode = "realtime",接口行为不变。请按以下顺序切换:
- 部署服务,让数据库初始化新增
analytics_*表。 - 在管理员运行时设置中将模式改为
shadow。后台 worker 会自动补偿升级前所有已成功的 IP 扫描执行; 新版本服务会在 execution 成功的同一事务中写入 outbox。 - 正常升级无需手动全量重建。仅在需要重新计算已完成的统计事实时,在维护窗口运行:
cargo run --release -- --config /etc/network-mapping/config.toml \
--rebuild-analytics-snapshots
命令只替换 analytics_* 紧凑统计事实,不会删除或修改扫描 observation、任务或资产数据。
已有可读水位会保留;失败会报告错误,不会把尚未完成的队列报告为重建成功。
4. 使用原有 /api/analysis/distribution 和 /api/analysis/discovery-heatmap 对典型用户、扫描器、
任务来源和时间范围做结果核验。
5. 确认首次回填水位已生成后,在运行时设置中改为 snapshot。首次快照尚未完整时接口返回 503,
不会静默回退到可能很慢的实时 ES 聚合。
配置¶
[analytics_snapshot]
# realtime: 保持旧实时查询;shadow: 后台构建、接口仍实时;snapshot: 接口只读快照。
mode = "realtime"
# 历史补偿检查及下一轮固定回填范围的建立周期;不是队列消费休眠时间。
interval_minutes = 30
TOML 仅首次初始化 runtime_configuration。数据库已有 analytics_snapshot 配置后,修改 TOML
并重启不会覆盖运行时设置。以管理员接口 GET /api/config/runtime/analytics_snapshot 返回的
data.document 和 data.revision 为准。
worker 每批最多处理 100 个 execution,有积压时只让出 1 秒后继续,空闲时每 5 秒检查新任务及重试。 历史全量补偿不再发生在每次领取任务时。失败项延迟五分钟重试,ES 读取、统计写入及事务错误均进入 同一重试路径;单次处理限时 30 分钟,进程中断遗留的领取记录 60 分钟后可重新领取。
首次启动固定当前待处理执行集合到 analytics_snapshot_build_execution。之后新增执行不会扩张
这一集合。每个执行的统计事实、队列完成标记和集合移除在同一事务中提交;集合清空时发布水位。
下一轮集合的建立及处理不删除已有水位。空数据库也会生成有效空快照。历史失败任务仍会阻止其所属
回填范围完成,系统不会通过跳过失败来伪造完整性。
领取使用 FOR UPDATE SKIP LOCKED,写入前校验领取时间并加锁,防止重试或重新上传后旧计算覆盖
新任务。统计事实每 1,000 行批量写入;写入失败整笔事务回滚,保留旧事实。ES 超时、失败分片、分页
游标异常或读取观察数少于执行记录的计数时,不发布该执行的统计结果。
进度与排错¶
管理员接口 GET /api/config/runtime/analytics_snapshot 除配置外返回 progress:
data_as_of:最近完成的回填范围水位,首次尚未完成时为空。build_started_at/build_completed_at:当前固定范围的建立和完成时间。remaining:当前范围剩余执行数,后续新任务不计入。pending/running/completed/retrying:整个统计队列状态。failed_execution_id/last_error:最近一个未完成失败任务及原因。
首次快照不可读时,分析接口对管理员返回相同进度,页面显示剩余数量及最近失败原因。 普通用户只收到通用回填提示,不暴露其他用户的任务或错误。 水位 SQL 出错与回填未完成使用不同错误码,不再把数据库错误伪装成未回填。
升级时部署更新后的 source/database/init.sql,服务初始化会幂等创建两张回填范围表。
无须清空已有统计表或重新运行全量重建;开启 shadow / snapshot 后自动接续原队列。
统计口径¶
- 服务/端口分布按执行内的代表性端点计数;同一 endpoint 的首次 observation 决定其 30 分钟窗口。
- 服务名以
LOWER(BTRIM(service))归一化;空服务名不进入服务分布。 - 发现 IP 按执行和上海自然日记录,并在接口查询时按 IP 去重。
- 统计响应的
meta.data_as_of表示最近完成的固定执行集合的建立时间,是后台处理进度水位, 不是 ES refresh 时间或任意 observation 时间范围的完整性保证。统计表按执行原子更新,可能已含 水位之后处理完成的执行;它不是按全局版本冻结的历史数据库视图。
Elasticsearch 权威模式会按 execution_id 读取 observation 文档。旧索引缺少该字段或必要元数据时,
应先完成现有的扫描事实迁移,再执行快照重建。