一、项目背景
近几年,信也科技的研发技术伴随着业务的快速增长逐步演化为微服务化的分布式体系架构,但随之带来的系统间的上下游依赖关系的复杂度也呈指数级上升,已有的烟囱式的监控产品(CAT、ELK等)存在数据散落、指标覆盖度低的特点,用户定位、分析异常故障需要切换多个监控产品,并且经常需要上下游多人协作定位,定位问题的效率非常低下,甚至会出现找不到问题根源等难题,同时监控数据的价值也没有有效挖掘与使用。为了解决这些问题,谛听全链路监控平台应运而生。
二、产品介绍
谛听全链路监控平台通过自动化埋点、收集、存储、分析分布式系统中的指标数据、链路数据和日志数据,将流转在上下游站点间的信息串联起来,形成全链路跟踪,通过多维指标、链路与日志的关联分析与计算,提供统一告警、信息检索和展示等功能,极大的提升了定位故障的效率。目前线上已接入300多个应用,每日产生近百亿条数据,支撑公司多个重要项目(测试多环境、OneID、应用水位线、风险模型变量监控、AlarmBox等)的实施。
三、设计理念
监控系统本质是海量数据的采集、处理、分析、存储及展示,平台设计的难点在于我们不仅要知道“有没有问题”,还要知道“是什么原因”导致的问题,以及发现问题如何快速修复。目前我们主要对系统的运行状态(请求量、响应时间、异常数、出错率等)、事件状态(配置变更、发版、重启、告警等)及内部状态(健康状态、连接池情况、线程池情况、队列积压数、GC次数以及时长等)等数据进行多维度监测,从面到线再到点逐步排除过滤,进而发现故障根因,支撑开发快速排障,这是当初设计谛听监控高效排障的思路。
进一步,我们是否可以利用应用的实时运行的数据,通过检测算法和模型,提前发现问题避免故障的发生,这是我们后续努力尝试探索的一个方向。
举个典型的例子来说,用户收到一条应用响应慢的告警信息,大致的排障流程如下:
- 收到告警信息后,首先查看应用概览页并结合拓扑关系图分析是自身问题(异常、慢查询等情况)还是外部服务(DB、缓存、三方服务等)依赖问题。
- 查看事件中心分析是否是近期系统发版或者容器自动重启导致的系统异常,是否有其它告警事件发生。
- 在应用监控指标页查看接口列表定位具体慢的接口,按时间区间查询链路日志,发现是慢SQL导致的问题。
- 查看慢SQL对应的日志报文信息,发现是参数传递错误,导致接口变慢。
- 查看接口上游,分析定位到调用方应用及接口与应用负责人沟通修复问题。
目前我们已在积极探索将一些标准化定位问题的流程通过自动化分析手段,将诊断结果附加到告警消息中(例如应用异常的堆栈摘要推送到异常类告警中),帮助开发人员进一步提升定位问题的效率。
四、总体架构
信也根据内部现有的监控系统及基础设施并结合开源系统为基础,打通日志Logging、指标(时序)Metrics和链路Tracing数据,经过近1年的逐步演化实践形成以下架构:
该架构主要有以下几个特点:
- 高吞吐量:监控平台每日处理近百亿条TB级数据,整个处理过程全异步,服务端实时无状态方式,支持大流量增长下数据采样及机器扩容。
- 实时性:采用flink实时计算,对于复杂的监控规则,每分钟的检测窗口,分钟级的告警推送;利用客户端Agent秒级检测任务,对应用的紧急异常事件(死锁、OOM等)达到秒级检测,实时推送告警。
- 低成本接入:使用主流的Agent无侵入的方式接入,容器接入应用无感知,降低应用接入及运维成本,功能比jar包方式功能更强大。
- 高可用:集群化部署,无单点问题,即使监控服务组件出现问题对应用也无影响,监控组件(kafka、flink、influxdb-proxy、elk等)从设计上具有多副本和数据恢复能力。
- 适应性强:与业界很多开源系统及组件做了良好的适配,且与公司多个系统进行数据关联,提升定位问题的效率。
五、设计及实现
1. 客户端设计
1.1 插件开发
Java Agent(Instrumentation)是JDK1.5引入的技术,基于JVM TI机制,使得开发者可以构建一个独立于应用程序的代理(Agent),用来监测运行在 JVM 上的程序或者替换和修改某些类的定义。
谛听Agent主要使用基于AspectJ在类加载期切面织入方式对各种组件代码进行AOP拦截,通过–javaagent 参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动相应的代理程序,植入我们扩展的Plugin代码以实现监控功能。
目前谛听已支持近20种常用插件主要包括sofa-plugin,httpclient3-plugin,httpclient4-plugin,okhttp2-plugin,okhttp3-plugin,mysql-plugin,redis-plugin,resttemplate-plugin,feign-plugin, xxljob-plugin, tomcat-plugin,jetty-plugin等。
1.2 指标收集
为了保证数据的准确性,谛听Agent实现了通过从操作系统内核文件、MBean、组件自带监控扩展点以及AOP拦截等多种方式结合获取数据,不但可以根据指标的重要性进行分级,而且支持动态设置不同的指标上报频率,并且设计上支持推和拉两种方式(目前使用的是推的模式)。
值得说明的是,使用Linux内核文件的监控数据相比较其它方式,数据的准确度及完整度更高,例如读取/proc/stat收集cpu信息与我们日常使用的TOP命令获取的数据方式一致,经测试比JVM的收集的CPU数据准确性高很多,而且可以进一步了解CPU消耗的原因是系统、用户还是IO等待导致的。
目前谛听支持CPU、内存、磁盘、网络、文件句柄、内存区、垃圾回收、堆与非堆、thread、tomcat、jetty、sofa、netty、sentinel、rabbitMQ、druid、tomcatJDBC、hakari等200多个系统及中间件指标。
同时收集了60多个维度200多个性能指标,全部使用预计算的模式,充分保证数据的精确性。
另外,通过定时清理无请求的多余指标、指标分级、动态启停指标收集、高基维度指标防呆设计等多种方式防止指标收集对应用的影响。
1.3 日志收集
日志使用自研的日志组件,日志输出时自动与链路关联,并支持MDC方式自定义扩展,并根据应用的重要程度进行集群分离、冷热分离,热数据使用SSD存储,提升查询性能。
另外,通过谛听平台查询日志,谛听后台根据用户查询条件自动分析精准定位,另提供关键词高亮,线程查询,链路查询,IP查询,上下文查询等多种条件组合查询,查询效率比原有的Kibana查询效率提升5倍以上,用户体验更佳。
1.4 链路设计
数据主要使用公司已有的CAT的CAL数据模型,并在CAT的服务端定制链路分析器将CAT的模型清洗成类OpenTracing的模型,存储到elasticsearch中,解决了CAT无法根据条件查询链路的问题,并保留了与CAT系统的链路兼容,方便互相连接,谛听支持10多种条件链路查询,并支持手动打点及从请求或者响应报文中规则匹配将业务信息与链路自动关联,提升查询及定位问题的效率。
链路系统中另外一个有挑战的问题是,如何在各种技术栈调用情况下保证不丢失Trace信息、不破坏链路的完整性?
这里就涉及到数据透传的功能,分为应用内和应用间Trace信息的传播,有同步和异步两种调用情况,还有可能遇到池化复用线程(ExecutorService)的场景,谛听主要使用TransmittableThreadLocal(阿里开源的库)技术,TTL继承了InheritableThreadLocal,优化了在使用线程池等会池化复用线程的情况下传递ThreadLocal的使用(我们使用TTL Agent方式,应用无侵入,透明实现线程池的传递,进一步说明了Agent功能非常强大),在数据透传实现层根据协议的不同有不同的设置方式,比如目前广泛使用的rpc调用使用的http协议,我们首先将上下文中的信息取出放到Request Header中,服务端再从Request Header中取出放到上下文中,完成透传工作,对于其它的协议比如sofa,kafka等协议也有类似于header方式,传递流程类似,以上这一系列工作由Agent内部插件自动埋点实现。
2. 计算层设计
数据分区处理方式让同一个应用的维度数据进入同一个Partition,利用Flink的广播流+State+Checkpoint等机制实现。我们对计算逻辑进行高度抽象化,具体处理流程如下:
如图所示,这种机制有如下优点:
通过广播流在每个节点都保存了一份完整的规则数据,当规则发生变化时,每个节点都会获取到最新的规则,这保证了整体逻辑的一致性。
将数据流时间设置为EventTime,同时利用Flink的TimeService机制解决了动态开窗、延时、乱序问题,Flink中的 state解决了数据缓存的问题,使其不用依赖于外部缓存,大大增加了吞吐量。
同时基于Flink本身的checkpoint机制,可以实现failover后状态中的规则和缓存数据的恢复。
3. 存储层设计
谛听根据监控数据的使用场景不同,使用两种存储引擎:
对于时序类的指标数据,使用高性能的开源时序数据库influxdb,目前按应用及指标维度进行拆表,明细数据保存3个月,定期rollup保证查询性能。influxdb开源版本不支持集群模式,我们通过在influxdb前面的proxy中实现故障迁移,在线扩缩容、数据恢复、监控等功能,保障系统的高可用。
对于调用链的日志类数据使用业界广泛使用的ELK架构,通过Mapping模板优化,关闭不必要的分词和存储,调整默认的字段类型、优化索引刷新时间、按小时滚动创建索引、Routing直接命中分片(不打开整个索引),冷热分离,保证实时数据的查询性能,查询时根据时间及条件精准定位路由,前台查询达到秒级返回。
六、核心功能及实践场景
以上蓝色为已完成功能,棕色为规划待开发功能
核心功能建设思路:基于底层采集的全、准、细的指标、链路与日志数据,经过一系列的关联分析,提供数字化的呈现,并与常用诊断工具与其它系统集成,为数据应用及智能化场景提供支撑,提升效率,为应用赋能:
1. 实践场景一 多维条件查询链路,多视图展示
谛听提供根据时间范围、TraceId、客户端名、服务端名、客户端IP、服务端IP、仅异常调用、接口名称、环境、耗时大于(ms)、HTTP状态码等条件进行组合查询。
支持查看链路中请求报文、响应报文、SQL语句、redis命令、异常堆栈信息、业务主键等信息展示。
Agent自动在服务的响应报文中添加traceId,服务接收方可以通过页面、异常对话框、日志、数据库等存储,出现异常时可以快速通过TraceID进行链路重放,现场溯源。
谛听支持根据业务信息(报文提取及手工打点方式)查询链路,实时追踪用户轨迹,以业务的角度去排查异常问题。
谛听提供拓扑视图、调用树视图、混合视图及日志视图,多种角度展示链路信息,并提供系统指标、应用信息帮助开发更快速地找出性能瓶颈。
2. 实践场景二 多维指标分析,快速定位根因
谛听监控平台提供应用上下游拓扑、慢调用、慢SQL、异常统计、CPU高、GC问题、线程问题等多种常见问题的多维分析能力,代替传统的人肉命令行(例:top,jstack,netstat,iostat,jmap,jinfo等)定位问题的方式,帮助开发人员快速找到故障的根因。
3. 实践场景三 实时告警,多种报表,提前发现问题
提供6套默认告警模板,应用无需配置,告警功能自动生效,另外提供可视化的告警规则定制能力以及规则化配置触发容器的能力(重启、拉出流量等行为),帮助应用自愈。
支持告警消息的分组、抑制、静默、聚合减少告警噪声干扰,支持邮件、短信、企微、WebHook、MQ等多种通道告警消息的推送。
提供日报表、周报表、健康分等多种报表,帮助开发人员提前发现系统问题。
七、未来展望
(1) 目前CAT异步链路问题还未完全解决,后续逐步脱离CAT,兼容云原生OpenTelemetry标准。
(2) Cat指标监控维度单一,不能满足业务需求,后续开放客户端的metrics,支持业务监控,完善整体监控告警体系。
(3) 完善全链路监控体系,向用户体验端监控、业务监控和中间件监控进一步拓展。
(4) 利用收集的多维度的监控数据进行挖掘,结合应用场景,利用算法模型及专家经验,使应用更加智能更加高效。
本文来自拍码场,经授权后发布,本文观点不代表信也智慧金融研究院立场,转载请联系原作者。