1.为什么需要监控服务

  监控服务的所属服务器硬件(如cpu,内存,磁盘I/O等)指标、服务本身的(如gc频率、线程池大小、锁争用情况、请求、响应、自定义业务指标),对于以前的小型单体服务来说,确实没什么必要,但对于中大型项目,尤其那些群集部署显得尤为重要、尤其是现在的微服务架构,服务众多,而且很多服务都是群集部署,我们更是需要实时知道每一个服务所属的实例(pod,服务器)的运行、请求异常、自定义业务监控指标等情况。



2.监控方案

  监控方案因公司而异,没有固定的套路,不一定复杂就好用,越复杂学习、维护、支出成本就越高,适合自己团队就好,抛砖引玉我们之前使用过的方案:

  1. 自己的服务器windows群集,.net core微服务架构,使用Telegraf在每台机服务器上进行采集cpu,内存,磁盘IO等等硬件指标数据和sqlserver、redis、rabbitmq等指标信息,使用Prometheus来采集.net core服务的请求相关的数据,无论是硬件指标还是软件指标,统一发送到时序数据库InfulxDB种,使用开源的报表程序Grafana来进行实时报表监控,通过Grafana的Alert条件触发webhook来将报警的数据信息组织好格式后,发送到我们自己写的一个服务接收,然后通过我们研发的通知订阅中心来发送给订阅者邮件、短信、企业微信、桌面等告警提示;

  2. 腾讯云Linux服务器,.net core微服务架构,基于k8s编排管理的docker集群,既然是云,很多硬件指标都是自带的监控,使用Prometheus监控集群下的所有服务的异常请求,Rabbitmq,Redis等等中间件指标信息,这次是基于Prometheus自带的时许数据库,使用其altermanger组件进行告警,全部Prometheus配置和自动发现新pod能力,都由牛逼的运维团队完成。

3.Prometheus

  本文中,我们主要来说说目前非常流行的监控中间件Prometheus,基于docker的搭建、配置、基本指标采集、自定义业务指标采集。

  Prometheus是一个开源的现代化的、支持云原生的系统监控与告警系统,2012年由前谷歌员工开发并做为社区开源项目开发,2015年正式发布,2016年加入云原生计算基金会CNCF,热度仅次于K8S。git地址

  已经很多知名的三方厂商已经基于Prometheus做成了导入器node exporter,比如linux系统,MYSQL数据库,Redis等等非常多的中间件,有了这些导入器,我们直接可以使用,非常丰富的监控指标人家已经为我们做好了。等下,我们演示以下使用linux的导入器来监控linux系统指标。

  上面是官方给出的生态组件图,Prometheus整个生态圈组成主要包括prometheus server,Exporter,pushgateway,alertmanager,grafana,Web ui界面,Prometheus server由三个部分组成,Retrieval,Storage,PromQL;

  1. Retrieval 负责在活跃的target主机上抓取监控指标数据;
  2. Storage 存储主要是把采集到的数据存储到磁盘中;
  3. PromQL是Prometheus提供的查询语言模块;

  工作流程,Prometheus server定期从活跃的目标主机上通过http pull的方式拉取指标数据,目标主机可以通过prometheus的配置文件进行配置或者通过服务发现方式来发现目标主机;也可以通过pushGateway组件,从目标主机推送该组件,Prometheus server再定时从该组件拉取指标数据;

4.Prometheus基于docker的搭建和监控

  1. 拉取linux系统的导入器node exporter
docker pull prom/node-exporter
  1. 启动linux监控容器
docker run --name=node-exporter -p 9100:9100 -itd prom/node-exporter
  1. 创建prometheus配置文件
mkdir /opt/prometheus
cd /opt/prometheus/
vim prometheus.yml
  1. 修改配置文件
global:
scrape_interval: 60s
evaluation_interval: 60s scrape_configs:
- job_name: linuxNode1 --目标任务名称
static_configs:
- targets: ['ip:9100'] --可以是多台
labels:
instance: linux1 --指标维度

5.启动prometheus容器

docker run -d -p 9090:9090 -v /opt/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml --name prometheus prom/prometheus:latest



启动成功后,prometheus的webui也可以使用了,浏览器输入http://IP:9090/targets

5.Grafana

  官方说明,grafana是用于可视化大型测量数据的开源程序,他提供了强大和优雅的方式去创建、共享、浏览数据。用过之后确实强大,可配置性灵活,现成的主流中间件基于prometheus的报表模板非常丰富。

  1. 拉取grafana镜像
docker pull grafana/grafana
  1. 启动grafana容器
docker run -d -p 3000:3000 --name=jmeterGrafana grafana/grafana

浏览器访问:http://ip:3000(账号密码都是:admin)



选择数据源

至此,我们的linux服务器的报表监控好了,接下来,我们来监控.net core服务的基本指标、请求、自定义业务数据。

6..net core集成prometheus

  1. nuget引入prometheus-net.AspNetCore
  2. startup类,管道运行时配置中
 //收集一些服务基本信息,比如线程数,内存使用,句柄,3个GC得回收次数统计
app.UseMetricServer();
  1. 启动程序访问http://localhost:5000/metrics

  2. 做为API服务,我们当然要收集http请求,请求状态,耗时,次数这些

 //收集一些服务基本信息,比如线程数,内存使用,句柄,3个GC得回收次数统计
app.UseMetricServer();
//收集http请求和计数监控,比如总请求数,每次请求得耗时
app.UseHttpMetrics();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

  1. 我们还想收集一些.net core服务运行时一些更深的指标来定位一些困难问题,不用我们写,我们只需要再引入一个别人封装好的包 prometheus-net.DotNetRuntime,就可以得到以下指标:

    • 垃圾回收的收集频率和时间;
    • 服务占用堆大小;
    • 对象堆分配的字节;
    • JIT编译和JIT CPU消耗率;
    • 线程池大小,调度延迟以及增长/缩小的原因;
    • 锁争用情况;

      代码如下:
//Program下main方法,为了减少性能开销,可以设置如下
DotNetRuntimeStatsBuilder
.Customize()
//每5个事件个采集一个
.WithContentionStats(sampleRate: SampleEvery.FiveEvents)
//每10事件采集一个
.WithJitStats(sampleRate: SampleEvery.TenEvents)
.WithThreadPoolStats()
.WithGcStats()
.StartCollecting();
  1. 再次运行会看到更多的指标了

  2. 这么多指标,维度的监控在prometheus原生UI上通过过滤可以看到响应的数据和报表,比如我们要看服务运行总内存,通过指标key:dotnet_total_memory_bytes,去webui上搜索:

  1. 原生UI多少差点意思,我们去prometheus报表模板市场去看看,有没有基于prometheus的.net core运行时的模板,市场传送门



我们找到一个模板,复制id用上文grafana导入模板的方法,导入进去,看看:

嗯,看上去好像不咋地,很多指标显示不出来,实际项目里,我们知道了指标数据,都是基于grafana自己配置要看的报表,下文我们继续来看看,怎么在.net core中基于promethues自定义一些指标收集,并且利用grafana来配置响应的报表。

7.自定义指标收集与配置报表

  通过上文的metrics指标数据,指标数据其实就是key value结构,只不过key中有label增加维度,并且每一个键值对都有响应的指标类型,prometheus的metrics有以下4种主要类型:

  • Counter:计数器,单调递增,应用启动之后只会增加不会减少
  • Gauge:仪表,和 Counter 类似,可增可减
  • Histogram:直方图,柱形图,Histogram其实是一组数据,主要用于统计数据分布的情况 —— 统计落在某些值的范围内的计数,同时也提供了所有值的总和和个数
  • Summary:汇总,摘要,summary 类似于 histogram,也是一组数据。不同的是,它统计的不是区间的个数而是统计分位数。
  1. 接下来,我们在代码里,使用Counter和Gauge这两种类型,来演示自定义指标收集;
  2. 先定义一个收集中心HUB
public class PrometheusMetricsHub
{
/// <summary>
/// 监控计数器维度统计容器
/// </summary>
public Dictionary<string, Counter> Counters { get; set; } = new Dictionary<string, Counter>();
/// <summary>
/// 监控仪表盘维度统计容器
/// </summary>
public Dictionary<string, Gauge> Gauges { get; set; } = new Dictionary<string, Gauge>(); /// <summary>
/// 创建计数器容器
/// </summary>
/// <param name="key"></param>
/// <param name="desc"></param>
/// <returns></returns>
public void CreateCounter(string key, string desc)
{
if (!this.Counters.ContainsKey(key))
this.Counters.Add(key, Metrics.CreateCounter(key, desc));
} /// <summary>
/// 创建仪表盘容器
/// </summary>
/// <param name="key"></param>
/// <param name="desc"></param>
/// <returns></returns>
public void CreateGauge(string key, string desc)
{
if (!this.Gauges.ContainsKey(key))
this.Gauges.Add(key, Metrics.CreateGauge(key, desc));
} /// <summary>
/// 根据维度类型获取监控实例
/// </summary>
/// <typeparam name="TContainer"></typeparam>
/// <param name="prometheusEnum"></param>
/// <param name="key"></param>
/// <returns></returns>
public TContainer GetContainer<TContainer>(PrometheusEnum prometheusEnum, string key) where TContainer : class
{
if (prometheusEnum == PrometheusEnum.Counter && this.Counters.ContainsKey(key))
return this.Counters.GetValueOrDefault(key) as TContainer;
if (prometheusEnum == PrometheusEnum.Gauge && this.Gauges.ContainsKey(key))
return this.Gauges.GetValueOrDefault(key) as TContainer;
return null; }
  1. 创建Prometheus注册容器的扩展方法
public static class PrometheusMetricsHubExtenisons
{
public static IServiceCollection AddPrometheusMetricsHub(this IServiceCollection services,Action<PrometheusMetricsHub> buildAction)
{
var hub = new PrometheusMetricsHub();
buildAction(hub);
services.AddSingleton<PrometheusMetricsHub>(hub);
return services;
}
}
  1. 启动类,使用扩展方法,进行对PrometheusHub配置并注入容器
 //注册监控
services.AddPrometheusMetricsHub(hub =>
{
hub.CreateCounter("demoCounter", "测试计数器");
hub.CreateGauge("demoGauge", "测试仪表盘");
});
  1. 创建一个中间件,每一次请求,都使用Prometheus指标容器进行累加统计
 public class PrometheusRequestMiddleware
{
private readonly RequestDelegate _next;
private readonly PrometheusMetricsHub _prometheusMetricsHub;
public PrometheusRequestMiddleware(RequestDelegate next, PrometheusMetricsHub prometheusMetricsHub)
{
_next = next;
_prometheusMetricsHub = prometheusMetricsHub;
}
public async Task InvokeAsync(HttpContext context)
{ try
{
//增加测试数据
var counter = _prometheusMetricsHub.GetContainer<Counter>(Models.PrometheusEnum.Counter, "demoCounter");
var gauge = _prometheusMetricsHub.GetContainer<Gauge>(Models.PrometheusEnum.Gauge, "demoGauge"); counter.Inc();
gauge.Inc();
await _next(context); }
finally
{ }
}
}
app.UseMiddleware<PrometheusRequestMiddleware>();
  1. 启动,并查看metrics指标

  2. 配置Grafana报表

由上图所见,我们自定义的指标监控完成。

8.关于Prometheus高可用

  Prometheus本身不支持群集部署,也就是说本身没法动态水平扩容,其实其本身的性能非常高,很少有撑不住情况,我们担心的是硬盘容量问题,假设真的是超级大量的指标数据,怎么办呢,下面有几个方案,也欢迎留言讨论:

  1. 取舍方案,放弃一些不重要的指标采集,降低指标数据持久化时间,调整采集速率等等一些逻辑优化;
  2. 服务维度拆分方案,也很容易理解,之前一台Prometheus去采集监控100个服务,现在用3台,划分服务,每台采集30多个服务;
  3. 分片方案,这种比较极端,某一个服务,pod规模上千甚至更多,这时候,你单台Promethues想完整采集这些pod的服务,对宽带、硬盘、CPU要求极高极高,性能估计也不咋地,这时候就要分片处理,从一台变多台,分别采集,但是这里有2个问题:

    1.这么多pod,肯定是要利用注册中心,在promethues配置里通过服务发现来动态配置要监控的服务,consul可以,并且promethues服务发现配置也支持consul,然后在服务注册的时候通过区分一个维度注册,好让对应promethues知道哪些节点是当前这台需要采集的。

    2.分片监控一个服务,基于Prometheus本身存储,肯定是没法集中聚合观看了,这里又涉及到统一使用其他数据源,比如InfluxDB,Redis等等,Promethes也支持配置只采集不存储,通过 remote write 方式写入远程存储库。

9.一些问题

  1. Prometheus不是持久化数据的,但是对于大部分指标监控,我们也不需要持久化,这里有一些产品上的业务指标,要想好是否需要持久化,别某台服务重启,之前数据没了。
  2. 报表问题,专业的BI产品经理才行,维度得把控好才行。
  3. .自定义指标收集时候,最好不要侵入性代码,能解耦则解耦。

微服务系列之服务监控 Prometheus与Grafana的更多相关文章

  1. 玩转Windows服务系列——Windows服务小技巧

    伴随着研究Windows服务,逐渐掌握了一些小技巧,现在与大家分享一下. 将Windows服务转变为控制台程序 由于默认的Windows服务程序,编译后为Win32的窗口程序.我们在程序启动或运行过程 ...

  2. 玩转Windows服务系列——Windows服务启动超时时间

    最近有客户反映,机房出现断电情况,服务器的系统重新启动后,数据库服务自启动失败.第一次遇到这种情况,为了查看是不是断电情况导致数据库文件损坏,从客户的服务器拿到数据库的日志,进行分析. 数据库工作机制 ...

  3. 玩转Windows服务系列——Windows服务小技巧

    原文:玩转Windows服务系列——Windows服务小技巧 伴随着研究Windows服务,逐渐掌握了一些小技巧,现在与大家分享一下. 将Windows服务转变为控制台程序 由于默认的Windows服 ...

  4. go微服务系列(二) - 服务注册/服务发现

    目录 1. 服务注册 1.1 代码演示 1.2 在go run的时候传入服务注册的参数 2. 服务发现均衡负载 2.1 均衡负载算法 2.2 服务发现均衡负载的演示 1. 服务注册 1.1 代码演示 ...

  5. go微服务系列(三) - 服务调用(http)

    1. 关于服务调用 2. 基本方式调用服务 3. 服务调用正确姿势(初步) 3.1 服务端代码 3.2 客户端调用(重要) 1. 关于服务调用 这里的服务调用,我们调用的可以是http api也可以是 ...

  6. Longhorn,企业级云原生容器分布式存储 - 监控(Prometheus+AlertManager+Grafana)

    内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? Longhorn 企业级云原生容器分布式存储解决方案设计架构和概念 Longhorn 企业级云原生容器分 ...

  7. 玩转Windows服务系列——给Windows服务添加COM接口

    当我们运行一个Windows服务的时候,一般情况下,我们会选择以非窗口或者非控制台的方式运行,这样,它就只是一个后台程序,没有界面供我们进行交互. 那么当我们想与Windows服务进行实时交互的时候, ...

  8. 玩转Windows服务系列——使用Boost.Application快速构建Windows服务

    玩转Windows服务系列——创建Windows服务一文中,介绍了如何快速使用VS构建一个Windows服务.Debug.Release版本的注册和卸载,及其原理和服务运行.停止流程浅析分别介绍了Wi ...

  9. 玩转Windows服务系列——Debug、Release版本的注册和卸载,及其原理

    Windows服务Debug版本 注册 Services.exe -regserver 卸载 Services.exe -unregserver Windows服务Release版本 注册 Servi ...

  10. 玩转Windows服务系列——创建Windows服务

    创建Windows服务的项目 新建项目->C++语言->ATL->ATL项目->服务(EXE) 这样就创建了一个Windows服务项目. 生成的解决方案包含两个项目:Servi ...

随机推荐

  1. [题解] Atcoder ARC 142 D Deterministic Placing 结论,DP

    题目 (可能有点长,但是请耐心看完,个人认为比官方题解好懂:P) 首先需要注意,对于任意节点i上的一个棋子,如果在一种走法中它走到了节点j,另一种走法中它走到了节点k,那么这两种走法进行完后,棋子占据 ...

  2. 网络安全(一)主动进攻之DNS基础和ettercap实现DNS流量劫持

    alittlemc,个人原创,个人理解和观点.若有错误.不理解请与我联系,谢谢! 介绍了DNS的解析过程. DNS劫持的思路和实践. DNS 域名 以为live.bilibili.com为例子,从后到 ...

  3. uni-app 如何优雅的使用权限认证并对本地文件上下起手

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1.起因 最近有一个需求,需要使用自定义插件,来对接硬件功能,需要配合对手机的权限进行判断和提示,并在对接后对本地文件进行操作,这里给大家 ...

  4. 第一种方式:使用form表单将前端数据提交到servelt(将前端数据提交到servlet)

    第二种使用Ajax的形式将前台的数据传输到后台:https://blog.csdn.net/weixin_43304253/article/details/120335657 1.form表单 引入了 ...

  5. 微服务架构学习与思考(11):开源 API 网关02-以 Java 为基础的 API 网关详细介绍

    微服务架构学习与思考(11):开源 API 网关02-以 Java 为基础的 API 网关详细介绍 上一篇关于网关的文章: 微服务架构学习与思考(10):微服务网关和开源 API 网关01-以 Ngi ...

  6. 靶机: easy_cloudantivirus

    靶机: easy_cloudantivirus 准备 下载靶机(Target):https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/ ...

  7. 9-模型层及ORM介绍

    一.模型层 模型层负责和数据库之间进行通信     二.Django配置mysql数据库 1.Django默认的数据库是sqllite3,将其更改为mysql数据库需要进行对应配置 1.安装mysql ...

  8. 使用 JWT 生成 token

    JWT 简介 JWT:Json Web Token 官网:https://jwt.io 优点:可生成安全性较高的 token 且可以完成时效性的检验(登陆过期检查) JWT 结构:(由官网获取) JW ...

  9. openstack单机部署 未完成

    注:centos8单机版 注:本次实验手动配置密码均为admin 环境准备:配置hosts文件 192.168.116.85为本机IP echo '192.168.116.85 controller ...

  10. 【Devexpress】Gridcontorl的列隐藏后再显示位置发生了变化

    首先在可视化界面中排序好每个列的显示位置索引 在窗口初始化时进行记录在字段中 /// <summary> /// 当前显示列的位置索引,用于隐藏后显示进行重新排序位置 /// </s ...