马蜂窝大交通业务监控报警系统架构设计与实现

2023-12-15 07:40

本文主要是介绍马蜂窝大交通业务监控报警系统架构设计与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

为了让大交通下的各业务线都能够通过报警尽早发现问题、解决问题,进而提升业务系统的服务质量,我们决定构建统一的监控报警系统。一方面在第一时间发现已经出现的系统异常,及时解决;另一方面尽早发现一些潜在的问题,比如某个系统目前来看没有影响业务逻辑的正常运转,但是一些操作耗时已经比较长等,这类问题如果不及时处理,将来就很可能影响业务的发展。

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

架构设计与实现

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

1. 常用组件自动报警:对于各业务系统常用的框架组件(如 RPC ,HTTP 等)创建默认报警规则,来方便框架层面的统一监控。

2. 业务自定义报警:业务指标由业务开发自定义埋点字段,来记录每个业务和系统模块的特殊运行状况。

3. 快速定位问题:发现问题并不是目的,解决才是关键。我们希望在完成报警消息发送后,可以让开发者一目了然地发现问题出现在什么地方,从而快速解决。

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

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

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

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

1. 数据收集

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

首先数据收集模块我们没有重复造轮子,可是直接基于 MES (马蜂窝内部的大数据分析工具)来实现,主要考虑下面几个方面的原因:一来数据分析和报警在数据来源上是相似的;二来可以节省很多开发成本;同时也方便报警的接入。

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

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

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

2. 数据存储

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

**一是动态字段存储。**每个业务系统关注的指标可能都不一样,每个中间件的关注点也不同,所以埋哪些字段、每个字段的类型都无法预知,这就需要一个可以动态添加字段的数据库来存储埋点。Elasticsearch 不需要预先定义字段和类型,埋点数据插入的时候可以自动添加。

二是能够经得起海量数据的考验。每个用户请求进过每个监控组件都会产生多条埋点,这个数据量是非常庞大的。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

报警规则定义如下:

  • 过滤:通过若干个条件限制来圈定一个数据集。对于上面的问题,过滤条件可能是:app_name=A , is_error=true , datetime between ‘2019-14-02 16:12:00’ and ‘2019-14-02 16:13:00’.

  • 聚合:通过 count,avg,sum,max 等预先定义的聚合类型对上一步的数据集进行计算,得到一个唯一的数值。对于上面的问题,我们选择 count 来计算出现 ERROR 的次数。

  • 比较:把上一步得到的结果与设定的阈值比较。

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

假设有这样一个问题:如果调用的 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. 内存瞬间被打满

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

报警中心也一样,报警中心对外面临最大的瓶颈点在接收 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。

解决办法:

1. 保证 ApplicationContextHolder 的初始化

2. DelegatingLogbackAppender 有三种模式:OFF SOFT ON ,如果需要打开,尽量使用 SOFT模式,这时候缓存被存储在一个由 SoftReference 包装的列表中,在系统内存不足的时候,可以被垃圾回收器回收掉。

近期规划

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

  • 更易用:提供更多的使用帮助提示,帮助开发人员快速熟悉系统。

  • 更多报警维度:目前支持 HTTP,SQL, Dubbo 组件的自动报警,后续会陆续支持 MQ,Redis 定时任务等等。

  • 图形化展示:将埋点数据通过图形的方式展示出来,可以更直观地展示出系统的运行情况,同时也有助于开发人员对于系统阈值的设置。

小结

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

  • 支持灵活的报警规则配置,丰富的筛选逻辑

  • 自动添加常用组件的报警,Dubbo、HTTP 自动接入报警

  • 接入简单,接入 MES 的系统都可以快速接入使用

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

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

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

本文作者:宋考俊,马蜂窝大交通平台高级研发工程师。

(题图来源:网络)

关注马蜂窝技术,找到更多你想要的内容

这篇关于马蜂窝大交通业务监控报警系统架构设计与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/495661

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi