针对中小型项目,介绍一下简单的 Prometheus 监控方案。

Prometheus 帮助我们解决了 Metrics 监控的难题,后续出现的 Thanos 解决了 Prometheus 存储扩展的难题。总体来说,Prometheus 已经是一个非常成熟的监控方案。 各大云厂商也相继推出了云版本的 Prometheus,用户可以不用去考虑如何运维 Prometheus,降低了人工运维成本。

既然 Prometheus 的运行问题已经得到解决,接下来就看看,如何使用它。

棘手的问题

Prometheus 的 Client 接口设计的很合理,使用上也没什么问题。随之会出现几个棘手的问题。

  • 监控什么
  • 代码里怎么写监控指标,Label 该怎么带
  • 怎么配置图形化

不要小看这个问题,监控什么跟设计 API 一样不是一件容易的事。如果我们强行往代码里【塞入】Prometheus 监控相关代码,我敢保证,代码会很乱。

举个例子,监控一个函数运行了多长时间,我们要做如下几个事。

  • 合理命名监控项
  • 合理配置 Label
  • 代码里嵌入计时代码
  • 处理错误逻辑
  • 图像化

光上面几个逻辑,至少需要20+行代码,如果每个函数都是如此,整个项目的代码会非常【难看】。

对于追求【干净,简介】代码的我们来说,这是一个难受的体验。

干净的解决方案

这里我们介绍 rk-boot/v2 + Prometheus + Grafana 的解决方案。这个方案里,我们使用两个方法解决上述棘手的问题。

简单来说,就是在函数里面添加两行代码,监控这个函数。

  • Wrap Prometheus 相关逻辑
  • 现成 Grafana 图表

代码干净

Golang 不像 Spring 一样有 annotation 的支持,可以在函数上面标记一个 @xxx 可以轻松实现函数监控。不过,我们可以在代码里添加【两行代码】,以最低成本实现函数监控。

现成图表(Grafana)

有一个通用 Grafana 监控 Dashboard 是一个很幸福的事情,毕竟上手 Grafana 不是几个小时就能搞定的事情。

Demo

1.Docker 启动 Prometheus

我们需要创建一个 prometheus.yml 文件,告诉 prometheus 从哪里收集监控数据。

  • prometheus.yml
  • 启动 Prometheus

2.使用 Docker 启动 grafana 并配置 Prometheus

初始化账号: admin

初始化密码:admin



  • 选择 Prometheus 为数据源



  • 配置 Prometheus 地址



3.下载 rk-boot/v2

rk-boot/v2 是可以通过 YAML 文件启动 Golang 流行框架的依赖库,里面包含了很多实用中间件。

为了模拟微服务,我们同时还下载 rk-gin/v2 来启动 gin-gonic 服务。

4.配置 boot.yaml

boot.yaml 文件告诉 rk-boot/v2 启动哪些 Gin 配套的服务。

5.写个 API

6.启动 main.go & 发送请求

7.查看图形化监控

boot.yaml 文件告诉 Gin 启动 API 监控中间件,所以我们可以监控两个东西。

rk-prom: 自动记录每个 API 的 Metrics,有默认 grafana dashboard rk-cursor: 代码里嵌入的监控(就是我们写的那两行代码),有默认 grafana dashboard

  • 引入 rk-prom dashboard (代号:15111):







我们可以看到 API 的监控了,不需要任何代码改动。



  • 引入 rk-cursor dashboard (代号:15937):



我们可以看到 Cursor 的监控了



8.解释一下 rk-prom & rk-cursor dashboard

rk-prom 是一个自带的监控中间件,会默认监控所有 API 的运行时间,错误码。包含的监控项有【运行时间】,【API 可用性】,【API 速率】

如果想要看到本地的输出的监控数据,可以查看 localhost:8080/metrics

rk-cursor 是一个 struct,通过 Click() 方法获取一个 Pointer struct,再通过 pointer.Release() 方法结束监控。 会默认监控所有 API 的运行时间,错误码。包含的监控项有【Function 运行时间】,【Function 可用性】,【Function 速率】。

rk-cursor 使用方法

rk-cursor 可以实现如下三个监控。

  • 监控 Function 运行时间
  • 监控 Function 错误
  • 监控 Function 里调用其他 Function 的运行时间(相当于 1层的调用链)

监控 Function 错误

对于上面的代码进行一行改动。

再运行一次,发送请求,并观察日志和 grafana dashboard



监控 Function 调用链

rk-cursor 会使用 runtime.Caller() 函数记录上一层调用函数的名字。

举个例子,Greeter() 函数调用 B() 函数和 C() 函数,那么我们可以观察 Greeter() 函数的里,B() 和 C() 花了多尝试时间。

我们稍微修改一下 main.go

这个例子里,函数的入口是 main.Greeter(),这个函数的 parentOperation 标记为 -



main.Greeter() 调用了 B() 和 C(),在 parentOperation 里选择 main.Greeter(),我们就可以看到,1层的调用链。