前言
后端软件行业正经历着缓慢却又日新月异的改革,从SOA到微服务、从业务一体化到中台战略、从虚拟化到云原生,历史告诉我们,在技术上如果跟不上时代的变迁,就终将成为技术的弃儿。
2020年,整体技术的发展已经充分影响到后端软件工程师开发的方方面面,包括开发时的所想所写,代码构建、部署和发布的流程,以及后期维护、优化的方式。这背后的推动力说白了就是硬件的发展已经遇到了瓶颈,人们无法在硬件上获得更大突破,所有才有了追求软件行业大规模的积聚效益的动力。
本篇着重描述dotnet探针代码结构及基本原理,下一篇将描述Tracing在SkyWalking中的实现规范。
闲话不多说,回到主题,作为一个现代(ppt)后端软件工程师,若我们需要对我们运行的服务的性能有充分的了解,就离不开APM(Application Performance Monitoring)。APM有三个基本定义:
1、Metrics 指标性统计
比如说我们会去做一个服务的 TBS 的正确率、成功率、流量等,这是我们常见的针对单个指标或者某一个数据库的,这就是 Metrics 单指标分析。
2、Tracing 分布式追踪
这里提到的是一次请求的范围,也就是我们从浏览器或者手机端发起任何的一次调用,甚至我们可以再推广一点,是一次业务教育,比如说一次订购的过程,从浏览商品到最后下定单、支付、物流、最后交到我们的手上。这是一个流程化的东西,我们需要轨迹,需要去追踪。
3、 Logging 日志记录
我们程序在执行的过程中间发生了一些日志,会一帧一帧地跳出来给大家去记录这个东西,这是日志记录。
如果你做一个监控的产品, 你需要明确自己的定位,每个领域实际上要关心的事情是不一样的,而且这些领域之间会有交叉点。比如 Metrics 和 Logging 可能是之于某个指标的统计,但你通过日志的方式去做了一个搜集,最后统计了这些 Metrics 的信息,以及这些 Metrics 信息和对应的 Logging 的关系,那么你走的可能是 Metrics 和 Logging 之间的范围。如果你要去做 Metrics 和 Logging 中间的这些点,你需要清楚你是不是要付出这么大的代价。因为你每去占到这个圆中的一个部分,你的系统复杂度、内存的开销、后端的存储都需要付出相应的代价。随着指标数、内容的加入,你所要投入的研发技术难度也在逐步上升。
在几年前,我们可能会自己开发性能监控系统(造轮子
- Metric监控我们可以有基于代码入侵的打点或者非入侵的agent,然后上报到Prometheus存储、最后用一套UI比如Grafana展现出来。
- Tracing监控我们有Zipkin、jaeger以及今天的主角Apache Skywalking等
- Logging利用ES来作存储查询,然后使用Kibana展示
SkyWalking也干了差不多的事情,只不过它是一套标准化的系统,他出现的意义就在于减少我们重复的开发工作(KPI又少了)。关于SkyWalking的数据核心 OAP(Observability Analysis Platform)我能力不够不作分析,今天我们来看看基于其规范的 dotnet 探针的设计思路。
源码结构
这个项目是一个实现优雅的core风格的项目,目录拆分、文件命名都有所考究,代码上整体都遵循依赖注入。
项目大体结构分为:
- Core :探针核心启动逻辑,注册自己到OAP数据中心,对采集到的数据进行格式归一、采样及最后的上报工作
- http://Agent.XXX :不同Host的agent输出,目前有 netfx、netcore 以及 general host三种
- http://Diagnostics.XXX :不同的采集器实现
- CLI :命令行工具
- Transport :与OAP数据中心的传输协议层,目前数据上报都是用的gRPC来传输
- Utilities:日志、依赖注入扩展、配置读取等
最后的产物就是名字叫http://SkyApm.Agent.XXX的几个dll,这几个dll根据各自所代表平台的特点,对不同的采集器进行了组合。
探针数据采集器的基本原理是:DiagnosticSource。
在 .NET Core 中使用 Diagnostics (Diagnostic Source) 记录跟踪信息www.cnblogs.com
DiagnosticSource 实现了一个消息的生产者消费者模型,在某个地方触发消息,然后可以在任意地方接收。微软在很多官方库里都预留了性能打点,例如:HttpContext、HttpClient、SqlClient、EntityFrameworkCore等,还有gRPC、CAP、SmartSql等一些第三方库等也都提前留了打点。它们在开始做某件事、做完某件事、做错某件事的时候,都会对进程内触发一个消息,让我们可以通过 DiagnosticSource 消费到这个消息,然后就可以用它来记录某次事件的具体历史了,便是实现了tracing。
我们也可以为自己的库配适SkyWalking,但是要手动打点,向 DiagnosticSource 发送你的事件信息,然后扩展一个自己的采集器就可以了。
探针监听这些消息的关键代码就一句:
DiagnosticListener.AllListeners.Subscribe(_observer);
DiagnosticListener
即是 DiagnosticSource 的具体实现,这个_observer 参数即是探针所做的主要工作,我们利用它来监听消息,然后将数据发送到数据中心,它是一个 TracingDiagnosticProcessorObserver
类型,这个类型维护了一组 Processors,这些 Processors 就是各个具体干活的采集器了。
private readonly IEnumerable<ITracingDiagnosticProcessor> _tracingDiagnosticProcessors;
它们都实现了一个简单的接口 ITracingDiagnosticProcessor
public interface ITracingDiagnosticProcessor
{
string ListenerName { get; }
}
实例分析
我们拿两个有代表性的 Processor 来研究:
HostingDiagnosticProcessor
HttpClientDiagnosticProcessor
前者是AspNetCore请求管线的Processor,它内部监听了这些事件源:
- Microsoft.AspNetCore.Hosting.BeginRequest
- Microsoft.AspNetCore.Hosting.EndRequest
- Microsoft.AspNetCore.Diagnostics.UnhandledException
- Microsoft.AspNetCore.Hosting.UnhandledException
后者是http://System.Net下的通用httpclient,内部监听了这些事件源:
- System.Net.Http.Request
- System.Net.Http.Response
- System.Net.Http.Exception
我们只要监听这些字符串代表的事件,就可以完整地拿到请求的上下文,有了这些上下文后,就可以产出一些标准的tracing信息,然后上报到数据中心。经OAP分析后,SkyWalking即可为我们展现出直观的 APM 信息,推荐读者可以自己动手在电脑上安装SkyWalking,加入探针后启动自己的服务,体验一下。
https://github.com/SkyAPM/SkyAPM-dotnetgithub.com
完。
编辑于 01-20