一、背景
随着分布式系统架构的普及,系统越来越复杂,常常被切分为多个独立子系统并以集群方式部署在数十甚至成百上千的机器上。为掌握系统运行状态,确保系统健康,我们需要一些手段去监控系统,以了解系统行为,分析系统的性能,或在系统出现故障时,能有能力发现问题、记录问题、定位问题。也可以根据监控数据发现系统瓶颈,提前感知故障,预判系统负载能力等。
因此「微盟APM系统」(链接:https://developers.weixin.qq.com/community/develop/article/doc/000aaed6f98b28093f3a5265151c13)应运而生,在微盟各业务线投入时候后,微盟各个业务线的小程序的公众号的流量也从2020年初的日均百万级别提升了2倍多。之前APM系统的主要功能是进行日志、打点、报错等信息的采集和汇总,并以调用链的形式展现出来,方便开发、运营人员直观查询并根据报错、耗时等性能指标来排查异常或进行功能点优化。但随着流量的不断提升,另一个课题摆在了面前。在发现错误或者异常行为的情况下,如何能够在第一时间得知这样的情况并作出应对,故我们基于APM系统打造了告警能力。
二、架构设计
- 整体架构
以上是我们的整体设计流程图,在我们对APM进行优化后 (链接:https://developers.weixin.qq.com/community/develop/article/doc/00006209434c506bc31cc3c4454c13),我们引入了Ckafka,利用消息队列的高吞吐、低延迟的特点,达到更高的消息处理速度。基于Ckafka,我们将告警设计成为一种数据消费的过滤条件。
2. 创建告警
如下图所示,用户首先需要在APM系统中创建一条报警规则:
用户可以在规则中选择
- 所监听的服务
- 产生的告警级别
- 抑制时间(告警的间隔)
- 发送告警的渠道(企业微信、邮件、短信等等)
- 告警接收人 (单人/用户组)
然后用户需要对该条规则进行补充,即如何才能触发此条规则完成告警,那么就需要添加告警策略了。
何为告警策略?顾名思义就是告警规则的判断依据,只有满足了所有或者任一策略,该条告警规则才会真正对接受人发起告警。
告警策略的主要由以下几部分组成:
- 间隔:时间间隔
- 阀值:即时间间隔单位内满足策略的次数
- 过滤器:具体过滤的条件,主要为采集数据内的一些属性
- 操作符:对阀值的补充,是大于还是大于等于
- 是否为平均值
以上条件即约束了在固定时间间隔内满足过滤器内条件并超过阀值的数据,即会触发此条告警策略。
举个例子,让我们来新建一条策略:
通过 Redis 的 pub/sub 功能告知 kafka-consumer ,在consumer中会根据该报警策略生成新的过滤规则,在消费数据中进行过滤判断,若触发过滤条件则通过令牌桶算法(基于Redis)记录触发次数,从而保证在分布式的架构中也能完成阀值统计,一旦触发阀值后,则会进行对应的告警。
此条策略约束了若5分钟内满足过滤器条件的数据出现的平均值超过10条,即满足此条策略。
由于过滤器中的值为用户上报数据中的部分字段,该字段的高度自由化,方便用户自定义监听维度。故可以定义出各种满足用户需求的告警维度,例如:
- 报错频次
- 卡顿频次
- 页面数据访问频次
- 某些接口的调用频次
而在整个告警规则中,基于一个或若干策略策略的触发,才会正真产生一条告警数据。根据该条产生的告警数据内配置的告警对象(人/用户组)以及告警方式(企业微信/邮件/短信等)进行精准告警。
3. 设计思路
上文提到微盟APM系统采用了Kafka作为消息队列用于承载日渐增多的数据量级。且由于初始数据发送至Kafka的时候有可能是进行过压缩等处理,故需要在消费者层面进行数据处理后才能存储至Elasticsearch。所以我们基于这样的架构,在消费者端增加了一个数据筛选流程用于处理告警规则的判断。
不同于利用Job的设计,使用筛选条件的模式需要将过滤规则尽可能的扁平化,同时也更契合ES的数据格式,可谓一举两得。故我们会对用户自定义的告警格式进行展平,使之和数据上报至ES的格式保持一致,最后使用Hash的方式直接筛选数据,时间负责度为O(1),经测试对数据消费基本不会产生影响。
由于告警基本都是以频次来计算是否触发阀值,故我们采用了类似 rate-limiter 的令牌桶算法来计算触发告警策略的次数,当超过预定阀值之后即判断满足该条告警策略。而 rate-limiter 在分布式的应用中一般都会使用Redis在进行数量统计,故我们在告警策略/告警规则的变更中也一样使用了Redis来进行Pub/Sub,所有在APM上的告警操作能瞬间同步到所有的Consumer上并产生效用,不会存在延时,立即起效。
以上就是微盟APM告警系统的整体架构以及实现,感谢您的阅读,我们下次再见。
牛了