前言

业务监控对许许多多的场景都是十分有意义,业务监控看板可以让我们比较直观的看到当前业务的实时情况,然后运营人员可以根据这些情况及时对业务进行调整操作,避免业务出现大问题。

老黄曾经遇到过一次比较尴尬的“事故”。

其中一条业务线,服务着的其中一个商家,把大部分流量切到另外一个地方去了,而我们的运营人员在当天却是完全不知情,第二天看了昨天的统计报表之后才发现这个商家的量少了很多,才能跟进协调处理。

ps: 当时实时报表比较欠缺,都是第二天凌晨生成昨天的数据报表,也没有告警机制。

后面就弄了个大屏幕做了业务监控的实时看板,看一眼就知道有什么风吹草动了。

先来看一下最终的效果图。

这个图里面主要包含了下面几个内容。

  1. 总的订单数量
  2. 退单的数量
  3. 创建订单的频率
  4. 不同渠道的订单量
  5. 不同渠道的退单量

下面就介绍一下如何实现这样的业务监控。

搭建基础设施

这里涉及的基础设施就有两个,一个是prometheus,另一个是grafana。

先启动prometheus,这里直接用docker启动。

$base = Split-Path -Parent $MyInvocation.MyCommand.Definition
$prometheusyml = Join-Path $base prometheus.yml
$fileconfig = Join-Path $base "config" write-host $prometheusyml
write-host $fileconfig docker run `
--name prom `
-p 9090:9090 `
-v ${prometheusyml}:/etc/prometheus/prometheus.yml `
-v ${fileconfig}:/etc/prometheus/fileconfig `
prom/prometheus:v2.20.1

下面是prometheus.yml

global:
scrape_interval: 15s
evaluation_interval: 15s alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093 rule_files: scrape_configs:
- job_name: 'file_ds'
file_sd_configs:
- refresh_interval: 10s
files:
- ./fileconfig/*.yml

这里用了基于文件的发现机制,没有用静态的。更多其他方式,参见 https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config

这个时候prometheus已经是运行起来了。

再来就是grafana了,启动这个更加简单。

docker run -d --name grafana -p 3000:3000 grafana/grafana:7.1.3

执行完,访问 localhost:3000 就可以看到登录界面了。

确定业务指标(metrics)

确定指标可以说是整个业务监控中最最最最最为主要的一个环节了,只有明确了我们要监控什么,我们才可以在业务上去进行埋点,拿到想要的数据。

这个其实和我们平时面对的需求是一个样的,需求明确了,做出来的东西才可能是我们想要的,需求不明确,做出来的东西可能就不会是我们想要的了。

为了帮助大家简单的理解相关的内容,这里举个监控的例子,监控不同渠道的下单和退单量。

涉及到量的,在一天内基本上是属于只增不减的,这个时候我们一般会选用 counter 类型来处理。

一个是下单,一个是退单,所以这里定义两个

  • yyyorder_created_total
  • yyyorder_canceled_total

counter类型的,一般在命名的时候最好都用_total作为结尾。

还有不同渠道呢?

渠道我们就用 lable 来标识一下。

最后展现格式大致如下:

yyyorder_created_total{appkey="mt",opreator="cw"} 1
yyyorder_canceled_total{appkey="pdd",opreator="cw"} 2

这里也要注意一个问题,确定指标的时候,也要避免定义太多指标出来,如果可以,考虑用label去进行区分同性质的内容。

业务埋点

在明确了业务指标之后,就要在对应的业务上去进行埋点操作,会对业务代码有一定的侵入性,当然如果业务代码写得足够好,耦合的东西少,或许可以借助AOP来埋点,从而降低侵入性。

后面就写个简单的例子来模拟业务埋点这一块。

创建一个ASP.NET Core的项目,并安装prometheus-net.AspNetCore这个nuget包。

<ItemGroup>
<PackageReference Include="prometheus-net.AspNetCore" Version="3.6.0" />
</ItemGroup>

其次是启用 ASP.NET Core exporter middleware

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting();
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
// 这一句。
endpoints.MapMetrics();
endpoints.MapControllers();
});
}

最后就是埋点了。

[ApiController]
[Route("")]
public class HomeController : ControllerBase
{
private static readonly Counter OrderCreatedCount = Metrics
.CreateCounter("yyyorder_created_total", "Number of created orders.", new CounterConfiguration
{
LabelNames= new [] { "appkey", "opreator" }
}); private static readonly Counter OrderCanceledCount = Metrics
.CreateCounter("yyyorder_canceled_total", "Number of canceled orders.", new CounterConfiguration
{
LabelNames = new[] { "appkey", "opreator" }
}); [HttpGet]
public string Get()
{
var appKeys = new[] { "ali", "pdd", "mt" };
var opreators = new[] { "cw", "pz" }; var rd = new Random((int)DateTimeOffset.Now.ToUnixTimeMilliseconds()).Next(0, 2000);
var appKeyidx = rd % 3;
var opreatoidx = rd % 2;
OrderCreatedCount.WithLabels(appKeys[appKeyidx], opreators[opreatoidx]).Inc(); var cRd = new Random((int)DateTimeOffset.Now.ToUnixTimeMilliseconds()).NextDouble(); if (cRd < 0.3d)
{
OrderCanceledCount.WithLabels(appKeys[appKeyidx], opreators[opreatoidx]).Inc();
} return "ok";
}
}

上面这个控制器中,创建了两个Counter,就是上面确定业务指标中定义好的。

这里是每访问一次,就创建一个订单,同时生成一个随机数,如果是小于0.3,那么就当它是退单的,这样就可以把两种指标都模拟出来了。

程序刚启动是有部分默认指标的。

当我们访问埋点的地址后,可以发现我们自定义的业务指标也已经有数据了。

到这里,数据已经有了,我们要怎么呈现呢?

要想呈现数据,我们需要先让prometheus来保存我们的业务指标数据。

数据写入

把数据写入prometheus有两钟方式,一种是pull,一种是push。

pull是让prometheus主动去拉取我们产生的数据,只要我们暴露一个地址出来即可,这中也是比较推荐的做法。

push方式要借助pushgateway,埋点数据要先主动推送到pushgateway,后面在由pushgateway把数据写进prometheus。

默认情况下,当我们用了endpoints.MapControllers();之后,就会把数据暴露在 http://ip:port/metrics 这个地址上。

知道要用pull的方式后,还要做什么呢?当然就是要去配置promethues了。

前面我们的 scrape_configs 是通过文件去自动发现的,所以只要在挂载的路径上面加一个对应的yml文件就可以了。

老黄这里加了一个nc-service.yml,具体内容如下:

- labels:
service: nc
project: demo
targets:
- 192.168.1.103:9874
- 192.168.1.103:9875

这个时候就可以在Targets里面看到我们这两个地址的信息了。

通过prometheus的默认界面,也可以发现数据已经正常读取了。

后面就是真正的数据查询和展示了。

数据展示

通过上面的步骤,我们已经保证数据可以正常写入和查询了,现在就在grafana中创建一个业务监控看板了。

在grafana中先配置我们的数据源。

这里填上我们prometheuse的地址保存就可以了,可以看到那个绿色的提示,告诉我们这个数据源是正常工作的了。

先来一个总的订单数。

创建一个新的dashboard,再创建一个Panel。

我们在panel中填写我们的信息还有就是选择要的图形。

然后就是写上查询条件,就可以看到我们要的结果了。

订单总数这个查询如下:

sum(ceil(increase(yyyorder_created_total[1d])))

里面用到了, sum、ceil、increase这三个函数。

其中 increase 是用来统计一段时间范围内的增量。后面带了 [1d] 这个范围表明这里是查看1天内的增量。

ceil是用来把increase的结果进行四舍五入的,可能有人会好奇,怎么还会要四舍五入呢?

看看下面这个图,大家就会发现,非常多的小数点。

其实这个和prometheus的统计方法是有关系的,这里不展开,先这样用着。

sum 这个是用来求和的,指标中还包含了很多label,我们还要把每个label的求和,才是真正的结果。

所以这里就得到了下面这个结果。

退单总数的查询和订单总数一样,只是把名字换成退单的即可。

sum(ceil(increase(yyyorder_canceled_total[1d])))

再来看看各渠道的订单统计。

既然是看各渠道的统计,那么这里就要用到前面定义好的label了。appkey代表的就是渠道,那么我们基于它去分一下组就可以了。

就得到下面的查询。

sum by (appkey) (ceil(increase (yyyorder_created_total[1d])))

结果如下:

同理,各渠道退单的也是一样的写法

sum by (appkey) (ceil(increase (yyyorder_canceled_total[1d])))

ps: 如果想把订单和退单的放在一个图里面,可以加多个查询。

示例如下:

现在有了所有渠道的总量,各个渠道独立的总量,那么我们有办法知道某个时间段的趋势吗?

这个是肯定有的,且听老黄慢慢道来。

有上面这个疑问,多半是经历过,某个时间段量非常多,但是有的时间段又几乎为零,玩的就是心跳呀。

我们可以把这个称之为时间段内的订单增长情况。

这里需要用到rate函数,这个就是帮助我们统计增长速率的函数。

它统计的是每秒的平均增长率,这个粒度有点太细,所以我们会在这个基础上乘以60,放大到一分钟。

然后在看它sum的结果,最后才四舍五入。

ceil(sum(rate(yyyorder_created_total[5m]) * 60))

结果如下:

从这个结果可以看出,订单大部分时间都没有增长,只在中间那个时间段,有部分单进来。

到这里主要的各个小panel已经完成了,剩下的就是在dashboard里面调整位置,大小那些了。

总结

这样打造出来的监控看板还是挺不错的,不过还是要注意下面几个问题的

  1. prometheus是把数据存储在本地的,总是会达到上限的,这里要么是定期删,要么是写到远程存储。
  2. prometheus自己独立的查询语法可能刚开始会比较不适应,查不出自己想要的结果,这里多查查资料,多实践基本问题也不大。
  3. 业务埋点这一个块,还是要尽可能的减少对现有业务代码的侵入性。
  4. 业务指标一定要确定好,不然埋点痛苦,查询也痛苦。

这里还没有涉及到告警相关的内容,后面有时间再写一个告警相关的。

文中示例代码:

https://github.com/catcherwong-archive/2020/tree/master/08/PromDemo

本文首发于我的个人公众号 不才老黄 ,不定期发布一些内容,有兴趣的可以关注一下哟!

基于Prometheus和Grafana打造业务监控看板的更多相关文章

  1. 基于Prometheus和Grafana的监控平台 - 运维告警

    通过前面几篇文章我们搭建好了监控环境并且监控了服务器.数据库.应用,运维人员可以实时了解当前被监控对象的运行情况,但是他们不可能时时坐在电脑边上盯着DashBoard,这就需要一个告警功能,当服务器或 ...

  2. Golang 基于Prometheus Node_Exporter 开发自定义脚本监控

    Golang 基于Prometheus Node_Exporter 开发自定义脚本监控 公司是今年决定将一些传统应用从虚拟机上迁移到Kubernetes上的,项目多而乱,所以迁移工作进展缓慢,为了建立 ...

  3. 基于 prometheus 的微服务指标监控

    基于prometheus的微服务指标监控 服务上线后我们往往需要对服务进行监控,以便能及早发现问题并做针对性的优化,监控又可分为多种形式,比如日志监控,调用链监控,指标监控等等.而通过指标监控能清晰的 ...

  4. [转帖] 基于telegraf, influxdb, grafana 建立 esxi 监控

    [系统集成] 基于telegraf, influxdb, grafana 建立 esxi 监控 https://www.cnblogs.com/hahp/p/7677420.html 之前在 nagi ...

  5. incubator-dolphinscheduler 如何在不写任何新代码的情况下,能快速接入到prometheus和grafana中进行监控

    一.prometheus和grafana 简介 prometheus是由谷歌研发的一款开源的监控软件,目前已经贡献给了apache 基金会托管. 监控通常分为白盒监控和黑盒监控之分. 白盒监控:通过监 ...

  6. 远见而明察近观若明火|Centos7.6环境基于Prometheus和Grafana结合钉钉机器人打造全时监控(预警)Docker容器服务系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_181 我们知道,奉行长期主义的网络公司,势必应在软件开发流程管理体系上具备规范意识,即代码提交有CR(CodeReview),功能 ...

  7. 基于Prometheus和Grafana的监控平台 - 环境搭建

    相关概念 微服务中的监控分根据作用领域分为三大类,Logging,Tracing,Metrics. Logging - 用于记录离散的事件.例如,应用程序的调试信息或错误信息.它是我们诊断问题的依据. ...

  8. 基于Prometheus搭建SpringCloud全方位立体监控体系

    前提 最近公司在联合运维做一套全方位监控的系统,应用集群的技术栈是SpringCloud体系.虽然本人没有参与具体基础架构的研发,但是从应用引入的包和一些资料的查阅大致推算出具体的实现方案,这里做一次 ...

  9. Prometheus+Grafana打造Mysql监控平台

    prometheus/node_exporter/mysqld_exporter都是由go语言编写,需要先安装GoLang环境 下载node_exporter(监控服务器的CPU.内存.存储使用情况) ...

随机推荐

  1. 面试题之----禁掉cookie的session使用方案

    方式一:通过 url 传值,把session id附加到url上 缺点:整个站点中不能有纯静态页面,因为纯静态页面session id 将无法继续传到下一页面 方式二:通过隐藏表单,把session ...

  2. Java 匿名对象、内部类

    一.匿名对象 1.概念 匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量. public class Person{ public void eat(){ System.o ...

  3. Kali小技巧

    说明:此方法适用于Debian.Ubuntu等带apt工具的操作系统. sudo apt-get autoremove --purge 软件名 # 命令&参数解释: # sudo--获取 ro ...

  4. KMP算法图解

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

  5. html实现a元素href的URL链接自动刷新或新窗口打开

    有时我们想实现这样一个功能,点击一个链接,如果这个链接浏览器已经打开过,则刷新已经打开的链接窗口:如果这个链接没有打开过,则使用新窗口打开这个链接页面. 这是一个非常好的体验增强功能,可以有效避免浏览 ...

  6. darkbzoj #3759. Hungergame 博弈论 线性基 NIM

    LINK:Hungergame 放上一道简单题 复习一下. 考虑每次可以打开任意多个盒子 如果全打开了 那么就是一个NIM游戏了. 如果发现局面是异或为0的时候此时先手必胜了. 考虑局面不全体异或为0 ...

  7. luogu P5892 [IOI2014]holiday 假期 决策单调性优化dp 主席树

    LINK:holiday 考虑第一个subtask. 容易想到n^2暴力枚举之后再暴力计算答案. 第二个subtask 暴力枚举终点可以利用主席树快速统计答案. 第三个subtask 暴力枚举两端利用 ...

  8. Idea Live Temlpates 自定义代码

    Idea Live Temlpates 自定义代码 目的 - 加快常用代码的书写 使用## 打开Settings 快捷键Ctrl+Alt+S 选中Live Templates 选中temlpates ...

  9. 027_go语言中的通道选择器

    代码演示 package main import "fmt" import "time" func main() { c1 := make(chan strin ...

  10. Azure DevOps+Docker+Asp.NET Core 实现CI/CD(一 .简介与创建自己的代理池)

    前言 本文主要是讲解如何使用Azure DevOps+Docker 来实现持续集成Asp.NET Core项目(当然 也可以是任意项目). 打算用三个篇幅来记录完整的全过程 觉得有帮助的朋友~可以左上 ...