经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
使用Prometheus搞定微服务监控
来源:cnblogs  作者:Kevin Wan  时间:2021/3/1 16:33:58  对本文有异议

最近对服务进行监控,而当前监控最流行的数据库就是 Prometheus,同时 go-zero 默认接入也是这款数据库。今天就对 go-zero 是如何接入 Prometheus ,以及开发者如何自己定义自己监控指标。

监控接入

go-zero 框架中集成了基于 prometheus 的服务指标监控。但是没有显式打开,需要开发者在 config.yaml 中配置:

  1. Prometheus:
  2. Host: 127.0.0.1
  3. Port: 9091
  4. Path: /metrics

如果开发者是在本地搭建 Prometheus,需要在 Prometheus 的配置文件 prometheus.yaml 中写入需要收集服务监控信息的配置:

  1. - job_name: 'file_ds'
  2. static_configs:
  3. - targets: ['your-local-ip:9091']
  4. labels:
  5. job: activeuser
  6. app: activeuser-api
  7. env: dev
  8. instance: your-local-ip:service-port

因为本地是用 docker 运行的。将 prometheus.yaml 放置在 docker-prometheus 目录下:

  1. docker run -p 9090:9090 -v dockeryml/docker-prometheus:/etc/prometheus prom/prometheus

打开 localhost:9090 就可以看到:

点击 http://service-ip:9091/metrics 就可以看到该服务的监控信息:

上图我们可以看出有两种 bucket,以及 count/sum 指标。

go-zero 是如何集成监控指标?监控的又是什么指标?我们如何定义我们自己的指标?下面就来解释这些问题

以上的基本接入,可以参看我们的另外一篇:https://zeromicro.github.io/go-zero/service-monitor.html

如何集成

上面例子中的请求方式是 HTTP,也就是在请求服务端时,监控指标数据不断被搜集。很容易想到是 中间件 的功能,具体代码:https://github.com/tal-tech/go-zero/blob/master/rest/handler/prometheushandler.go。

  1. var (
  2. metricServerReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
  3. ...
  4. // 监控指标
  5. Labels: []string{"path"},
  6. // 直方图分布中,统计的桶
  7. Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 1000},
  8. })
  9. metricServerReqCodeTotal = metric.NewCounterVec(&metric.CounterVecOpts{
  10. ...
  11. // 监控指标:直接在记录指标 incr() 即可
  12. Labels: []string{"path", "code"},
  13. })
  14. )
  15. func PromethousHandler(path string) func(http.Handler) http.Handler {
  16. return func(next http.Handler) http.Handler {
  17. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  18. // 请求进入的时间
  19. startTime := timex.Now()
  20. cw := &security.WithCodeResponseWriter{Writer: w}
  21. defer func() {
  22. // 请求返回的时间
  23. metricServerReqDur.Observe(int64(timex.Since(startTime)/time.Millisecond), path)
  24. metricServerReqCodeTotal.Inc(path, strconv.Itoa(cw.Code))
  25. }()
  26. // 中间件放行,执行完后续中间件和业务逻辑。重新回到这,做一个完整请求的指标上报
  27. // [??:洋葱模型]
  28. next.ServeHTTP(cw, r)
  29. })
  30. }
  31. }

其实整个很简单:

  1. HistogramVec 负责请求耗时搜集:
    • bucket 存放的就是 option 指定的耗时指标。某个请求耗时多少就会被聚集对应的桶,计数。
    • 最终展示的就是一个路由在不同耗时的分布,很直观提供给开发者可以优化的区域。
  2. CounterVec 负责指定 labels 标签搜集:
    • Labels: []string{"path", "code"}
    • labels 相当一个 tuplego-zero 是以(path, code)作为整体,记录不同路由不同状态码的返回次数。如果 4xx,5xx过多的时候,是不是应该看看你的服务健康程度?

如何自定义

go-zero 中也提供了 prometheus metric 基本封装,供开发者自己开发自己 prometheus 中间件。

代码:https://github.com/tal-tech/go-zero/tree/master/core/metric

名称 用途 搜集函数
CounterVec 单一的计数。用做:QPS统计 CounterVec.Inc() 指标+1
GuageVec 单纯指标记录。适用于磁盘容量,CPU/Mem使用率(可增加可减少) GuageVec.Inc()/GuageVec.Add() 指标+1/指标加N,也可以为负数
HistogramVec 反应数值的分布情况。适用于:请求耗时、响应大小 HistogramVec.Observe(val, labels) 记录指标当前对应值,并找到值所在的桶,+1

另外对 HistogramVec.Observe() 做一个基本分析:

我们其实可以看到上图每个 HistogramVec 统计都会有3个序列出现:

  • _count:数据个数
  • _sum:全部数据加和
  • _bucket{le=a1}:处于 [-inf, a1] 的数据个数

所以我们也猜测在统计过程中,分3种数据进行统计:

  1. // 基本上在prometheus的统计都是使用 atomic CAS 方式进行计数的
  2. // 性能要比使用 Mutex 要高
  3. func (h *histogram) observe(v float64, bucket int) {
  4. n := atomic.AddUint64(&h.countAndHotIdx, 1)
  5. hotCounts := h.counts[n>>63]
  6. if bucket < len(h.upperBounds) {
  7. // val 对应数据桶 +1
  8. atomic.AddUint64(&hotCounts.buckets[bucket], 1)
  9. }
  10. for {
  11. oldBits := atomic.LoadUint64(&hotCounts.sumBits)
  12. newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
  13. // sum指标数值 +v(毕竟是总数sum)
  14. if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) {
  15. break
  16. }
  17. }
  18. // count 统计 +1
  19. atomic.AddUint64(&hotCounts.count, 1)
  20. }

所以开发者想定义自己的监控指标:

  1. 在使用 goctl 生成API代码指定要生成的 中间件https://zeromicro.github.io/go-zero/middleware.html
  2. 在中间件文件书写自己需要统计的指标逻辑
  3. 当然,开发者也可以在业务逻辑中书写统计的指标逻辑。同上。

上述都是针对 HTTP 部分逻辑的解析,RPC 部分的逻辑类似,你可以在 拦截器 部分看到设计。

总结

本文分析了 go-zero 服务监控指标的逻辑,当然对于一些基础设施的监控,prometheus 可以通过引入对应的 exporter 来完成。

项目地址

https://github.com/tal-tech/go-zero

欢迎使用 go-zero 并 star 支持我们!

go-zero 系列文章见『微服务实践』公众号

原文链接:http://www.cnblogs.com/kevinwan/p/14463445.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号