本文为大家讲解 MOF 中的 CaptureFramework 框架。该框架提供统一的数据抓取行为和生成抓取结果能力,实现实时数据采集。
背景
应用服务监控是智能运维系统的重要组成部分。在 UAV 系统中,中间件增强框架(MOF)探针提供了应用画像及性能数据收集等功能,其中数据收集功能主要采集四类数据:实时数据、画像数据、调用链接数据生成以及线程数据分析数据。为实现实时数据采集,UAVStack 设计了 CaptureFramework 框架,提供统一的数据抓取行为和生成抓取结果能力。
CaptureFramework 运行原理
关键技术说明:
JavaAssist
Monitor 捕获体系
precap/docap
架构说明:
捕获点:支持 Tomcat、MSCP、Springboot、Jetty 埋点。
UAVServer 单例:作为统一的捕获入口点,提供了同步和异步方法。
StandardMonitor:实现了 Monitor 接口,是实时数据抓取实现类,提供了 doCapture 方法,负责抓取行为和生成抓取结果。
MonitorElemCapHandler:不同的抓取逻辑和抓取点的共同接口实现不同的埋点逻辑,提供了抓取行为的方法 preCap 与 doCap 以及生成抓取结果的方法 preStore。
StandardMonitorRepository:存储实时数据抓取数据结构。
DataObserver:暴露了 JMX/HTTP 接口数据。
关键类说明
Monitor 实时监控主要是从 DefaultMonitorSupporter 类启动初始化 StandardMonitor 对象,通过 CaptureFramework 将 monitor 对象安装到 DataStore 对象中。
DataObserver 提供 JMX/HTTP 服务,供后续 MA 抓取使用,其中 Http 服务注册了三个 handler,分别为 HttpJEEJVMObserver、HttpJEEMonitorObserver、HttpJEEProfileObserver。不同的 handler 暴露了不同的接口。
MonitorHandler 包下的 Handler 类具体处理 Monitor 的指标数据计算和统计。
捕获点剖析
CaptureFrameWork 框架提供了统一的捕获入口点,在 UAVServer 中分别提供了同步方法与异步方法:
同步捕获入口点:runMonitorCaptureOnServerCapPoint
异步捕获入口点:runMonitorAsyncCaptureOnServerCapPoint
同步与异步调用的差异分析:
异步比同步多增加了一个参数 CaptureContextMapFromAnotherThread,该参数若不为空,则需要合并上下文的信息。一般情况下在使用异步方法埋点时,在方法执行前调用异步捕获方法传入的 CaptureContextMapFromAnotherThread 为空,并返回封装好的上下文信息,在方法执行结束后调用异步捕获方法传入上下文信息,并进行上下文信息合并,再进行具体的捕获操作,具体可参考以下代码片段:
方法执行前的异步调用:
方法执行后的异步调用如下,其中 ccMap 为异步调用返回的封装好的上下文信息:
抓取行为剖析
Monitor 接口:提供了多个接口,其中最主要的是 doCapture 与 doPreStore 方法,doCapture 用来实现在特定的捕获点执行抓取数据行为,doPreStore 方法用来实现在存储到数据结构之前的一些捕获动作,做一些特殊数据的处理。
StandardMonitor 类:Monitor 接口的具体实现类。
StandardMonitorRepository 类:存储实时数据抓取数据结构。
MonitorElementInstance 接口:存储实时数据抓取数据结构的实例接口。
StandardMonitorElementInstance 类:MonitorElementInstance 接口的具体实现类。
无论是同步捕获入口点还是异步捕获入口点都会执行 doCapture 方法,代码片段如下:
monitor.doCapture 是调用了 Monitor 接口中的 doCapture,其实现类是 StandardMonitor。
StandardMonitor 中的 doCapture 方法主要做了如下操作:
根据参数获取当前的 MonitorElement 数组,MonitorElement 数组通过 StandardMonitorRepository 的 getElementByCapId 实现;
循环处理 MonitorElement 数组,获取捕捉数据实现类,根据实现类获取当前要执行的 handler,最后根据当前获取的 handler 判断捕获阶段(precap/docap),然后进行相应的处理。不同的 handler 根据不同的特性处理生成 MonitorElementInstance,最后将结果存储在 StandardMonitorRepository 数据结构中。
以 ServerEndRespTimeCapHandler(服务端抓取行为)为例:
preCap 方法:只记录了服务的开始请求时间。
doCap 方法:根据不同的 monitorElemId 进行不同的逻辑处理,最后封装好 MonitorElementInstance 实例,然后再进行抓取行为结果的处理,其中包含最大值消峰、最大值、最小值、返回状态码、时间戳更新、计数等相应的数据处理。
什么是实时数据
即运行时数据,指的是在程序运行时产生的信息,程序占用的 CPU、堆内存、JVM 信息以及提供服务访问与客户端调用的相关统计信息 (平均响应时间、访问计数等)。
服务端数据采集
DefaultMonitorSupporter 的实现
服务端数据采集以 DefaultMonitorSupporter.start 为入口点,构建 monitor 实例:
默认构建 service 类型的 StandardMonitor 实例,其中包含 StandardMonitorRepository 实例,StandardMonitorRepository 实例注册 monitor,一个该实例包含多个 MonitorElement 实例,并将所有的 MonitorElement 实例保存在 elemsMap 属性中。
elemsMap 属性根据不同的采集对象保存不同的采集类 handler:
ServerEndRespTimeCapHandler:采集 Server、APP、URL 的响应时间和加载计数等.
JVMStateCapHandler:采集 jvm 状态,包括 Heap 使用、GC 计数、线程计数、CPU、class 计数等。
代码片段如下:
客户端数据采集
DefaultClientMonitorSupporter 的实现
客户端数据采集以 DefaultClientMonitorSupporter.start 为入口点,构建 monitor 实例:
默认构建 client 类型的 StandardMonitor 实例,其中包含 StandardMonitorRepository 实例,StandardMonitorRepository 实例注册 monitor,一个该实例包含多个 MonitorElement 实例,并将所有的 MonitorElement 实例保存在 elemsMap 属性中。
elemsMap:属性只保存一个 ClientRespTimeCapHandler 采集类。
ClientRespTimeCapHandler:采集客户端的响应时间和加载计数等。
无论是客户端的数据采集还是服务端的数据采集,都会将 monitor 安装到 DataObserver 中;并且最后都会将构建成功的 monitor 绑定至指定的捕获方法(即 precap 和 docap)。
DataObServer 的实现
DataObServer 提供了两种模式来暴露接口数据,分别为 JMX 和 HTTP:
HTTP 方式:
由 HttpDataObserverWorker.start 作为入口点,分别注册了三个 handler,分别为获取 JVM 数据、Monitor 数据以及 profile 数据的 handler。不同的 handler 暴露了不同的接口,最终都返回了 JSON 格式的数据。
JMX 方式:
JMX 代理通过 getMBeanInfo 方法获取暴露的接口,来获取数据;
DataObServer 还提供了安装与卸载 monitor、增加与移除 listener 以及获取 profile 和 monitor 的方法:
读完本文后相信大家对 CaptureFramework 框架有了基本的了解,并对 CaptureFramework 的应用有了一定的感悟。本文只介绍了 MOF 相关的一部分内容,若大家对 MOF 感兴趣,欢迎大家后台留言或添加小助手“uavstack-assist”申请加入官方用户群,相信您一定会有所收获。
官方网站:https://uavorg.github.io/main/
开源地址:https://github.com/uavorg
UAV MOF 工作原理之 Agent 注入机制原理:http://college.creditease.cn/…