timex,time吸烟神曲完整版

  

  最近一直在监控服务,Prometheus是目前被监控最多的数据库,go-zero的默认访问也是这个数据库。今天go-zero如何接入普罗米修斯,开发者如何定义自己的监控指标。   

  

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

  

  Prometheus 3360主机3360 127.0.0.1端口3360 9091路径:/metrics如果开发者在本地构建Prometheus,需要在Prometheus的配置文件prometheus.yaml中写需要收集服务监控信息的配置:   

  

  -job _ name : ' file _ ds ' static _ configs :-targets : ' your-local-IP :9091 ' labels : job : active user app : active user-API env : Instance : your-local-IP : service-port因为本地正在运行docker。将prometheus.yaml放在docker-prometheus目录中:   

  

  Docker Run \-p 909033609090 \-v Docker YML/Docker-Prometheus 3360/etc/Prometheus \ Prometheus打开localhost:9090可以看到:   

  

     

  

  点击http://service-IP 33609091/metrics查看该服务的监控信息:   

  

     

  

  在上图中,我们可以看到有两种桶,以及计数/总和指示器。   

  

  那么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   

  

  Var(公制serverreqdur=公制。Newhistogramvec(公制。直方图{.//监控指标Labels: string{'path'},//在直方图分布中,统计桶Buckets : float 64 { 5,10,25,50,100,250,500,1000},})MetricServerReQCodeTotal=metric。NewCountervec(公制。抵消费用.//监控指标:只记录指标incr()和Labels:string {'path ',' code'},}))func PromethousHandler(path string)func(http。处理程序)http。Handler { return func(next http。处理程序)http。处理程序{ return http。HandlerFunc(func(w http。ResponseWriter。Request) {//请求条目的时间start Time 3360=timer . now()CW 3360=security . withcoderesponsewriter { Writer 3360 w } defer func(){//请求返回的时间为MetricServerReqdur。观察(Int64 (Timex。自(开始时间)/时间。Millicent),PATH)metricserverreqcodetotal . Inc(PATH   

, strconv.Itoa(cw.Code)) }() // 中间件放行,执行完后续中间件和业务逻辑。重新回到这,做一个完整请求的指标上报 // <:洋葱模型> next.ServeHTTP(cw, r) }) }}其实整个很简单:

  

HistogramVec 负责请求耗时搜集:bucket 存放的就是 option 指定的耗时指标。某个请求耗时多少就会被聚集对应的桶,计数。最终展示的就是一个路由在不同耗时的分布,很直观提供给开发者可以优化的区域。CounterVec 负责指定 labels 标签搜集:Labels: <>string{"path", "code"}labels 相当一个 tuple。go-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() 指标+1GuageVec单纯指标记录。适用于磁盘容量,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种数据进行统计:

  

// 基本上在prometheus的统计都是使用 atomic CAS 方式进行计数的// 性能要比使用 Mutex 要高func (h *histogram) observe(v float64, bucket int) { n := atomic.AddUint64(&h.countAndHotIdx, 1) hotCounts := h.counts if bucket < len(h.upperBounds) { // val 对应数据桶 +1 atomic.AddUint64(&hotCounts.buckets, 1) } for { oldBits := atomic.LoadUint64(&hotCounts.sumBits) newBits := math.Float64bits(math.Float64frombits(oldBits) + v) // sum指标数值 +v(毕竟是总数sum) if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { break } } // count 统计 +1 atomic.AddUint64(&hotCounts.count, 1)}所以开发者想定义自己的监控指标:

  

在使用 goctl 生成API代码指定要生成的 中间件:https://zeromicro.github.io/go-zero/middleware.html在中间件文件书写自己需要统计的指标逻辑当然,开发者也可以在业务逻辑中书写统计的指标逻辑。同上。上述都是针对 HTTP 部分逻辑的解析,RPC 部分的逻辑类似,你可以在 拦截器 部分看到设计。

  

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

  

项目地址https://github.com/tal-tech/go-zero

  

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

  

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

相关文章