APP下载

轻量级监控系统的架构设计与踩坑经验_报警

消息来源:baojiabao.com 作者: 发布时间:2024-05-17

报价宝综合消息轻量级监控系统的架构设计与踩坑经验_报警

作者介绍

宋考俊,马蜂窝大交通平台高阶研发工程师。

部门的业务线越来越多,任何一个线上执行的应用,都可能因为各种各样的原因出现问题:比如业务层面,订单量比上周减少了,流量突然下降了;技术层面,系统出现 Error ,界面响应变慢了。拿大交通业务来说,一个明显的特点是依赖很多供应商的服务,所以我们还需要关注呼叫供应商界面是否出现异常等等。

为了让大交通下的各业务线都能够通过报警尽早发现问题、解决问题,进而提升业务系统的服务质量,我们决定构建统一的监控报警系统。

一方面在第一时间发现已经出现的系统异常,并及时解决;另一方面尽早发现一些潜在的问题,比如某个系统目前来看没有影响业务逻辑的正常运转,但是一些操作耗时已经比较长等,这类问题如果不及时处理,将来就很可能影响业务的发展。

本文主要介绍马蜂窝大交通业务监控报警系统的定位、整体架构设计,以及我们在落地实践过程中的一些踩坑经验。

一、架构设计与实现

我们希望监控报警系统主要具备以下三个能力:

在这样的前提下,报警中心的整体架构图和关键流程如下图所示:

纵向来看,Kafka 左侧是报警中心,右侧是业务系统。

报警中心的架构共分为三层,最上层是 Web 后台管理页面,主要完成报警规则的维护和报警记录的查询;中间层是报警中心的核心;最下面一层是资料层。业务系统通过一个叫做 mes-client-starter 的 JAR 包完成报警中心的接入。

我们可以将报警中心的工作划分为五个模组:

1、资料收集

我们采用指标采集上报的方式来发现系统问题,就是将系统执行过程中我们关注的一些指标进行记录和上传。上传的方式可以是日志、UDP 等等。

资料收集模组我们没有重复造轮子,是直接基于 MES (马蜂窝内部的大资料分析工具)来实现,主要考虑下面几个方面的原因:

那具体应该采集哪些指标呢?以大交通业务场景下使用者的一次下单请求为例,整个链路可能包括 HTTP 请求、Dubbo 呼叫、SQL 操作,中间可能还包括校验、转换、赋值等环节。一整套呼叫下来,会涉及到很多类和方法,我们不可能对每个类、每个方法呼叫都做采集,既耗时也没有意义。

为了以最小的成本来尽可能多地发现问题,我们选取了一些系统常用的框架元件自动打点,比如 HTTP、SQL、我们使用的 RPC 框架 Dubbo 等 ,来实现框架层面的统一监控。

而对于业务来说,每个业务系统关注的指标都不一样。对于不同业务开发人员需要关注的不同指标,比如支付成功订单数量等。开发人员可以通过系统提供的 API 进行手动埋点,自己定义不同业务和系统模组需要记录的状况。

2、资料储存

对于采集上来的动态指标资料,我们选择使用 Elasticsearch 来储存,主要基于两点原因:

此外,Elasticsearch 还支援聚合计算,方便快速执行 count , sum , avg 等任务。

3、报警规则

有了埋点资料,下一步就需要定义一套报警规则,把我们关注的问题量化为具体的资料,验证是否超出了预设的阈值。这是整个报警中心最复杂的问题,也最为核心。

之前的整体架构图中,最核心的部分就是“规则执行引擎”,它通过执行定时任务来驱动系统的执行。首先,执行引擎会去查询所有生效的规则,然后根据规则的描述到 Elasticsearch 中进行过滤和聚合计算,最后将上一步聚合计算得结果跟规则中预先设定的阈值做比较,如果满足条件则传送报警讯息。

这个过程涉及到了几个关键的技术点:

1) 定时任务

为了保证系统的可用性,避免由于单点故障导致整个监控报警系统失效,我们以“分钟”为周期,设定每一分钟执行一次报警规则。这里用的是 Elastic Job 来进行分散式任务排程,方便操控任务的启动和停止。

2)“三段式”报警规则

我们将报警规则的实现定义为“过滤、聚合、比较”这三个阶段。举例来说,假设这是一个服务 A 的 Error 埋点日志:

app_name=B is_error=false warn_msg=aa datetime=2019-04-01 11:12:00

app_name=A is_error=false datetime=2019-04-02 12:12:00

app_name=A is_error=true error_msg=bb datetime=2019-04-02 15:12:00

app_name=A is_error=true error_msg=bb datetime=2019-04-02 16:12:09

报警规则定义如下:

对于一些复杂条件的报警,比如我们上边提到的失败率和流量波动,应该如何实现呢?

假设有这样一个问题:如果呼叫的 A 服务失败率超过 80%,并且总请求量大于 100,传送报警通知。

我们知道,失败率其实就是失败的数量除以总数量,而失败的数量和总数量可以通过前面提到的“过滤+聚合”的方式得到,那么其实这个问题就可以通过如下的公式描述出来:

failedCount/totalCount>0.8&&totalCount>100

然后我们使用表示式引擎 fast-el 对上面的表示式进行计算,得到的结果与设定的阈值比较即可。

3) 自动建立预设报警规则

对于常用的 Dubbo, HTTP 等,由于涉及的类和方法比较多,开发人员可以通过后台管理界面维护报警规则,报警规则会储存到 MySQL 数据库中,同时在 Redis 中快取。

以 Dubbo 为例,首先通过 Dubbo 的 ApplicationModel 获取所有的 Provider 和 Consumer,将这些类和方法的资讯与规则模板结合(规则模板可以理解为剔除掉具体类和方法资讯的规则),创建出针对某个类下某个方法的规则。

比如:A 服务对外提供的 dubbo 界面/ order / getOrderById 每分钟平均响应时间超过 1 秒则报警;B 服务呼叫的 dubbo 界面/ train / grabTicket /每分钟范围 false 状态个数超过 10 个则报警等等。

4、报警行为

目前在报警规则触发后主要采用两种方式来发生报警行为:

之后我们会持续完善报警行为的策略,比如针对不同等级采用不同的报警方式,使开发人员既可以迅速发现问题,又不过多牵扯在新功能研发上的精力。

5、辅助定位

为了能够快速帮助开发人员定位具问题,我们设计了命中抽样的功能:

首先,把命中规则的 tracer_id 提取出来,提供一个连结可以直接跳转到 Kibana 检视相关日志,实现链路的还原。

其次,开发人员也可以自己设定他要关注的字段,然后把这个字段对应的值也抽取出来,问题出在哪里就可以一目了然地看到。

技术实现上,定义一个命中抽样的字段,这个字段里面允许使用者输入一个或者多个 dollar 大括号。比如我们可能关注某个供应商的界面执行情况,则命中抽样的字段可能为下图中上半部分。在需要传送报警讯息的时候,提取出里面的字段,到 ES 中查询对应的值,用 FreeMarker 来完成替换,最终传送给开发人员的讯息是如下所示,开发人员可以快速知道系统哪里出了问题。

二、踩坑经验和演进方向

大交通业务监控报警系统的搭建是一个从 0 到 1 的过程,在整过开发过程中,我们遇到了很多问题,比如:内存瞬间被打满、ES 越来越慢、频繁 Full GC,下面具体讲一下针对以上几点我们的优化经验。

1、踩过的坑

1)内存瞬间被打满

任何一个系统,都有它能承受的极限,所以都需要这么一座大坝,在洪水来的时候能够拦截下来。

报警中心也一样,报警中心对外面临最大的瓶颈点在接收 Kafka 中传过来的 MES 埋点日志。上线初期出现过一次由于业务系统异常导致瞬间大量埋点日志打到报警中心,导致系统内存打满的问题。

解决办法是评估每个节点的最大承受能力,做好系统保护。针对这个问题,我们采取的是限流的方式,由于 Kafka 消费讯息使用的是拉取的模式,所以只需要控制好拉取的速率即可,比如使用 Guava 的 RateLimiter :

messageHandler = (message) -> {

RateLimiter messageRateLimiter = RateLimiter.create(20000);

final double acquireTime = messageRateLimiter.acquire();

/**

save..

*/

}

2)ES 越来越慢

由于 MES 日志量比较大,也有冷热之分,为了在保证效能的同时方便资料迁移,我们按照应用 + 月份的粒度建立 ES 索引,如下所示:

3)频繁 Full GC

我们使用 Logback 作为日志框架,为了能够搜集到 Error 和 Warn 日志,自定义了一个 Appender。如果想搜集 Spring 容器启动之前(此时 TalarmLogbackAppender 还未初始化)的日志, Logback 的一个扩充套件 jar 包中的 DelegatingLogbackAppender 提供了一种快取的方式,内存泄漏就出在这个快取的地方。

正常情况系统启动起来之后,ApplicationContextHolder 中的 Spring 上下文不为空,会自动从快取里面把日志取出来。但是如果因为种种原因没有初始化这个类 ApplicationContextHolder,日志会在快取中越积越多,最终导致频繁的 Full GC。

解决办法:

2、近期规划

目前这个系统还有一些不完善的地方,也是未来的一些规划:

三、小结

总结起来,大交通业务监控报警系统架构有以下几个特点:

线上生产运维主要做 3 件事:发现问题、定位问题、解决问题。发现问题,就是在系统出现异常的时候尽快通知系统负责人。定位问题和解决问题,就是能够为开发人员提供快速修复系统的必要资讯,越精确越好。

报警系统的定位应该是线上问题解决链条中的第一步和入口手段。将其通过核心线索资料与资料回溯系统(Tracer 链路等),部署释出系统等进行有机的串联,可以极大提升线上问题解决的效率,更好地为生产保驾护航。

不管做什么,我们最终的目标只有一个,就是提高服务的质量。

作者:宋考俊

来源:马蜂窝技术(ID:mfwtech)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:[email protected]

2019-08-04 01:51:00

相关文章