Files
pig-farm-controller/design/exceeding-threshold-alarm/index.md

6.9 KiB

需求

实现采集数据超过阈值报警

issue

实现采集数据超过阈值报警

方案

  1. 架构核心: 新增一个 告警领域服务,作为告警系统的核心大脑,负责告警事件的生命周期管理。
  2. 任务分离:
    • 新增 阈值告警任务 (分为区域主控和普通设备两种),仅负责检测数据并将结果报告给领域服务。
    • 新增 告警通知发送任务,作为一个独立的定时任务,负责调用领域服务,获取并发送所有待处理的通知。
  3. 计划调度:
    • 修改现有 "定时全量数据采集" 计划, 更名为 "周期性系统健康检查",并将 阈值告警任务 加入其中。
    • 新增一个独立的 "告警通知发送" 计划,用于定时执行 告警通知发送任务
  4. 数据与接口:
    • 新增独立的告警记录表(建议采用“活跃告警表 + 历史告警超表”的模式)。
    • 新增相应的告警配置管理接口。

方案细节

架构与职责划分

  1. 告警领域服务 (internal/domain/alarm/) - 管理器

    • 职责: 作为告警系统的核心大脑,负责处理告警事件的完整生命周期。
    • 功能:
      • 接收来自检测任务的状态报告。
      • 根据报告和现有告警记录,决策是创建新告警、更新为已解决、还是忽略。
      • 管理“手动忽略” (Ignored) 状态和忽略到期时间 (ignored_until)。
      • 实现可配置的“重复通知”策略(re_notification_interval),决定何时对持续存在的告警再次发送通知。
      • 提供接口供 告警通知发送任务 调用,以获取所有待处理的通知。
  2. 阈值告警任务 (internal/domain/task/) - 检测器

    • 职责: 职责纯粹,仅负责执行检测并将结果报告给告警领域服务。
    • 逻辑: 获取传感器数据 -> 与阈值比对 -> 调用 告警领域服务.ReportStatus()
    • 无状态: 任务本身不关心告警是否已存在或被忽略。
  3. 告警通知发送任务 (internal/domain/task/) - 发送器

    • 职责: 作为一个独立的定时任务,解耦通知发送与告警检测。
    • 逻辑: 调用 告警领域服务.GetAndProcessPendingNotifications() -> 获取待发送通知列表 -> 调用 通知领域服务 逐一发送。
    • 优势: 统一管理定时任务,实现资源控制,提高系统稳定性和可扩展性。

计划与任务调度

  1. "周期性系统健康检查" 计划

    • 任务顺序: 此计划中的任务必须严格按顺序执行,确保依赖关系正确。
      1. 全量数据采集任务 (ExecutionOrder: 1): 必须是第一个执行的任务,为后续的告警检测提供最新的数据基础。
      2. 阈值告警任务 (ExecutionOrder: 2, 3...): 在全量采集完成后执行。
  2. "告警通知发送" 计划

    • 内容: 包含一个独立的 告警通知发送任务
    • 调度: 可配置独立的执行频率(如每分钟一次),与健康检查计划解耦。

阈值告警任务 (具体定义)

  1. 任务类型: 增加两个阈值告警任务类型,分别对应 区域主控普通设备 告警。
  2. 参数结构:
    • 通用参数: 任务参数将包含 Value (阈值) 和 Operator (操作符,如 ><) 字段。通过组合两个任务,可实现范围告警。
    • 普通设备任务: 配置包含 DeviceID
    • 区域主控任务: 配置包含 AreaControllerID, SensorType, 以及一个 ExcludeDeviceIDs (需要排除的设备ID列表)。

告警事件与生命周期

  1. 告警事件定义:

    • 区分 告警规则 (配置的策略) 和 告警事件 (规则被具体设备触发的实例)。
    • 区域主控下不同设备触发的告警,即使基于同一规则,也应视为独立的 告警事件,以便于精确追溯和独立操作。
  2. 生命周期管理:

    • 自动闭环: 当阈值告警任务报告数据恢复正常时,告警领域服务会自动将对应的 Active 告警事件状态更新为 Resolved
    • 手动忽略 (Snooze): 用户可通过接口将告警事件状态置为 Ignored 并设置 ignored_until。在此期间,即使数据持续异常,也不会发送通知。忽略到期后若问题仍存在,告警将重新变为 Active 并发送通知。
    • 持续告警与重复通知: 对持续未解决的 Active 告警,只保留一条记录。告警领域服务会根据 re_notification_interval 配置的重复通知间隔,决定是否需要再次发送通知。

数据库设计考量

  1. 冷热分离方案 (推荐):

    • active_alarms (活跃告警表):
      • 类型: 标准 PostgreSQL 表。
      • 内容: 只存放 ActiveIgnored 状态的告警。
      • 优势: 保证高频读写的性能,避免在被压缩的数据上执行更新操作。
    • historical_alarms (历史告警表):
      • 类型: 改造为 TimescaleDB 超表
      • 内容: 存放 Resolved 状态的告警。当告警在 active_alarms 中被解决后,记录将移至此表。
      • 优势: 适合存储海量历史数据,便于分析、统计,并可利用 TimescaleDB 的压缩和数据生命周期管理功能。
  2. 表结构字段:

    • status: 枚举类型,包含 Active, Resolved, Ignored
    • ignored_until: timestamp 类型,记录忽略截止时间。
    • last_notified_at: timestamp 类型,记录上次发送通知的时间。

阈值告警服务 (应用服务层)

  1. 服务职责: 提供一个应用服务,负责管理阈值告警 配置 的增删改查。
  2. 排除列表计算与联动:
    • 删除独立规则后归属: 当一个普通设备的独立告警规则被删除时,它将自动从其所属区域主控的 ExcludeDeviceIDs 列表中移除,从而回归到区域统一告警策略的管理之下。
    • 设备生命周期管理: 在对设备进行修改(特别是更换区域主控)或删除时,以及在删除区域主控时,必须同步更新相关的 ExcludeDeviceIDs 列表,以保证数据一致性。
    • 实现: DeviceService 中负责处理设备更新和删除的方法,以及处理区域主控删除的方法,需要调用阈值告警服务提供的刷新接口。

阈值告警控制器

  1. 独立接口: 提供两组独立的 Web 接口,分别用于管理区域主控和普通设备的阈值告警配置。
    • 区域主控告警配置接口: /api/v1/alarm/region-config
    • 普通设备告警配置接口: /api/v1/alarm/device-config
  2. 接口职责: 接口负责接收前端请求,调用应用服务层的阈值告警服务来完成实际的业务逻辑。