使用Elastic APM监控你的.NET Core应用
作者:Jax
前言
在应用实际的运维过程中,我们需要更多的日志和监控来让我们对自己的应用程序的运行状况有一个全方位的了解。然而对于大部分开发者而言,平时大家所关注的更多的是如何更优雅的实现业务,或者是如何让应用的响应速度更快等等与编码相关的技术,对于应用程序的监控,可能还停留在日志文件的层面,而且大多数是出了事故被人为发现后,才通过日志尝试去定位问题。
本文所准备介绍的Elastic APM是一套用于监控应用各项指标,比如系统响应时间、异常、EF执行的SQL记录等等,并且可以将这些记录组织成一个可追溯的链路,方便查询问题。此外,Elastic APM还可以通过Kibana来做非常漂亮的可视化展示,方便我们定位和发现问题。
废话不再多说,我们开始实战~
Elastic APM介绍
Elastic APM的由下面四个组件所组成,如下图:
APM Agent
APM Agent是安装到你的.NET Core程序中的一个Nuget包,他用于性能、错误等各类数据的收集,并将收集到的数据缓存起来分批发送到APM Server。当然,除了.NET Core使用的Nuget包,他还可以支持很多其他的语言,比如Java,Node.Js,Python等
支持的语言列表请参考这里:https://www.elastic.co/guide/en/apm/agent/index.html
APM Server
APM Server是部署在服务器端的一个用于接收Agent发来的数据包的应用程序,并根据这些数据包自动创建文档,将数据转存到Elastic Server中。
Elastic Search
这个相信大家都很熟悉了,他就是一个基于Lucene实现的高性能、分布式的全文搜索引擎,用于快速、实时的存储、搜索和分析大量数据。在这里来说,他提供的是数据存储和搜索能力!
Kibana
如果你熟悉Elastic Search,那么你一定多少会了解Kibana,Kibana是开源的分析和可视化平台,他能与Elastic Search进行很好的协同,帮助你快速的可视化存储在Elastic Search中的数据,并做成各种各样漂亮的报表、图形等。
环境准备
在本次的实战过程中,我们需要以下的东西:
- Elastic Search
- Kibana
- APM Server
- 一个基于.NET Standard 2.0 + 的项目
Elastic Search的安装:https://www.cnblogs.com/baiyunchen/p/11227144.html
Kibana的安装:
我的环境是Centos 7,所以照着https://www.elastic.co/guide/en/kibana/7.3/rpm.html 这个官网教程安装的,整个过程很简单:
- 下载Kibana RPM包(采用这种方式是因为用yum install网速太慢,所以我用迅雷下载完成rpm文件后上传到Linux机器中)
- 执行命令rpm --install “下载的文件名” 进行安装
- 安装完成后,到/etc/kibana/kibana.yml文件中在文件末尾增加以下配置:
server.host: 0.0.0.0
server.name: 主机IP
server.port: 一个你喜欢的端口号
elasticsearch.hosts: ["已安装好的ES地址,多个之间用逗号隔开"]
logging.dest: /var/log/kibana.log //需要提前把这个文件创建好,然后把权限给够
- 将Kibana安装为系统服务并启动
sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable kibana.service sudo systemctl start kibana.service
这里大家一定要注意Elastic Search的版本和Kibana一定要匹配,不然会报错的。(我的ES是前段时间装的,所以会有这问题,如果大家一口气安装所有的,应该没啥问题)
如果不幸遇到了问题,可以通过配置文件中logging.dest中配置的路径查看日志。
APM Server的安装
APM Server的安装跟Kibana的安装类似,过程如下:
- 下载RPM包,包在这个页面找你需要的版本,也需要跟ES、Kibana的版本一致,不然你懂得~ https://www.elastic.co/cn/downloads/past-releases#apm-server
- 执行rpm --install “下载的文件名”进行安装
- 在文件夹/etc/amp-server中修改配置文件apm-server.yml,将配置文件最开始的host: “localhost:8200”修改成“0.0.0.0:8200”,以便让他能允许通过ip:端口号的方式访问, 并在配置的最后面添加如下配置:
output.elasticsearch:
hosts: ["已安装好的ES地址,多个之间用逗号隔开"]
- 将apm-server安装为系统服务并启动
sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable apm-server.service sudo systemctl start apm-server.service
执行上述操作完成后,在浏览器中尝试打开服务器Ip:8200,最终如果APM Server安装的没有问题,则浏览器中会打印出类似于如下的内容:
{
"build_date": "2019-06-20T14:39:23Z",
"build_sha": "9a099b63c53eac8c55707df96193143ec66337e9",
"version": "7.2.0"
}
此时我们在浏览器中打开Kibana,然后点击Add APM
然后将新打开的页面往下滚动,点击Check APM Server Status按钮,如果出现You have correctly setup APM Server则说明安装完成~
到这里为止,我们的安装工作就全部完成了,接下来,我们尝试将.NET Core与Elastic APM集成起来,一起继续吧~
.NET Core 应用集成
我们创建一个Demo项目,来用于测试APM的各项功能。
项目的地址请参考GitHub:
引用依赖包
我们需要从Nuget引用相关的SDK来与我们的应用做集成,其实就是引用我们最开始说的APM Agent的部分,在Nuget中,我们引用Elastic.Apm.NetCoreAll这个包。
依赖这个包其实相当于自动依赖了如下三个包,你也可以根据需要只依赖其中的一部分。
这里我们为了简单起见,直接印用Elastic.Apm.NetCoreAll这个包
将Agent添加到.NET Core
找到.NET Core的StartUp文件,在里面的Configure方法中添加如下代码:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAllElasticApm(Configuration);
}
然后在application.json中添加如下内容:
{
"ElasticApm": {
"LogLevel": "Error", // Log级别,根据自己的需要来定"ServerUrls": "http://localhost:8200", //设置前面安装好的APM Server URL,默认端口号是8200
"ServiceName" : "MyApp", //应用的名字,跟着实际情况起就行,allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application
}
}
此时我们将项目启动起来,随便的刷新几下,然后回到Kibana中,在刚才的页面中往下滚动,选择.NET,然后点击Check Agent Status按钮,如果顺利,就会显示“Data successfully received from one or more agents”,如果不幸没能显示这句话,可以通过VS的Diagnostic Tools中的Event跟踪一下,看看是不是哪里没有配置对
监控数据查看
在Kibana的Add APM页面的最下方,找到Load Kibana Objects,来创建索引,然后点击APM dashboard按钮,就可以进入APM数据的查看页面。
点击APM Dashboard按钮后,展示的页面如下:
该页面中的功能分为Services、Traces两个大的功能模块,先来简单了解一下这两个Tab页中对应的功能。
Services
下面的列表中显示的XianDotnetCommunity其实就是你在配置文件中配置的ServiceName,点击这个名字进入,又可以看到如下的报表,里面有Transactions,Errors,Metrics三个Tab页。
其中
Transactions:展示的当前应用请求情况的概览,包括请求响应时长、请求调用次数等等
Errors:程序中的异常列表
Metrics:应用程序所在机器的CPU/内存使用情况
PS:其实我觉得非常需要一个当前应用程序所消耗的内存和CPU的值,但是貌似.NET Core版本的代理没有实现这些功能,期待未来的更新吧
Traces
里面是用于做链路追踪的视图,首页包含所有事务的名称列表以及响应时间等
点击具体的事务进去,可以看到这个事务经过的链路列表以及更详细的一些响应信息,从而帮你分析出整个链路中的瓶颈,更多内容我们在下面细讲。
探索更多
Elastic APM还有很多其他的功能,比如链路追踪、数据库调用执行,让我们来一起探索吧~
监控API调用链路追踪
如果你了解过微服务架构,那你一定了解链路追踪这个概念。那什么是链路追踪呢?举个栗子:
有个服务A,他会依赖服务B,C,而服务B又会依赖服务D,E,服务C又依赖F,G(省略无数依赖关系),然后有一天,服务A变得非常慢,那到底该怎么定位是哪个服务慢呢?此时链路最终就派上用场了~
我们来简单模拟一下这种嵌套的调用:
在一个WebAPI项目Demo1中有一个ConsumerController,他里面有一个API A,里面调用了另外一个WEB API项目Demo2中的接口B/C/D/E。代码大致如下:
项目甲:
[Route("api/consumer")]
[ApiController]
public class ConsumerController : ControllerBase
{
private readonly IHttpClientFactory _httpClientFactory;
public ConsumerController(IHttpClientFactory httpClientFactory)
{
//使用HttpClientFactory时需要先在StartUp中调用services.AddHttpClient();
_httpClientFactory = httpClientFactory;
} private const string baseUri = "http://localhost:54597"; [HttpGet("a")]
public async Task<string> A()
{
//HttpClient client = new HttpClient();
var client = _httpClientFactory.CreateClient();
Thread.Sleep(new Random().Next(1, 1500));
var b = await client.GetStringAsync($"{baseUri}/api/data-source/b");
var c = await client.GetStringAsync($"{baseUri}/api/data-source/c");
var d = await client.GetStringAsync($"{baseUri}/api/data-source/d");
var e = await client.GetStringAsync($"{baseUri}/api/data-source/e");
return $"b={b} & c={c} & d={d} & e={e}";
}
}
项目乙:
[Route("api/data-source")]
[ApiController]
public class DataSourceController : ControllerBase
{
[HttpGet("b")]
public async Task<string> B()
{
Thread.Sleep(new Random().Next(1, 1500));
return "B";
} [HttpGet("c")]
public async Task<string> C()
{
Thread.Sleep(new Random().Next(1, 1500));
return "C";
} [HttpGet("d")]
public async Task<string> D()
{
Thread.Sleep(new Random().Next(1, 1500));
return "D";
} [HttpGet("e")]
public async Task<string> E()
{
Thread.Sleep(new Random().Next(1, 1500));
return "E";
}
}
此时我们请求Demo1中的API A (xxx/api/consumer/a),然后在Kibana中打开APM中的Traces,找到”GET Consumer/A” 这条记录(看起来默认是根据Controller的名字+Action的名字命名的),然后点击查看详情。
在详情中的最下方,我们找到TimeLine,可以看到如下图所示的图形:
我们可以看到我们在请求API A时的时间分别花费在调用4个API中的时间,也可以看出调用第三个API花费的时间更长,点击蓝色的条可以看到请求的详细信息。
这里不太好的一点是默认显示的名字是GET localhost这样的,其实我们更期望的是显示成调用的api uri对吧?这个我提了一个pr给他们,大家可以关注下:https://github.com/elastic/apm-agent-dotnet/pull/463
监控EF执行记录
这个不需要过多的解释,就是在EF执行DB操作时,进行监控,以便发现性能等问题,我的代码大致如下:
[HttpGet("person")]
public void TestEfCore()
{
using (var db = new ApmDbContext())
{
var jax = new Person
{
Name = "西安.NET社区",
Age = 26,
Remark = "做最好的技术社区~"
}; db.Persons.Add(jax); db.SaveChanges(); db.Persons.FirstOrDefault(x => x.Id == jax.Id ); db.Persons.FirstOrDefault(x => x.Name == "西安.NET社区"); jax.Name = ".NET西安社区";
db.SaveChanges(); db.Persons.Remove(jax);
db.SaveChanges();
}
}
当我们使用Kibana查看这次请求时,TimeLine显示如下:
我们可以比较清晰直观的看到在这次请求中,执行了哪些SQL语句,各耗时多少,对我们的请求分析来说,还是蛮有用处的。点击具体的蓝条,还可以看到更详细的数据,但比较遗憾的是,数据中并没有记录SQL Params ,这对于我们想完全重现这次请求来说,还是不够友好~
自行埋点记录
相对来说,Elastic APM目前生态圈还不够好,比sky walking还是稍微差一些组件的支持,如果要使用Elastic APM,免不了自己去做一些性能数据的埋点记录,或者在为第三方组件、类库做支持时,也需要做一些数据的埋点。接下来我们就在我们的请求中,埋一些我们想额外记录的信息,示例代码如下:
[HttpGet]
public void RecordMyApmData()
{ var transaction = Agent.Tracer.CurrentTransaction; var span1 = transaction.StartSpan("Stage 1", "Customize");
Thread.Sleep(300);
span1.End(); Thread.Sleep(200); var span2 = transaction.StartSpan("Stage 2", "Customize");
Thread.Sleep(100);
span2.End(); Thread.Sleep(100); var span3 = transaction.StartSpan("Stage 3", "Customize");
Thread.Sleep(500);
span3.End();
}
最终记录的效果如下:
这个Demo虽然写的很简单,但是我相信你已经能大概脑补如何使用Elastic Apm Agent这个类去自定义自己需要捕捉的一些监控数据了~
异常监控
当我们的程序发生了异常时,Elastic APM能帮助你记录,这个功能和日志差不多,但可能比日志稍微好用那么一点点。我们一起来看看吧~
示例代码如下:
[HttpGet]
public void TestException()
{
try
{
throw new Exception("捕获的异常");
}
catch (Exception)
{ } throw new Exception("未捕获的异常");
}
执行代码后,我们可以通过点击Service Name,然后在Errors这个Tab页中查看到这次的异常
点击详情,我们能看到详细的堆栈调用信息:
此外,我们可以在Trasactions Tab中,找到发生异常的这个请求,然后点击查看详情,在详情中我们也能看到这次异常的发生:
总结
本文介绍了如何使用Elastic APM在.NET Core应用中收集性能和异常数据,并使用Kibana进行可视化分析,整体来说,Elastic APM还是挺强大的,对于性能监控、链路追踪、异常监控基本是够用了。
目前来说,Elastic APM 支持的组件还是比较有限,比如对数据库查询还只是支持EF Core,并不支持更多的组件,链路追踪也仅支持HTTP请求的追踪,也没用支持其他的方式。另外,个人认为Elastic APM把监控报警(Watcher) 给放到X-Pack收费包中也是挺让人伤心的,异常监控报警其实还是蛮关键的。
欢迎大家尝试Elastic APM,有问题的地方共同探讨~
使用Elastic APM监控你的.NET Core应用的更多相关文章
- .Net Core with 微服务 - Elastic APM
上一次我们介绍了Seq日志聚合组件.这次要给大家介绍的是Elastic APM ,一款应用程序性能监控组件.APM 监控围绕对应用.服务.容器的健康监控,对接口的调用链.性能进行监控.在我们实施微服务 ...
- 多语言应用性能监控系统:Elastic APM
▶ 概述 Elastic APM 是基于 Elastic Stack 构建的应用性能监控系统.通过 Elastic APM 可以监控应用程序,收集有关请求的响应时间.数据库查询.高速缓存调用.外部 H ...
- 使用 Elastic 技术栈构建 K8S 全栈监控 -4: 使用 Elastic APM 实时监控应用性能
文章转载自:https://www.qikqiak.com/post/k8s-monitor-use-elastic-stack-4/ 操作步骤 apm-servver连接es使用上一步创建的secr ...
- Elastic AMP监控.NET程序性能
什么是Elastic AMP Elastic APM 是一个应用程序性能监控系统.它可以请求的响应时间.数据库查询.对缓存的调用.外部 HTTP 请求等的详细性能信息,可以实时监控软件服务和应用程序. ...
- Node.js项目APM监控之New Relic
现在上一个项目,如果没有APM监控服务或应用的运行性能参数,等于是一架没有盲降系统的飞机正在盲降,结果会很悲催.出现了访问失效等问题时,都很难判定是性能瓶颈还是一个藏的深的bug,汇报的时候一顿眼晕, ...
- Build Telemetry for Distributed Services之Elastic APM
官网地址:https://www.elastic.co/guide/en/apm/get-started/current/index.html Overview Elastic APM is an a ...
- .net core使用App.Metrics+InfluxDB+Grafana进行APM监控
一.InfluxDB 1.下载InfluxDB wget https://dl.influxdata.com/influxdb/releases/influxdb-1.5.2.x86_64.rpm 2 ...
- 开源APM系统 HttpReports 在 .Net Core的应用
前言 简单说明下,APM全称Application Performance Management应用性能管理,通过各种收集请求数据,同时搭配Dashboard以实现对应用程序性能管理和故障管理的系统化 ...
- 微服务监控zipkin+asp.net core
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 监控目录:微服务监控zipkin.skywalking以及日志ELK监控系列 一.zipkin介绍 zipkin是一种分布式跟踪系 ...
随机推荐
- Python基础总结之初步认识---clsaa类(上)。第十四天开始(新手可相互督促)
最近的类看着很疼,坚持就是胜利~~~ python中的类,什么是类?类是由属性和方法组成的.类中可能有很多属性,以及方法. 我们这样定义一个类: 前面是class关键字 后面school是一个类的名字 ...
- 【算法】【查找】二分法 Bisection
#include<stdio.h> int main(){ ,,,,,,,,,,,,,,}; ; //长度 ; //要查找到的值 int Bisection(int x,int* a,in ...
- [原创实践]RedHat Enterprise Linux 5 安装GCC和redis
Redis的安装需要使用GCC,Red Hat Enterprise 5默认是不安装gcc的,需要自己手动安装. 1:查看系统中是否有gcc gcc -v 查看本机linux版本 lsb_releas ...
- Spring Boot + Security + JWT 实现Token验证+多Provider——登录系统
首先呢就是需求: 1.账号.密码进行第一次登录,获得token,之后的每次请求都在请求头里加上这个token就不用带账号.密码或是session了. 2.用户有两种类型,具体表现在数据库中存用户信息时 ...
- Java学习|Exception和Error有什么区别?
典型回答: Exception和Error都继承了Throwable类,java中只有Throwable类型的实例才能被Throw(抛出)或者catch(捕获). Exceptio ...
- 提取html内的文字1
public static string StripHTML(string strHtml) { string [] aryReg ={ @"<scrip ...
- Oracle - SPM固定执行计划(一)
一.前言 生产中偶尔会碰到一些sql,有多种执行计划,其中部分情况是统计信息过旧造成的,重新收集下统计信息就行了.但是有些时候重新收集统计信息也解决不了问题,而开发又在嗷嗷叫,没时间让你去慢慢分析原因 ...
- 并查集模板题----P3367 【模板】并查集
题目描述 如题,现在有一个并查集,你需要完成合并和查询操作. 输入格式 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1时,将Xi与Yi ...
- 大白话5分钟带你走进人工智能-第36节神经网络之tensorflow的前世今生和DAG原理图解(4)
目录 1.Tensorflow框架简介 2.安装Tensorflow 3.核心概念 4.代码实例和详细解释 5.拓扑图之有向无环图DAG 6.其他深度学习框架详细描述 6.1 Caffe框架: 6.2 ...
- 运行MonkeyRunner时使用Genymotion模拟器
Android自带的模拟器实在太慢太卡,远没有Genymotion的顺畅,所以找了一个办法,在启动py文件时使用Genymotion的模拟器 1.Genymotion安装完成之后,在Settings- ...