创业公司技术体系建设 -APM
APM 被形象的称为应用医生,做为前文的后续,本文将详细介绍一下公司 APM 架构的演进过程。
一、1.0 版架构
1.0 版的架构中,主要通过应用改造集成一个 jar 包完成 metrics 采集,通过 prometheus 收集后,根据预设告警规则发送告警通知。整体的特点是:
应用需做改造,应用中集成 apm-client.jar,prometheus 周期性轮询/prometheus 接口获取程序运行时状态。
监控配置在 prometheus 的配置文件中,运行时修改不方便。
告警接收人配置在 alertmanager 的配置文件中,运行时修改不方便。
只能采集 cpu、memory、接口响应时间等 metrics 指标,采集不到 trace。
应用必须包含 web 环境,否则无法通过/prometheus 接口获取程序运行时状态。
apm-client 对程序性能几乎无影响。
二、2.0 版架构
为了能够实现 trace 收集、运行时修改告警规则、尽可能无侵入,先后调研了 PinPoint、Skywalking、Elastic Apm 等几个通过 Agent 方式进行应用监控的 Apm 工具。
Pinpoint 部署过于复杂,需要 Hbase 环境,首先被排除。Skywalking 不能运行时修改告警配置也被排除在外(6.5.0 之后可以)。Elastic Apm 经过调研后也无法满足我们的要求。除此之外,Trace 类的 APM 工具一般都根据 Http 状态码判断请求成功还是错误,但公司很多遗留的项目中确存在这样一种问题,接口内部已经出现错误,但确仍然返回 http status code 200,在返回值中自定义了其他错误码,这样的写法导致了 Trace 类的 APM 工具无法判断接口返回是否正常。
综合来看,无论哪个 APM 工具都不能满足我们的需求,需要定制开发,最初希望通过修改 Skywalking 来实现我们的需求,但很遗憾按照官方文档没有编译成功,最终我们通过修改 Elastic Apm 来完成公司的 APM 开发。2.0 版的整体架构如下:
上文提到要解决运行时修改告警配置、判断接口返回是否成功这两个问题,对于运行时修改告警配置,我们开发了一个独立的 Alert 告警系统,并参考 PromQL 使用 Antlr 实现了语法解析器,周期性查询 ElasticSearch 来判断是否有异常发生。比如:
avg(dubbo{appname="qdp-polaris-server"} by interface range 5m) > 2000
计算 5 分钟内 qdp-polaris-server 系统各个 dubbo 接口的平均响应时间,如果超过 2000ms 则产生报警。 相当于 SQL
select avg(响应时间) from table where timestamp between now() - 5m and now() group by dubbointerfacename
avg(http{appname=“qdp-polaris-server”, url ~= “.xxx.”} range 5m) > 2000
计算 5 分钟内 qdp-polaris-server 系统 http 接口名称匹配正则表达式.xxx.的接口平均响应时间,如果超过 2000ms 则产生报警。
avg(jvm.memory{appname="kafka-connect-platform-web"} by ip range 5m) > 1024
计算 5 分钟内 kafka-connect-platform-web 系统各实例 jvm 堆内存利用率,如果超过 1024MB 则产生报警。 相当于 SQL
select avg(heap memory) from table where timestamp between now() - 5m and now() group by ip
对于判断接口返回是否成功这个问题,我们采用变通性办法解决,在程序中使用 AOP 拦截接口调用,通过自定义指标来记录接口返回是否成功,不在通过 http status code 进行判断。比如通过在程序中记录 ERROR 或者其他关键字来实现。
count(event{appname="qdp-skyline-web", keyword ~=".ERROR."} range 5m) > 5
计算 5 分钟内 qdp-skyline-web 系统 LOG 日志中匹配.ERROR.的总数,如果超过 5 次则产生报警。 相当于 SQL
select count(1) from table where timestamp between now() - 5m and now() and message ~= “.ERROR.”
基于 Agent 方式的 APM 有一个比较明显的缺点,只能根据用户的请求情况来判断系统是否正常,不能先于用户发现问题。为了解决这个问题,最初我们想使用 Elastic HeartBeats 进行接口主动探测来触发 APM 告警,后来在 QA 同学的建议下,我们用 HttpRunner 编写用例主动进行探活,用例开发的工作由 QA 同学来做。
三、总结
目前我们的 APM 工具仍然在进化开发过程中,告警量太多导致漏掉重要的告警信息也是一个要考虑的问题,目前我们采用类似 AlertManager 的方法过滤重复告警。
后续希望通过 AI 算法合并告警消息降低告警数量,以及引入 CEP 对告警事件做关联分析处理。
系列文章
版权声明: 本文为 InfoQ 作者【星际行者】的原创文章。
原文链接:【http://xie.infoq.cn/article/9d67e3a985daabf268c398893】。文章转载请联系作者。
评论 (1 条评论)