探针程序技术解析:基于 Spring Boot 非 Web 模式的云服务监控告警系统

文章目录


一、背景与挑战

在分布式服务架构中,"服务端内部监控一切正常,但客户却反馈接口无法使用"的现象时有发生。这是由于传统监控往往只关注服务自身健康状态(CPU、内存、连接池),而忽略了真实用户侧的接口可调用性。为解决这一痛点,我们设计了一款轻量级探针程序,通过周期性调用真实业务接口,从客户端视角评估服务质量,并依据多级阈值推送钉钉告警。

本文将从设计模式技术选型两个维度,深度剖析该探针的实现思路。


二、核心技术栈

类别 技术选型 选型理由
基础框架 Spring Boot 3.2.12(非 Web 模式) 成熟稳定,仅需核心容器 + 调度,不引入 Web 容器
构建工具 Maven 依赖管理简便,可打包为单一 fat jar
JDK Java 17+ 使用 java.net.http.HttpClient(原生),无需 Apache HttpClient
定时调度 Spring @Scheduled + 自定义 ThreadPoolTaskScheduler 满足固定频率探测,通过线程池隔离任务,避免阻塞
加密通信 阿里云提供的 rest-api-security.jar + BouncyCastle 实现请求加密、响应解密(国密算法)
HTTP 客户端 JDK 11 原生 HttpClient 零依赖,支持连接池、超时、异步
JSON 处理 Jackson(Spring Boot 自动配置) 性能优秀,与 Spring 无缝集成
告警推送 钉钉机器人 Webhook + 可选 HMAC-SHA256 加签 接入成本低,消息实时
状态存储 内存滑动窗口(LinkedList + synchronized 无需 Redis/DB,满足最近 10 次统计需求,轻量且高效
配置管理 @ConfigurationProperties + application.yml 类型安全,支持多环境切换

三、设计模式实践

本项目虽小,但巧妙运用了多个经典设计模式,保障了代码的可扩展性与可维护性。

1. 模板方法模式(Template Method)

使用场景:不同接口的探测流程高度相似(构造请求 → 调用API → 解析响应 → 更新滑动窗口 → 评估告警),差异仅在于请求体的构建方式、URL后缀以及告警消息模板。

实现方式AbstractProbeTask 抽象类定义了 probe() 模板方法,其中调用了三个抽象方法供子类实现:

java 复制代码
protected abstract String buildRequestPayload();      // 子类提供具体请求参数
protected abstract String getUrlSuffix();             // 子类提供接口路径
protected abstract String buildAlertMessage(...);     // 子类自定义告警内容

优点 :新增接口(如"批量查询")只需继承 AbstractProbeTask,实现三个方法并加上 @Scheduled 注解即可,符合开闭原则。

2. 策略模式(Strategy)

使用场景:告警规则因接口而异------最终位置与轨迹查询的响应时间阈值、错误码容忍度(204 是否算成功)均不同。规则判断逻辑需要独立于探测任务。

实现方式AlertRuleEvaluator 类作为上下文,持有两个 ProbeConfig 配置对象(分别对应两个接口的规则)。evaluate() 方法根据传入的 probeName 动态选择规则集进行匹配。

java 复制代码
public AlertLevel evaluate(List<ProbeRecord> records, String probeName) {
    ProbeConfig config = probeName.contains("LastLocation") ? lastLocationConfig : trackQueryConfig;
    if (matchesCritical(config, records)) return AlertLevel.CRITICAL;
    if (matchesMajor(config, records)) return AlertLevel.MAJOR;
    if (matchesMinor(config, records)) return AlertLevel.MINOR;
    return null;
}

优点:未来若需支持更多接口或调整规则,只需修改策略类或增加配置,无需改动探测任务本体。

四、关键设计亮点

1. 非 Web 模式 + 命令行保活

通过 WebApplicationType.NONE 关闭内嵌 Tomcat,再借助 CountDownLatch 阻塞主线程,实现后台驻留。相比传统 Web 应用,内存占用减少约 60%(实测约 50MB)。

2. 内存滑动窗口

使用 Deque<ProbeRecord> 维护最近 10 次探测记录,通过 synchronized 保证线程安全。每个探测任务拥有独立窗口,互不干扰。该设计避免了数据库或缓存的依赖,且重启后自动清空,符合探针"无状态"定位。

3. 告警冷却机制

利用 ConcurrentHashMap 记录每个接口各级告警的最后发送时间,冷却期内(默认 1 分钟)相同告警不再重复推送。有效避免网络抖动或持续异常时的消息轰炸。

4. 定时任务线程池隔离

默认 @Scheduled 使用单线程,任务阻塞会影响其他任务。通过自定义 ThreadPoolTaskScheduler 将线程池大小设为 10,每个探测任务和心跳任务均获得独立线程资源,保障调度可靠性。

5. 加密请求透明化

CloudApiClient 完全封装了 DataParseUtils.getDataPojoV1_0parseData1_0,调用方只需传入明文 JSON,得到明文响应,加解密过程对业务层不可见,降低了代码侵入性。

五、部署与运维

  • 打包mvn clean package 生成可执行 fat jar。
  • 运行java -jar cloud-probe.jarnohup java -jar cloud-probe.jar > probe.log 2>&1 &
  • 监控:每小时心跳通知会推送当前滑动窗口的平均响应时间及最近记录,便于追踪长期趋势。
  • 扩展 :新增接口只需继承 AbstractProbeTask,并在 application.yml 中配置规则即可。

六、总结

该探针程序充分利用了 Spring Boot 非 Web 模式的轻量性,结合 JDK 11 原生 HTTP 客户端与内存数据结构,实现了低依赖、高可靠的云服务监控。在架构上,通过模板方法策略 等设计模式,保证了业务扩展的便捷性;通过滑动窗口冷却机制,平衡了实时性与告警风控。

对于需要主动探测第三方接口可用性的场景,本方案提供了一个简洁且高效的参考实现。


完整代码已托管至内部仓库,欢迎阅读与改进。


相关推荐
Ajie'Blog1 小时前
AI 周报 | Claude Opus 4.8、Copilot Agent 和 Codex 工作流加速
前端·人工智能·gpt·ai·copilot·ai编程
武子康1 小时前
Java-22 深入浅出 MyBatis - 手写ORM框架3 手写SqlSession、Executor 工作原理
java·后端
sugar__salt1 小时前
深入吃透前端线性数据结构:数组、栈、队列、链表核心原理与实战
前端·数据结构·链表
ikoala1 小时前
Codex 不得不装的 12 个插件,都在这了
前端·javascript·后端
摇滚侠1 小时前
SpringMVC 入门到实战 简介和入门案例 01-13
java·后端·spring·intellij-idea
蝎子莱莱爱打怪1 小时前
自用推荐|XTerminal:我心中 SSH 客户端的终极形态
java·后端·程序员
道友可好2 小时前
用 Linter 驾驭 AI:机械化执行的艺术
前端·人工智能·后端
流浪码农~2 小时前
Element Plus DatePicker 动态设置每周起始日
前端·vue.js·elementui
jason_yang2 小时前
刚发版就背锅?前端版本控制就靠他version-rocket
前端