SpringBoot中实现告警判定算法-位报警与模拟量阈值-技术详解
SpringBoot中实现告警判定算法-位报警与模拟量阈值-技术详解适用场景IoT / 工业监控 / 设备告警 / 任何周期采样 → 判定是否告警 → 落库 → 恢复的系统。目录为什么告警判定要分两类第一类位报警布尔量—— 边沿检测第二类模拟量阈值 —— 双阈值迟滞回差两类算法对比告警生命周期与去重两类共用告警分级映射本项目落地实现解析通用示例代码设计要点与踩坑清单注博客https://blog.csdn.net/badao_liumang_qizhi一、为什么告警判定要分两类设备采集回来的信号本质上分两种物理类型判定方式完全不同信号类型例子取值判定方式开关量 / 布尔量位急停、水泵故障、风机故障、缺水故障true/false1 个 bit边沿检测状态跳变才动作模拟量 / 连续量粉尘浓度 TSP、压力、流量、电流连续数值阈值比较越过阈值才动作且要防抖动如果对这两类用同一种判定方式会出问题布尔量若只要为 true 就插一条告警2 秒一采会瞬间刷出成千上万条重复记录。模拟量若只要值 阈值就告警、值 阈值就恢复当数值在阈值附近抖动时会疯狂地告警—恢复—告警—恢复告警抖动 / flapping。因此需要两套算法位报警用边沿检测去重模拟量用双阈值迟滞防抖。二、第一类位报警布尔量—— 边沿检测2.1 电平 vs 边沿电平Level信号当前的状态值true/false。边沿Edge信号状态发生的跳变。上升沿false → true正常→故障此刻应生成告警。下降沿true → false故障→正常此刻应恢复告警。保持状态未变什么都不做。只在跳变时动作就天然实现了去重——一次故障从发生到恢复只产生一条告警记录一次上升沿开、一次下降沿关。2.2 算法本质本次值与上次值对比边沿检测需要保存上一次的状态。每轮采集把本次值与上次值对比if (!oldStatus newStatus) - 上升沿 - 生成告警 if (oldStatus !newStatus) - 下降沿 - 恢复告警 否则 - 无动作状态存哪里本项目把上一轮整包 PLC 数据缓存在 Redis10s 过期下一轮取出来做对比既做了边沿检测的上次状态源又避免了额外维护状态表。2.3 空值处理传感器/通信可能读到 null。判定前要归一化本项目把 null 视为正常 false避免 NPE 且语义安全oldStatusoldStatusnull?false:oldStatus;newStatusnewStatusnull?false:newStatus;三、第二类模拟量阈值 —— 双阈值迟滞回差3.1 单阈值的抖动问题若只用一个阈值T值 T告警、值 T恢复。当实际值在T附近小幅波动如 T150值在 149~151 抖动时会产生大量告警→恢复→告警→恢复即告警抖动flapping既刷屏又无意义。3.2 迟滞Hysteresis/ 回差带解决办法是用两个阈值构成一个回差带报警阈值alarmThreshold高值 alarmThreshold才触发告警。预警/恢复阈值warnThreshold低值 warnThreshold才恢复告警。两者之间的区间warnThreshold 值 alarmThreshold是死区维持当前状态不变。浓度 ▲ │ ┌─────────── 告警区 alarmThreshold 触发 alarmThreshold ─┤ │ │ 死区维持现状不翻转 warnThreshold ──┤ │ └─────────── 恢复区 warnThreshold 才恢复 └───────────────────────────▶ 时间这样值必须先冲高越过报警线才告警之后必须回落到预警线以下才恢复——中间的小抖动被死区吸收告警不再来回翻转。这正是工业上常见的施密特触发器Schmitt Trigger思想。3.3 采样频率控制模拟量还常配合采样降频即使采集任务 2s 一轮TSP 可以只每 N 秒采样并入库一次比如tsp.sample.interval 默认 10s减少历史数据量与写入压力。四、两类算法对比维度位报警边沿检测模拟量阈值双阈值迟滞输入布尔量1 bit连续数值触发条件上升沿 false→true值 alarmThreshold恢复条件下降沿 true→false值 warnThreshold去重手段依赖上次状态对比依赖回差带 未闭合记录判断防抖手段天然去重跳变才动作回差带死区吸收抖动状态源上次采集值本项目存 Redis当前值 数据库未恢复记录典型信号急停、水泵/风机故障、缺水粉尘浓度、压力、温度五、告警生命周期与去重两类共用不论哪类算法产生的告警都落成一条有生命周期的记录start_time ────(持续中stop_time NULL)────▶ stop_time total_time stop - start handle_status: 0待确认 → 1已确认 / 2超时未确认 → 3已处理5.1 触发开告警生成一条新记录设置设备/料棚、告警名、开始时间、等级、处理状态待确认、备注。5.2 恢复关告警找到该设备该告警未闭合的记录写入stop_time并可计算持续时长。5.3 去重的两种实现位报警靠上次状态对比。只有上升沿才插入天然不会重复插。模拟量额外用数据库是否存在未恢复记录兜底去重selectUnfinishedAlarm(...) ! null。这样即使进程重启内存态丢失或多实例并发也不会对同一持续告警重复插入。经验以数据库未闭合记录作为状态源比纯内存状态更健壮重启不丢、多实例安全是模拟量告警推荐的去重方式。六、告警分级映射把告警名称 → 严重等级抽成映射表新增告警只改配置、不改判定逻辑等级1 提示 / 2 预警 / 3 严重 / 4 致命。未命中默认按严重处理保证漏配也不漏报。AlarmConstants的映射示例急停、总故障致命(4)各类故障严重(3)低流量、TSP 超标预警(2)。七、项目落地实现解析7.1 位报警checkAlarmStatus边沿检测采集任务每轮取出上一轮缓存的oldData与本轮newData对 11 类布尔故障逐一做边沿检测privatevoidcheckAlarmStatus(BusDevicedevice,LongshedId,StringalarmName,BooleanoldStatus,BooleannewStatus,Datenow){LongdeviceIddevice.getId();oldStatusoldStatusnull?false:oldStatus;// 空值归一化newStatusnewStatusnull?false:newStatus;// 上升沿正常→报警生成新告警if(!oldStatusnewStatus){BusDeviceAlarmalarmnewBusDeviceAlarm();alarm.setShedId(shedId);alarm.setDeviceId(deviceId);alarm.setAlarmName(alarmName);alarm.setStartTime(now);alarm.setAlarmLevel(AlarmConstants.getAlarmLevel(alarmName));// 名称→等级alarm.setHandleStatus(AlarmConstants.HANDLE_STATUS_PENDING);alarm.setRemark(PLC触发alarmName设备device.getDeviceName()PLCdevice.getPlcAddress());busDeviceAlarmService.insertBusDeviceAlarm(alarm);}// 下降沿报警→正常恢复告警if(oldStatus!newStatus){busDeviceAlarmService.updateAlarmStopTime(deviceId,alarmName,now);}}调度侧对多类故障批量判定急停、风机/水泵故障、摇摆/仰俯/超限位/编码器/缺水故障、总故障等checkAlarmStatus(device,shedId,急停,oldData.getEStop(),newData.getEStop(),now);checkAlarmStatus(device,shedId,摇摆故障,oldData.getSwingFault(),newData.getSwingFault(),now);// ... 其余同理上次状态从哪来——上一轮整包数据缓存在 RedisStringplcCacheKeyConstants.PLC_KEYdevice.getPlcAddress();PlcDataoldPlcDataredisCache.getCacheObject(plcCacheKey);// 取上次redisCache.setCacheObject(plcCacheKey,plcData,10,TimeUnit.SECONDS);// 存本次detectAndUploadAlarm(device,oldPlcData,plcData);// 边沿检测首次采集oldData null时直接 return不做判定无历史可比。7.2 模拟量阈值tspThresholdCheck双阈值迟滞 DB 去重privatevoidtspThresholdCheck(BusDevicedevice,doubletspValue,Datenow){LongdeviceIddevice.getId();LongshedIddevice.getShedId();// 阈值配置设备级优先料棚级兜底BusTspThresholdConfigconfigtspThresholdConfigService.selectEnableConfigByDeviceId(deviceId,shedId);if(confignull)return;// 无配置不检测doublealarmThresholdconfig.getAlarmThreshold().doubleValue();// 报警阈值(高)doublewarnThresholdconfig.getWarnThreshold().doubleValue();// 恢复阈值(低)// DB 去重以未恢复记录为准重启/多实例不重复插booleanisCurrentlyAlarmingbusDeviceAlarmService.selectUnfinishedAlarm(deviceId,TSP粉尘浓度超标)!null;if(tspValuealarmThreshold){if(!isCurrentlyAlarming){// 触发越过高阈值 且 当前无未恢复记录BusDeviceAlarmalarmnewBusDeviceAlarm();alarm.setShedId(shedId);alarm.setDeviceId(deviceId);alarm.setAlarmName(TSP粉尘浓度超标);alarm.setStartTime(now);alarm.setAlarmLevel(AlarmConstants.getAlarmLevel(TSP粉尘浓度超标));alarm.setHandleStatus(AlarmConstants.HANDLE_STATUS_PENDING);alarm.setRemark(TSP浓度tspValueμg/m³报警阈值alarmThreshold...);busDeviceAlarmService.insertBusDeviceAlarm(alarm);}}elseif(tspValuewarnThreshold){// 恢复回落到低阈值以下if(isCurrentlyAlarming){busDeviceAlarmService.updateAlarmStopTime(deviceId,TSP粉尘浓度超标,now);}}// warnThreshold tspValue alarmThreshold 落在死区维持现状不动作}采样降频tsp.sample.interval默认 10s与开关tsp.sample.enabled由sampleAndCheckTsp控制超标检查前还会异步写一条 TSP 历史记录。7.3 阈值配置的分级兜底selectEnableConfigByDeviceId(deviceId, shedId)优先取设备级阈值配置没有则回退到料棚级配置。这让运营能整棚统一配 个别设备特殊配是配置驱动 就近覆盖的典型设计。八、通用示例代码8.1 通用边沿检测器位报警publicclassEdgeAlarmDetector{publicenumEdge{RISING,FALLING,NONE}/** 对比上次/本次布尔状态返回边沿类型 */publicstaticEdgedetect(BooleanoldStatus,BooleannewStatus){booleanooldStatus!nulloldStatus;booleannnewStatus!nullnewStatus;if(!on)returnEdge.RISING;// 触发if(o!n)returnEdge.FALLING;// 恢复returnEdge.NONE;}}// 使用switch(EdgeAlarmDetector.detect(old,now)){caseRISING:alarmService.open(deviceId,name);break;caseFALLING:alarmService.close(deviceId,name);break;default:/* 无动作 */}8.2 通用双阈值迟滞判定模拟量publicclassHysteresisAlarm{privatefinaldoublehigh;// 触发阈值privatefinaldoublelow;// 恢复阈值 (low high)publicHysteresisAlarm(doublehigh,doublelow){if(lowhigh)thrownewIllegalArgumentException(low 必须小于 high);this.highhigh;this.lowlow;}publicenumAction{TRIGGER,RECOVER,KEEP}/** * param value 当前测量值 * param alarmingNow 当前是否处于告警中建议来自数据库未闭合记录 */publicActionevaluate(doublevalue,booleanalarmingNow){if(valuehigh!alarmingNow)returnAction.TRIGGER;// 越过高阈值且未在告警if(valuelowalarmingNow)returnAction.RECOVER;// 回落到低阈值以下且在告警returnAction.KEEP;// 死区/状态不变}}// 使用booleanalarmingalarmService.hasUnfinished(deviceId,浓度超标);switch(newHysteresisAlarm(150,100).evaluate(value,alarming)){caseTRIGGER:alarmService.open(deviceId,浓度超标);break;caseRECOVER:alarmService.close(deviceId,浓度超标);break;default:/* KEEP不动作 */}8.3 告警名称 → 等级映射配置化publicclassAlarmLevels{publicstaticfinalintINFO1,WARN2,SERIOUS3,FATAL4;privatestaticfinalMapString,IntegerMAPnewHashMap();static{MAP.put(急停,FATAL);MAP.put(浓度超标,WARN);// ...}/** 未命中默认从严避免漏报 */publicstaticintof(Stringname){returnMAP.getOrDefault(name,SERIOUS);}}九、设计要点与踩坑清单主题要点区分信号类型布尔量走边沿检测模拟量走双阈值迟滞不可混用。位报警去重只在跳变时动作靠上次状态对比本项目缓存在 Redis。首次采集oldData null时不判定避免把初始状态误当上升沿。空值归一化读到 null 统一按正常/无数据处理防 NPE 与误报。模拟量防抖必须用双阈值回差带单阈值会告警抖动刷屏。high/low 关系恢复阈值必须严格小于触发阈值否则死区不成立。模拟量去重以数据库未闭合记录为状态源重启/多实例安全。采样降频模拟量可独立于采集频率降频入库如 10s减小数据量。告警生命周期触发写 start恢复写 stop可算时长stop_time IS NULL表未恢复。分级映射名称→等级配置化漏配默认从严。阈值配置分级设备级优先、料棚级兜底兼顾统一与个性化。异常隔离单个告警判定异常应 try-catch 兜底不影响整轮采集与其它设备。小结告警判定的核心是按信号物理类型选算法布尔量用边沿检测跳变才动作天然去重模拟量用双阈值迟滞回差带吸收抖动。两者最终都收敛到统一的带生命周期的告警记录 未闭合记录去重 名称分级模型。本项目在GetModbusTCPDataTask中用checkAlarmStatus位报警与tspThresholdCheck模拟量分别实现了这两类算法并用 Redis 缓存上次状态、数据库未闭合记录双重去重构成了一套健壮、可平移的工业告警判定范式。

相关新闻

Java面试高效突击:从原理到场景的实战解题框架

Java面试高效突击:从原理到场景的实战解题框架

7月,又到了Java面试的高峰期。无论你是准备跳槽寻求更好的发展,还是应届生即将踏入职场,面对动辄几十上百页的面试题,是不是总感觉时间不够用、重点抓不住、背了又忘?这篇文章要解决的就是这个最实际的问题&#xff1a…

2026/7/24 9:31:31 阅读更多 →
如何使用Docker快速部署Superdesk:适合中小媒体的零成本方案

如何使用Docker快速部署Superdesk:适合中小媒体的零成本方案

如何使用Docker快速部署Superdesk:适合中小媒体的零成本方案 【免费下载链接】superdesk Superdesk is an end-to-end news creation, production, curation, distribution, and publishing platform. 项目地址: https://gitcode.com/gh_mirrors/su/superdesk …

2026/7/23 18:26:15 阅读更多 →
鸿蒙 ArkTS 实战:Community Haircut Booking 从社区理发预约到生活服务工具完整解析

鸿蒙 ArkTS 实战:Community Haircut Booking 从社区理发预约到生活服务工具完整解析

鸿蒙 ArkTS 实战:Community Haircut Booking 从社区理发预约到生活服务工具完整解析 前言 Community Haircut Booking 是一个基于鸿蒙 ArkTS 与 ArkUI 声明式 UI 实现的生活服务类单页应用,核心场景是 社区理发师傅排班预约。 它把 维护当前师傅、提醒…

2026/7/24 3:20:48 阅读更多 →

最新新闻

Transformer自注意力机制原理与工程实践

Transformer自注意力机制原理与工程实践

1. Transformer架构中的自注意力机制解析 2017年那篇《Attention Is All You Need》论文扔进NLP领域就像往池塘里丢了块巨石。当时我在做机器翻译项目,第一次看到完全基于注意力机制的模型架构时,整个人都是懵的。传统RNN那套序列处理方式突然被颠覆&…

2026/7/24 11:26:50 阅读更多 →
豆包AI平台:MoE架构与情境感知技术解析

豆包AI平台:MoE架构与情境感知技术解析

1. 豆包平台全景解析2026年的智能助手领域正在经历一场范式转移。作为字节跳动旗下最新一代AI智能体平台,豆包正在重新定义人机交互的边界。这个全场景解决方案最令人惊艳之处在于,它彻底打破了传统语音助手"一问一答"的机械模式,转…

2026/7/24 11:26:50 阅读更多 →
AI Agent在运维领域的实践与应用

AI Agent在运维领域的实践与应用

1. 项目概述:当运维遇上AI Agent 最近在技术圈里,AI Agent的概念越来越火。作为一个在运维领域摸爬滚打多年的老手,我一直在思考如何将AI Agent技术真正落地到日常运维工作中。经过几个月的实践和迭代,终于打磨出了一套实用的&quo…

2026/7/24 11:26:50 阅读更多 →
多模态 AI 视频生成云端平台测评:基于商用场景的客观选型报告

多模态 AI 视频生成云端平台测评:基于商用场景的客观选型报告

短视频量产、跨境内容营销、短剧分镜预演、广告创意素材需求持续扩张,推动多模态 AI 视频云端平台成为内容团队标准化生产工具。多模态云端平台区别于独立模型 API、本地推理方案,统一整合文本、图像、音频输入,内置算力调度、任务管理、合规…

2026/7/24 11:26:50 阅读更多 →
Docker与Nginx部署实战:高效Web服务搭建指南

Docker与Nginx部署实战:高效Web服务搭建指南

1. Docker与Nginx部署全景解读当我们需要在Linux服务器上快速搭建Web服务时,DockerNginx的组合堪称黄金搭档。作为从业十年的运维老兵,我见证过无数种服务部署方式,但容器化方案始终保持着最高的部署效率和环境一致性。本文将手把手带您完成从…

2026/7/24 11:26:50 阅读更多 →
ESXi根分区爆满的应急处理与长效解决方案

ESXi根分区爆满的应急处理与长效解决方案

1. 问题现象与背景解析上周五凌晨2点37分,监控系统突然狂发告警短信——某台运行关键业务的ESXi主机突然失去响应。当我顶着黑眼圈连上iDRAC查看时,熟悉的紫色管理界面已经变成了满屏的"root filesystem is full"错误。这种场景对于虚拟化运维…

2026/7/24 11:25:50 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻