写点什么

创业公司技术体系建设 -APM

用户头像
星际行者
关注
发布于: 2020 年 08 月 02 日
创业公司技术体系建设-APM

APM 被形象的称为应用医生,做为前文的后续,本文将详细介绍一下公司 APM 架构的演进过程。


一、1.0 版架构


1.0 版的架构中,主要通过应用改造集成一个 jar 包完成 metrics 采集,通过 prometheus 收集后,根据预设告警规则发送告警通知。整体的特点是:

  1. 应用需做改造,应用中集成 apm-client.jar,prometheus 周期性轮询/prometheus 接口获取程序运行时状态。

  2. 监控配置在 prometheus 的配置文件中,运行时修改不方便。

  3. 告警接收人配置在 alertmanager 的配置文件中,运行时修改不方便。

  4. 只能采集 cpu、memory、接口响应时间等 metrics 指标,采集不到 trace。

  5. 应用必须包含 web 环境,否则无法通过/prometheus 接口获取程序运行时状态。

  6. 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 工具无法判断接口返回是否正常。


public class Sample {    AppResponse getInfo() {        AppResponse ret = new AppResponse();
try { // ... // ret.setData() ret.setCode(0); }catch(Exception ex) { ret.setCode(-1); ret.setMsg(ex.getMessage()); }
return ret; } }
复制代码


综合来看,无论哪个 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 对告警事件做关联分析处理。



系列文章

一、创业公司技术体系建设

二、创业公司技术体系建设-CI/CD

三、创业公司技术体系建设-APM


发布于: 2020 年 08 月 02 日阅读数: 376
用户头像

星际行者

关注

编程多年依旧热爱。。。 2019.03.28 加入

还未添加个人简介

评论 (1 条评论)

发布
用户头像
Pinpoint部署过于复杂,需要Hbase环境,首先被排除。这比自己开发一个APM还难啊?
2020 年 08 月 03 日 12:02
回复
没有更多了
创业公司技术体系建设-APM