从零开始写一个APM监控程序(一)协议
APM(Application Performance Monitoring)是一种用于监控和管理应用程序性能的解决方案。它通过收集、分析和报告应用程序的性能数据,帮助开发人员和系统管理员更好地了解应用程序的运行状况,识别潜在的性能问题,并进行优化。
一般来说,APM 工具提供以下功能:
-
性能监控: 实时监控应用程序的性能指标,包括响应时间、吞吐量、错误率等。
-
事务追踪: 能够跟踪和记录应用程序中各个事务的执行情况,从而了解事务的执行路径、时间分布等。
-
错误检测: 检测并报告应用程序中的错误和异常,帮助快速定位和解决问题。
-
性能分析: 分析应用程序的性能瓶颈,提供可视化的分析工具,帮助开发人员优化代码和系统配置。
-
资源利用率监控: 监控硬件资源(如 CPU、内存、磁盘等)的利用率,帮助发现资源瓶颈。
APM 工具通常可以与各种类型的应用程序一起使用,包括 Web 应用、移动应用、微服务架构等。它们通过在应用程序中嵌入代理或采集器来收集数据,并将数据传送到中央存储或云服务中进行分析和展示。
一些常见的 APM 工具包括 New Relic、AppDynamics、Datadog、Elastic APM 等。这些工具的具体特性和支持的技术栈可能有所不同,选择合适的工具通常取决于应用程序的特点和需求。
国产的开源东西主要是SkyWalking。Apache SkyWalking 是一个开源的应用性能管理(APM)系统,用于监控、诊断和优化分布式系统的性能。它支持多种语言,包括 Java、.NET、Node.js、Go 等,可以跟踪分布式系统中的请求流,并提供详细的性能数据和可视化的监控工具。
以下是一些 SkyWalking 的主要特点:
-
分布式追踪: SkyWalking 提供了分布式追踪能力,可以跟踪请求在整个分布式系统中的传播路径,包括服务之间的调用和调用链路的详细信息。
-
性能指标: 提供系统的性能指标,包括吞吐量、响应时间、错误率等,以便开发人员和运维人员更好地了解系统的运行状况。
-
自动仪表板: 提供直观的仪表板和可视化工具,帮助用户监控和诊断分布式应用程序的性能问题。
-
跨语言支持: SkyWalking 支持多种语言,使其适用于各种技术栈和混合语言环境。
-
插件扩展: 具有插件系统,可以通过插件扩展功能,支持集成其他系统和工具。
-
开源社区: 作为 Apache 项目,SkyWalking 拥有活跃的开源社区,不断更新和改进系统。
SkyWalking 有助于开发团队识别性能瓶颈、优化代码,并提高系统的可维护性。
但是,别人的东西永远不一定完全适合自己,大多数时候改造的成本比从零开始写一个成本更高。
典型的APM(Application Performance Monitoring)通常是通过收集、分析和展示应用程序的性能数据,以监控和优化应用程序的运行状态。以下是一般的 APM 实现思路:
-
数据采集(Instrumentation): 在应用程序代码中插入监控点,收集关键性能指标。这通常包括跟踪请求、记录方法执行时间、捕获错误、以及收集资源利用情况等。开发者需要在代码中嵌入监控仪器,以便收集有关应用程序性能的数据。
-
数据传输: 将采集到的数据传输到中央收集点。这可以通过使用 Agent、SDK 或代理来完成。这些组件可以负责收集数据并将其传输到 APM 系统的后端。
-
数据存储: 将数据存储在后端数据库或数据仓库中,以供分析和查询。通常,APM 系统会使用数据库或其他持久性存储来保存监控数据。
-
数据分析: 对收集到的数据进行分析,以识别性能瓶颈、错误和潜在的优化点。分析可能包括生成报告、绘制性能图表、检测异常等。
-
可视化: 将分析结果以可视化的方式展示给开发者、运维人员和其他利益相关者。这可以通过仪表板、图表、报表等方式呈现。
-
告警和通知: 在性能达到或超过阈值时,发出告警,通知相关人员。这有助于快速响应性能问题,保持应用程序在高性能状态。
-
追踪请求和事务: 通过追踪请求和事务,可以了解整个系统的性能状况,包括前端和后端服务的交互。
-
支持多语言和多平台: APM 工具通常需要支持多种编程语言和运行环境,以便适用于各种应用程序和服务。
-
安全性: 保护监控数据的安全性,确保监控数据不被未授权的访问。
采集数据的部分分为探针和SDK两种,比如是JAVA和dotNet有虚拟机的,可以使用hook技术来拦截自己需要的方法,如果是编译型语言基本上使用的是SDK,程序员插码的方式实现。当然在linux下也可以使用eBPF的方式来构建挂钩程序,但是做到通用比较麻烦。
我认为与其在后期加HOOK,不如在项目之初就考虑需要监控的位置,用SDK来解决。
首先我们要解决交换协议:
一般,采集的内容分类3类:
- 某个代码块执行的时长效果等数据叫span,多个span可以串为一个trace;
- 针对硬件使用率的监控一般叫metric;
- 再有,就是分级部署时候探针(sdk)与后端之间还有一级,会对数据融合一次,减少数据量。
我打算采用protobuf3的方式定义数据交互格式,每个消息都定义最基本的常用的数据,其他的部分作为键值对可以扩展,后续只需要定义键值对就好了;其实也没有啥好扩展的,这么多年就这么点东西;数据传输可以用json,也可以用protobuf编码,目前大多数产品都是http传输,我觉得可以再进一步,使用http2或者websocket更好。
syntax = "proto3";
package model;
option go_package = "birdim/server/pb";// 服务定义
service ApmService {rpc AgentEvent (ApmAgentMsg) returns (ApmServerMsg);rpc FrontEvent (ApmAgentMsg) returns (ApmServerMsg);
}// 发送起端都是ApmAgentRequest 接收端应答ApmResponse
// 具体根据类型字段区分
// 1) ApmHello ----> ApmHelloReply
// 2) ApmSpan ----> ApmReply
// 3) ApmStatistic ----> ApmReply
// 4) APmUsage ----> ApmReply
// 5) ApmHeartBeat ----> ApmReply | ApmCtrl// 服务端发起参数调整 执行后应答
// 6) ApmCtrl ----> ApmReply// 展示端发起查询 服务端返回数据
// 7) ApmQuery ----> ApmData// 消息的所有类型
enum ApmMsgType {// Invalid value. The name must be globally unique.AMTUnused = 0;AMTHello= 1;AMTHelloReply = 2;AMTSpan = 3;AMTStatistic = 4;AMTCtrl = 5;AMTReply = 6;AMTQuery = 7;AMTData = 8;AMTHeartBeat = 9;AMTUsage = 10;
}// 控制命令代码
enum ApmCmdCode{ACUnused = 0;ACRestart = 1;ACSuspend = 2;ACResume = 3;ACConfig = 4;
}// 执行状态代码
enum ApmStateCode{ASUnused = 0;ASOk = 1;ASFail = 2;ASPending = 3;
}// 键值对,未用
message KeyValuePair {// 定义单个键值对string key = 1;string value = 2;
}// 如果需要登录,则需要认证
enum ApmAuthType{AUTNone = 0; // 可以不使用AUTPass = 1; // 前端客户使用AUTKey = 2; // agent 使用
}// 如果需要登录,一定是从客户端发起
message ApmHello{int64 seq = 1;int64 tm = 2;string u_id = 3;ApmAuthType auth_type = 4; // 认证类型string secret = 5; // 密码或者key,或者啥也不用map<string, string> params = 6;
}// 协商的应答
message ApmHelloReply{int64 seq = 1;int64 tm = 2;string u_id = 3; // 应答者的身份string state = 4; // 继续其他步骤,成功或者错误map<string, string> params = 6;
}// 采集的具体内容
message ApmSpan{// Request fields hereint64 seq = 1;int64 tm = 2;string u_id = 3;// APM-related fieldsstring trace_id = 4;string trace_name = 5;string span_id = 6;string parent_span_id = 7;string span_name = 8;string file = 9;string class = 10;string func = 11;string line = 12;int64 tm_start = 13;int64 tm_end = 14;ApmStateCode state = 15;string detail = 16;map<string, string> params = 17;
}// 如果需要在agent或者collector 统计过滤
message ApmStatistic{int64 seq = 1;int64 tm = 2;string u_id = 3;string trace_name = 4;string span_name = 5;int64 tm_start = 6;int64 tm_end = 7;int64 span_count = 8;int64 span_errors = 9;int64 span_slow_count = 10;int64 span_avg_time_cost = 11;int64 span_max_time_cost = 12;int64 span_min_time_cost = 13;map<string, string> params = 14;
}message ApmCtrl{int64 seq = 1;int64 tm = 2;string u_id =3;ApmCmdCode code = 4; // 控制的代码string cmd = 5;string detail = 6;map<string, string> params = 7;
}// 应答一条或者多条上报
message ApmReply{int64 seq = 1;int64 tm = 2;string u_id = 3;int64 ref_seq1 = 4;int64 ref_seq2 = 5;int32 state = 6;string detail = 7;
}// 心跳数据
message ApmHearBeat{int64 seq = 1;int64 tm = 2;string u_id = 3;
}// 使用率
message ApmUsage{int64 seq = 1;int64 tm = 2;string u_id = 3;int64 start_tm = 4; // 搜索开始时间int64 end_tm = 5; // 搜索结束时间int64 delta_tm = 6; // 时间片大小map<string, string> params = 7; // 内存,CPU,磁盘;的最大值,最小值,平均值,
}// 查询类型
enum ApmQueryType{AQTUnused = 0;AQTUsage = 1; // 利用率按时间片绘图AQTSpanDetail = 2; //AQTSpanStatistic = 3;
}enum ApmOpCodeType{AOCTUnused = 0; // 说明是一个括号,里面有多个childAOCTEqual = 1; // x = 1AOCTUnEqual = 2; // x != 1AOCTBetween = 3; // 1 < x < 2AOCTBetweenBoth = 4; // 1 <= x <= 2AOCTBetweenLeft = 5; // 1 <= x < 2AOCTBetweenRight = 6; // 1 < x <= 2AOCTGreaterThan = 7; // x > 1AOCTGreaterOrEqual = 8; // x >= 1AOCTLessThan = 9; // x < 9AOCTLessOrEqual = 10; // x <= 9AOCTLike = 11; // 正则匹配字符串AOCTUnlike = 12;AOCTIn = 13; // 集合之中
}// 定义一个查询条件的树状结构
message ApmQueryCondition{string name = 1;string field = 2; // 字段,ApmOpCodeType op_code = 3; // 计算符,值个数与运算符有关bool join_code = 4; // 同级条件合并运算符,and --> true, or ---> falserepeated string values = 5; // 根据字段的类型做数据转换repeated ApmQueryCondition children = 6; // 如果有多级,就用子节点方式,本级就相当于一个括号,op = Unused
}// 查询, 查询条件为空,就是认为全都要,统计类型需要时间分片大小,而详情不需要
message ApmQuery{int64 seq = 1;int64 tm = 2;string u_id = 3;int64 start_tm = 4; // 搜索开始时间int64 end_tm = 5; // 搜索结束时间int64 delta_tm = 6; // 时间片大小ApmQueryType type = 7;repeated ApmQueryCondition conditions = 8; // 一级条件也是一组,按照顺序合并}// 使用率的列表
message ApmUsageList{repeated ApmUsage list = 1;
}// 上报详细情况列表
message ApmSpanList{repeated ApmSpan list = 1;
}message ApmStatisticList{repeated ApmStatistic list = 1;
}// 查询数据得到的结果
message ApmData{int64 seq = 1;int64 tm = 2;string u_id = 3;int64 start_tm = 4; // 搜索开始时间int64 end_tm = 5; // 搜索结束时间int64 delta_tm = 6; // 时间片大小ApmQueryType type = 7;oneof message {ApmUsageList usages = 8;ApmSpanList spans = 9;ApmStatisticList statistic = 10;}}// the message that one agent would send
message ApmAgentMsg{ApmMsgType date_type=1;oneof message {ApmHello hello = 2;ApmSpan span = 3;ApmStatistic statistic = 4;ApmUsage usage = 5;ApmReply reply = 6;}
}// 前端查询使用
message ApmFrontMsg{ApmMsgType date_type=1;oneof message{ApmHello hello = 2;ApmQuery query = 3;}
}// reponse from server, collector or agent
message ApmServerMsg{ApmMsgType date_type=1;oneof message{ApmHelloReply hello_reply = 2;ApmReply reply = 3;ApmCtrl ctrl = 4;ApmData data = 5;}
}
未完待续……
相关文章:
从零开始写一个APM监控程序(一)协议
APM(Application Performance Monitoring)是一种用于监控和管理应用程序性能的解决方案。它通过收集、分析和报告应用程序的性能数据,帮助开发人员和系统管理员更好地了解应用程序的运行状况,识别潜在的性能问题,并进行…...
UDP网络套接字编程
先来说说数据在网络上的传输过程吧,我们知道系统其实终究是根据冯诺依曼来构成的,而网络数据是怎么发的呢? 其实很简单,网络有五层。如下: 如上图,我们知道的是,每层对应的操作系统中的那些地方…...
【苏州元德维康生物医药-注册】
...
从零带你底层实现unordered_map (1)
💯 博客内容:从零带你实现unordered_map 😀 作 者:陈大大陈 🚀 个人简介:一个正在努力学技术的准C后端工程师,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家…...
第六届浙江省大学生网络与信息安全竞赛 2023年 初赛/决赛 WEB方向 Writeup
-------------------【初赛】------------------- easy php 简单反序列化 __debuginfo()魔术方法打印所需调试信息,反序列化时候执行! 链子如下: BBB::__debuginfo()->CCC::__toString()->AAA::__call()EXP: <?php…...
设计模式篇---装饰模式
文章目录 概念结构实例总结 概念 装饰模式:动态的给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了 一种比使用子类更加灵活的替代方案。 装饰模式是一种对象结构型模式,它以对客户透明的方式动态地给一个对象附加上更多的责任…...
JAXB:根据Java文件生成XML schema文件
说明 JAXB有个schemagen脚本,可以根据Java文件生成XML schema。这个工具在JAXB独立发布包中有,可以从官网下载JAXB的独立发布包: https://eclipse-ee4j.github.io/jaxb-ri/ 示例 使用schemagen -d <path> <java files>格式 …...
opencv(5): 滤波器
滤波的作用:一幅图像通过滤波器得到另一幅图像;其中滤波器又称为卷积核,滤波的过程称为卷积。 锐化:边缘变清晰 低通滤波(Low-pass Filtering): 目标:去除图像中的高频成分&#…...
《微信小程序开发从入门到实战》学习二十二
3.3 开发创建投票页面 3.3.10 使用switch开关组件 用switch开关组件增加一个设置是否匿名投票的功能。 switch常用属性如下: checked 开还是关,默认false关 disabled 是否禁用,默认false不禁用࿰…...
LLM模型-讯飞星火与百度文心api调用
spark-wenxin 1-讯飞星火1_1-SparkApi.py1_2- Chat_spark.py1_3-调用api 2-百度文心2_1.code 3-两者之间比较与openai 1-讯飞星火 进入讯飞官网进行创建应用,获取相关密钥APPID,APISecret,APIKey,选择最新版本 首次调用讯飞官方a…...
AIGC ChatGPT 4 将数据接口文件使用Python进行入库Mysql
数据分析,数据处理的过程,往往将采集到的数据,或者从生产库过来的接口文件,我们都需要进行入库操作。 如下图数据: 将这样的数据接口文件,进行入库,插入到Mysql数据库中。 用Python代码来完成。 ChatGPT4来完成代码输入。 ChatGPT4完整内容如下: 这个任务可以使用`…...
Loguru:一个超酷的Python库
在项目中,了解代码运行情况至关重要,特别是遇到Bug需要排除问题的时候,而这正是日志记录发挥作用的地方。对于Python开发者来说,Loguru是一个简单但功能强大的日志记录库,它使得跟踪代码的行为变得轻松而高效。 什么是…...
cloud的概念
"Cloud"(云)通常指的是云计算(cloud computing)领域。云计算是一种通过网络(通常是互联网)提供计算资源和服务的模型。这些计算资源包括计算能力、存储空间、数据库、网络、分析能力等。云计算模…...
物联网赋能:WIFI HaLow在无线连接中的优势
在探讨无线网络连接时,我们不难发现,WIFI已经成为我们日常生活中不可或缺的一部分,承载了半数以上的互联网流量,并在家庭、学校、娱乐场所等各种场合广泛应用。然而,尽管WIFI4、WIFI5和WIFI6等协议无处不在,…...
淘宝商品详情数据接口(Taobao.item_get)
淘宝商品详情接口是一种程序化的接口,允许开发者根据商品ID或商品链接,获取淘宝平台上的商品详细信息。通过这个接口,开发者可以方便地获取商品的标题、价格、销量、描述等数据,进而提供给用户进行展示和购买。 使用淘宝商品详情…...
视频剪辑方法:一键批量调整色调的高效技巧
在视频剪辑的过程中,色调调整是一项非常重要的工作。它能够改变影片的氛围、情感和视觉效果,更好地沉浸在影片的情境中。然而,对于许多视频剪辑师来说,批量调整色调是一项非常繁琐的任务,需要耗费大量的时间和精力。色…...
NAS层协议栈学习笔记
NAS(Non-Access Stratum)是无线网络中非接入层及包括移动性管理(MM)和会话管理(SM)协议 ,在5G(NR)系统中连接管理(Connection Management)用于建立和释放UE与AMF之间的控制面(CP)信令连接。 5G中移动性管理是通过NAS信令在UE与核心网之间进行交互的,连接…...
前端食堂技术周刊第 105 期:TS 5.3 RC、Vite 5.0、W3C 新任 CEO、有害的 Pinia 模式、2024 更快的 Web
美味值:🌟🌟🌟🌟🌟 口味:金桂普洱 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly 大家好,我是童欧巴。欢迎来到前端食堂技术周刊,我们先来看下…...
jenkins 使用原生 git clone 命令,指定ssh密钥文件
使用环境变量 GIT_SSH_COMMAND 从Git版本2.3.0可以使用环境变量GIT_SSH_COMMAND,如下所示: GIT_SSH_COMMAND"ssh -i ~/.ssh/id_rsa_example" git clone example请注意,-i有时可以被您的配置文件覆盖,在这种情况下&…...
cobol数据类型
数据类型 数据部(data division)是用来描述程序中使用的变量的。 data name 数据名称 数据名称必须在数据部中定义,才能在过程部中使用。必须有一个用户自定义的名称,不能使用关键字,为存储实际数据的存储单元提供引…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
