<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用go-metrics在Go應(yīng)用中增加度量

          共 4159字,需瀏覽 9分鐘

           ·

          2021-10-17 11:53

          Go語(yǔ)言內(nèi)置expvar,基于expvar提供的對(duì)基礎(chǔ)度量的支持能力,我們可以自定義各種度量(metrics)。但是expvar僅僅是提供了最底層的度量定義支持,對(duì)于一些復(fù)雜的度量場(chǎng)景,第三方或自實(shí)現(xiàn)的metrics包必不可少。

          go-metrics包是Go領(lǐng)域使用較多的metrics包,該包是對(duì)Java社區(qū)依舊十分活躍的Coda Hale's Metrics library[2]的不完全Go移植(不得不感慨一下:Java的生態(tài)還真是強(qiáng)大)。因此該包在概念上與Coda Hale's Metrics library是基本保持一致的。go-metrics包在文檔方面做的還不夠,要理解很多概念性的東西,我們還得回到Coda Hale's Metrics library的項(xiàng)目文檔[3]去挖掘。

          go-metrics這樣的包是純工具類的包,沒有太多“燒腦”的地方,只需要會(huì)用即可,這篇文章我們就來簡(jiǎn)單地看看如何使用go-metrics在Go應(yīng)用中增加度量。

          1. go-metrics的結(jié)構(gòu)

          go-metrics在度量指標(biāo)組織上采用了與Coda Hale's Metrics library相同的結(jié)構(gòu),即使用Metrics Registry(Metrics注冊(cè)表)。Metrics注冊(cè)表是一個(gè)度量指標(biāo)的集合:

          ?????????????????????????????┌─────────────┐
          ?????????????????????????????│?????????????│
          ??????????????????????┌──────┤????metric1??│
          ??????????????????????│??????│?????????????│
          ??????????????????????│??????└─────────────┘
          ??????????????????????│
          ??????????????????????│
          ┌─────────────────┐???│??????┌─────────────┐
          │?????????????????├───┘??????│?????????????│
          │?????????????????│??????????│????metric2??│
          │?????Registry????├──────────┤?????????????│
          │?????????????????│??????????└─────────────┘
          │?????????????????├───────┐
          │?????????????????│???????│
          └──────────────┬──┘???????│??┌─────────────┐
          ???????????????│??????????│??│?????????????│
          ???????????????│??????????└──┤????metric3??│
          ???????????????│?????????????│?????????????│
          ???????????????│?????????????└─────────────┘
          ???????????????│???????????????????...?...
          ???????????????│?????????????┌─────────────┐
          ???????????????│?????????????│?????????????│
          ???????????????└─────────────┤????metricN??│
          ?????????????????????????????│?????????????│
          ?????????????????????????????└─────────────┘????????????

          go-metrics包將Metrics注冊(cè)表的行為定義為了一個(gè)接口類型:

          //?https://github.com/rcrowley/go-metrics/blob/master/registry.go
          type?Registry?interface?{

          ????//?Call?the?given?function?for?each?registered?metric.
          ????Each(func(string,?interface{}))

          ????//?Get?the?metric?by?the?given?name?or?nil?if?none?is?registered.
          ????Get(string)?interface{}

          ????//?GetAll?metrics?in?the?Registry.
          ????GetAll()?map[string]map[string]interface{}

          ????//?Gets?an?existing?metric?or?registers?the?given?one.
          ????//?The?interface?can?be?the?metric?to?register?if?not?found?in?registry,
          ????//?or?a?function?returning?the?metric?for?lazy?instantiation.
          ????GetOrRegister(string,?interface{})?interface{}

          ????//?Register?the?given?metric?under?the?given?name.
          ????Register(string,?interface{})?error

          ????//?Run?all?registered?healthchecks.
          ????RunHealthchecks()

          ????//?Unregister?the?metric?with?the?given?name.
          ????Unregister(string)

          ????//?Unregister?all?metrics.??(Mostly?for?testing.)
          ????UnregisterAll()
          }

          并提供了一個(gè)Registry的標(biāo)準(zhǔn)實(shí)現(xiàn)類型StandardRegistry:

          //?https://github.com/rcrowley/go-metrics/blob/master/registry.go
          type?StandardRegistry?struct?{
          ????metrics?map[string]interface{}
          ????mutex???sync.RWMutex
          }

          我們看到StandardRegistry使用map結(jié)構(gòu)來組織metrics。我們可以通過NewRegistry函數(shù)創(chuàng)建了一個(gè)基于StandardRegistry的Registry實(shí)例:

          //?https://github.com/rcrowley/go-metrics/blob/master/registry.go
          func?NewRegistry()?Registry?{
          ????return?&StandardRegistry{metrics:?make(map[string]interface{})}
          }

          和標(biāo)準(zhǔn)庫(kù)的flag或log包的設(shè)計(jì)方式類似,go-metrics包也在包層面上提供了默認(rèn)的StandardRegistry實(shí)例:DefaultRegistry,這樣大多數(shù)情況直接使用DefaultRegistry實(shí)例即可滿足你的需求:

          //?https://github.com/rcrowley/go-metrics/blob/master/registry.go
          var?DefaultRegistry?Registry?=?NewRegistry()

          一旦有了默認(rèn)Registry實(shí)例,我們通常使用下面goroutine并發(fā)安全的包級(jí)函數(shù)GetOrRegister來注冊(cè)或獲取某個(gè)度量指標(biāo):

          //?https://github.com/rcrowley/go-metrics/blob/master/registry.go
          func?GetOrRegister(name?string,?i?interface{})?interface{}?{
          ????return?DefaultRegistry.GetOrRegister(name,?i)
          }

          2. go-metrics的度量類型

          go-metrics繼承了其前身Coda Hale's Metrics library所支持的幾種基本的度量類型,它們是Gauges、Counters、Histograms、Meters和Timers。下面我們就針對(duì)這幾種基本度量類型逐一說明一下其含義和使用方法。

          1) Gauge

          Gauge是對(duì)一個(gè)數(shù)值的即時(shí)測(cè)量值,其反映一個(gè)值的瞬時(shí)快照,比如我們要度量當(dāng)前隊(duì)列中待發(fā)送消息數(shù)量、當(dāng)前應(yīng)用程序啟動(dòng)的goroutine數(shù)量,都可以用Gauge這種度量類型實(shí)現(xiàn)。

          下面的例子使用一個(gè)Gauge度量類型度量程序當(dāng)前啟動(dòng)的goroutine數(shù)量:

          //?gauge.go
          package?main

          import?(
          ?"fmt"
          ?"net/http"
          ?"runtime"
          ?"time"

          ?"github.com/rcrowley/go-metrics"
          )

          func?main()?{
          ?g?:=?metrics.NewGauge()
          ?metrics.GetOrRegister("goroutines.now",?g)
          ?http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{
          ?})

          ?go?func()?{
          ??t?:=?time.NewTicker(time.Second)
          ??for?{
          ???select?{
          ???case?<-t.C:
          ????c?:=?runtime.NumGoroutine()
          ????g.Update(int64(c))
          ????fmt.Println("goroutines?now?=",?g.Value())
          ???}
          ??}
          ?}()
          ?http.ListenAndServe(":8080",?nil)
          }

          啟動(dòng)該程序,并用hey工具[4]發(fā)起http請(qǐng)求,我們看到如下輸出:

          $hey?-c?5?-n?1000000?-m?GET?http://127.0.0.1:8080

          $go?run?gauge.go
          goroutines?now?=?9
          goroutines?now?=?10
          goroutines?now?=?7
          goroutines?now?=?8
          goroutines?now?=?7
          goroutines?now?=?7
          ...?...

          go-metrics包提供了將Registry中的度量指標(biāo)格式化輸出的接口,我們可以使用該接口將指標(biāo)情況輸出出來,而無需自行輸出log,比如上面例子可以改造為下面這樣:

          //?gauge1.go
          package?main

          import?(
          ?"log"
          ?"net/http"
          ?"runtime"
          ?"time"

          ?"github.com/rcrowley/go-metrics"
          )

          func?main()?{
          ?g?:=?metrics.NewGauge()
          ?metrics.GetOrRegister("goroutines.now",?g)
          ?go?metrics.Log(metrics.DefaultRegistry,?time.Second,?log.Default())
          ?http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{
          ?})

          ?go?func()?{
          ??t?:=?time.NewTicker(time.Second)
          ??for?{
          ???select?{
          ???case?<-t.C:
          ????c?:=?runtime.NumGoroutine()
          ????g.Update(int64(c))
          ???}
          ??}
          ?}()
          ?http.ListenAndServe(":8080",?nil)
          }

          同樣方式運(yùn)行上面gauge1.log:

          $go?run?gauge1.go
          2021/07/04?09:42:58?gauge?goroutines.now
          2021/07/04?09:42:58???value:??????????????10
          2021/07/04?09:42:59?gauge?goroutines.now
          2021/07/04?09:42:59???value:???????????????9
          2021/07/04?09:43:00?gauge?goroutines.now
          2021/07/04?09:43:00???value:???????????????9
          2021/07/04?09:43:01?gauge?goroutines.now
          2021/07/04?09:43:01???value:??????????????10
          ...?...

          go-metrics包的Log函數(shù)必須放在一個(gè)單獨(dú)的goroutine中執(zhí)行,否則它將阻塞調(diào)用它的goroutine的繼續(xù)執(zhí)行。但Log函數(shù)也是goroutine安全的,其每次輸出度量值時(shí)其實(shí)輸出的都是Registry中各個(gè)度量值的“快照副本”:

          //?https://github.com/rcrowley/go-metrics/blob/master/registry.go
          func?(r?*StandardRegistry)?Each(f?func(string,?interface{}))?{
          ????metrics?:=?r.registered()
          ????for?i?:=?range?metrics?{
          ????????kv?:=?&metrics[i]
          ????????f(kv.name,?kv.value)
          ????}
          }

          func?(r?*StandardRegistry)?registered()?[]metricKV?{
          ????r.mutex.RLock()
          ????defer?r.mutex.RUnlock()
          ????metrics?:=?make([]metricKV,?0,?len(r.metrics))
          ????for?name,?i?:=?range?r.metrics?{
          ????????metrics?=?append(metrics,?metricKV{
          ????????????name:??name,
          ????????????value:?i,
          ????????})
          ????}
          ????return?metrics
          }

          對(duì)于Gauge這類的季世志度量,就像上面代碼那樣,我們都是通過Update直接設(shè)置其值的。

          2) Counter

          Counter顧名思義計(jì)數(shù)器!和Gauge相比,其提供了指標(biāo)增減方法Inc和Dec,如下面代碼:

          //?https://github.com/rcrowley/go-metrics/blob/master/counter.go
          type?Counter?interface?{
          ????Clear()
          ????Count()?int64
          ????Dec(int64)
          ????Inc(int64)
          ????Snapshot()?Counter
          }

          計(jì)數(shù)是日常使用較多的度量場(chǎng)景,比如一個(gè)服務(wù)處理的請(qǐng)求次數(shù)就十分適合用計(jì)數(shù)這個(gè)度量指標(biāo),下面這段代碼演示的就是這一場(chǎng)景:

          //?counter.go

          package?main

          import?(
          ?"log"
          ?"net/http"
          ?"time"

          ?"github.com/rcrowley/go-metrics"
          )

          func?main()?{
          ?c?:=?metrics.NewCounter()
          ?metrics.GetOrRegister("total.requests",?c)
          ?go?metrics.Log(metrics.DefaultRegistry,?time.Second,?log.Default())
          ?http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{
          ??c.Inc(1)
          ?})

          ?http.ListenAndServe(":8080",?nil)
          }

          在這段代碼中,我們每收到一個(gè)http request就在其對(duì)應(yīng)的處理函數(shù)中利用Counter的Inc方法增加計(jì)數(shù),運(yùn)行上述代碼:

          $go?run?counter.go
          2021/07/04?10:29:03?counter?total.requests
          ...?...
          2021/07/04?10:29:06?counter?total.requests
          2021/07/04?10:29:06???count:???????????????0
          2021/07/04?10:29:07?counter?total.requests
          2021/07/04?10:29:07???count:???????????33890
          2021/07/04?10:29:08?counter?total.requests
          2021/07/04?10:29:08???count:???????????80160
          2021/07/04?10:29:09?counter?total.requests
          2021/07/04?10:29:09???count:??????????124855
          2021/07/04?10:29:10?counter?total.requests
          2021/07/04?10:29:10???count:??????????172077
          2021/07/04?10:29:11?counter?total.requests
          2021/07/04?10:29:11???count:??????????218466
          2021/07/04?10:29:12?counter?total.requests
          2021/07/04?10:29:12???count:??????????265476
          2021/07/04?10:29:13?counter?total.requests
          2021/07/04?10:29:13???count:??????????309153
          ...?...

          3) Meter

          Meter這個(gè)類型用于測(cè)量一組事件發(fā)生的速度,比如:web服務(wù)的平均處理性能(條/秒),除了平均值,go-metrics的Meter默認(rèn)還提供1分鐘、5分鐘和15分鐘時(shí)間段的平均速度,和top命令中的load average輸出的一分鐘、五分鐘、以及十五分鐘的系統(tǒng)平均負(fù)載類似。

          下面就是一個(gè)用Meter來測(cè)量web服務(wù)處理性能的例子:

          //?meter.go?

          package?main

          import?(
          ?"log"
          ?"net/http"
          ?"time"

          ?"github.com/rcrowley/go-metrics"
          )

          func?main()?{
          ?m?:=?metrics.NewMeter()
          ?metrics.GetOrRegister("rate.requests",?m)
          ?go?metrics.Log(metrics.DefaultRegistry,?time.Second,?log.Default())
          ?http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{
          ??m.Mark(1)
          ?})
          ?http.ListenAndServe(":8080",?nil)
          }

          我們用hey給該web server“施壓”并查看Meter度量指標(biāo)的輸出結(jié)果:

          $hey?-c?5?-n?1000000?-m?GET?http://127.0.0.1:8080

          $go?run?meter.go
          2021/07/04?10:55:59?meter?rate.requests
          2021/07/04?10:55:59???count:???????????????0
          2021/07/04?10:55:59???1-min?rate:??????????0.00
          2021/07/04?10:55:59???5-min?rate:??????????0.00
          2021/07/04?10:55:59???15-min?rate:?????????0.00
          2021/07/04?10:55:59???mean?rate:???????????0.00
          2021/07/04?10:56:00?meter?rate.requests
          2021/07/04?10:56:00???count:???????????????0
          2021/07/04?10:56:00???1-min?rate:??????????0.00
          2021/07/04?10:56:00???5-min?rate:??????????0.00
          2021/07/04?10:56:00???15-min?rate:?????????0.00
          2021/07/04?10:56:00???mean?rate:???????????0.00
          2021/07/04?10:56:01?meter?rate.requests
          2021/07/04?10:56:01???count:????????????8155
          2021/07/04?10:56:01???1-min?rate:??????????0.00
          2021/07/04?10:56:01???5-min?rate:??????????0.00
          2021/07/04?10:56:01???15-min?rate:?????????0.00
          2021/07/04?10:56:01???mean?rate:????????2718.27
          2021/07/04?10:56:02?meter?rate.requests
          2021/07/04?10:56:02???count:???????????50937
          2021/07/04?10:56:02???1-min?rate:??????????0.00
          2021/07/04?10:56:02???5-min?rate:??????????0.00
          2021/07/04?10:56:02???15-min?rate:?????????0.00
          2021/07/04?10:56:02???mean?rate:???????12734.04
          2021/07/04?10:56:03?meter?rate.requests
          2021/07/04?10:56:03???count:???????????96129
          2021/07/04?10:56:03???1-min?rate:??????19225.00
          2021/07/04?10:56:03???5-min?rate:??????19225.00
          2021/07/04?10:56:03???15-min?rate:?????19225.00
          2021/07/04?10:56:03???mean?rate:???????19225.54
          2021/07/04?10:56:04?meter?rate.requests
          2021/07/04?10:56:04???count:??????????141076
          2021/07/04?10:56:04???1-min?rate:??????19225.00
          2021/07/04?10:56:04???5-min?rate:??????19225.00
          2021/07/04?10:56:04???15-min?rate:?????19225.00
          2021/07/04?10:56:04???mean?rate:???????23512.40
          2021/07/04?10:56:05?meter?rate.requests
          2021/07/04?10:56:05???count:??????????187733
          2021/07/04?10:56:05???1-min?rate:??????19225.00
          2021/07/04?10:56:05???5-min?rate:??????19225.00
          2021/07/04?10:56:05???15-min?rate:?????19225.00
          2021/07/04?10:56:05???mean?rate:???????26818.71
          2021/07/04?10:56:06?meter?rate.requests
          2021/07/04?10:56:06???count:??????????234874
          2021/07/04?10:56:06???1-min?rate:??????19225.00
          2021/07/04?10:56:06???5-min?rate:??????19225.00
          2021/07/04?10:56:06???15-min?rate:?????19225.00
          2021/07/04?10:56:06???mean?rate:???????29358.98
          2021/07/04?10:56:07?meter?rate.requests
          2021/07/04?10:56:07???count:??????????279201
          2021/07/04?10:56:07???1-min?rate:??????19225.00
          2021/07/04?10:56:07???5-min?rate:??????19225.00
          2021/07/04?10:56:07???15-min?rate:?????19225.00
          2021/07/04?10:56:07???mean?rate:???????31022.05
          2021/07/04?10:56:08?meter?rate.requests
          2021/07/04?10:56:08???count:??????????321704
          2021/07/04?10:56:08???1-min?rate:??????21295.03
          2021/07/04?10:56:08???5-min?rate:??????19652.92
          2021/07/04?10:56:08???15-min?rate:?????19368.43
          2021/07/04?10:56:08???mean?rate:???????32170.20
          2021/07/04?10:56:09?meter?rate.requests
          2021/07/04?10:56:09???count:??????????362403
          2021/07/04?10:56:09???1-min?rate:??????21295.03
          2021/07/04?10:56:09???5-min?rate:??????19652.92
          2021/07/04?10:56:09???15-min?rate:?????19368.43
          2021/07/04?10:56:09???mean?rate:???????32945.48
          2021/07/04?10:56:10?meter?rate.requests
          2021/07/04?10:56:10???count:??????????401442
          2021/07/04?10:56:10???1-min?rate:??????21295.03
          2021/07/04?10:56:10???5-min?rate:??????19652.92
          2021/07/04?10:56:10???15-min?rate:?????19368.43
          2021/07/04?10:56:10???mean?rate:???????33453.34
          2021/07/04?10:56:11?meter?rate.requests
          2021/07/04?10:56:11???count:??????????440905
          2021/07/04?10:56:11???1-min?rate:??????21295.03
          2021/07/04?10:56:11???5-min?rate:??????19652.92
          2021/07/04?10:56:11???15-min?rate:?????19368.43
          2021/07/04?10:56:11???mean?rate:???????33915.67
          2021/07/04?10:56:12?meter?rate.requests
          2021/07/04?10:56:12???count:??????????479301
          2021/07/04?10:56:12???1-min?rate:??????21295.03
          2021/07/04?10:56:12???5-min?rate:??????19652.92
          2021/07/04?10:56:12???15-min?rate:?????19368.43
          2021/07/04?10:56:12???mean?rate:???????34235.60
          2021/07/04?10:56:13?meter?rate.requests
          2021/07/04?10:56:13???count:??????????518843
          2021/07/04?10:56:13???1-min?rate:??????22744.85
          2021/07/04?10:56:13???5-min?rate:??????19979.77
          2021/07/04?10:56:13???15-min?rate:?????19479.57
          2021/07/04?10:56:13???mean?rate:???????34589.43
          2021/07/04?10:56:14?meter?rate.requests
          2021/07/04?10:56:14???count:??????????560260
          2021/07/04?10:56:14???1-min?rate:??????22744.85
          2021/07/04?10:56:14???5-min?rate:??????19979.77
          2021/07/04?10:56:14???15-min?rate:?????19479.57
          2021/07/04?10:56:14???mean?rate:???????35016.17

          如果使用Meter度量服務(wù)的最佳性能值,那么需要有持續(xù)穩(wěn)定的“施壓”,待1、5、15分鐘速率穩(wěn)定后,這時(shí)的值才有意義。Meter的最后一項(xiàng)mean rate是平均值,即服務(wù)啟動(dòng)后處理請(qǐng)求的總量與程序運(yùn)行時(shí)間的比值。

          4) Histogram

          Histogram是直方圖,與概率統(tǒng)計(jì)學(xué)上直方圖的概念類似,go-metrics中的Histogram也是用來統(tǒng)計(jì)一組數(shù)據(jù)的統(tǒng)計(jì)學(xué)分布情況的。除了最小值(min)、最大值(max)、平均值(mean)等,它還測(cè)量中位數(shù)(median)、第75、90、95、98、99和99.9百分位數(shù)。

          直方圖可以用來度量事件發(fā)生的數(shù)據(jù)分布情況,比如:服務(wù)器處理請(qǐng)求時(shí)長(zhǎng)的數(shù)據(jù)分布情況,下面就是這樣一個(gè)例子:

          //?histogram.go?
          package?main

          import?(
          ?"log"
          ?"math/rand"
          ?"net/http"
          ?"time"

          ?"github.com/rcrowley/go-metrics"
          )

          func?main()?{
          ?s?:=?metrics.NewExpDecaySample(1028,?0.015)
          ?h?:=?metrics.NewHistogram(s)
          ?metrics.GetOrRegister("latency.response",?h)
          ?go?metrics.Log(metrics.DefaultRegistry,?time.Second,?log.Default())
          ?http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{
          ??i?:=?rand.Intn(10)
          ??h.Update(int64(time.Microsecond?*?time.Duration(i)))
          ?})
          ?http.ListenAndServe(":8080",?nil)
          }

          在上面這個(gè)例子中,我們使用一個(gè)隨機(jī)值來模擬服務(wù)處理http請(qǐng)求的時(shí)間。Histogram需要一個(gè)采樣算法,go-metrics內(nèi)置了ExpDecaySample采樣。運(yùn)行上述示例,并使用hey模擬客戶端請(qǐng)求,我們得到如下輸出:

          $go?run?histogram.go
          2021/07/04?11:31:54?histogram?latency.response
          2021/07/04?11:31:54???count:???????????????0
          2021/07/04?11:31:54???min:?????????????????0
          2021/07/04?11:31:54???max:?????????????????0
          2021/07/04?11:31:54???mean:????????????????0.00
          2021/07/04?11:31:54???stddev:??????????????0.00
          2021/07/04?11:31:54???median:??????????????0.00
          2021/07/04?11:31:54???75%:?????????????????0.00
          2021/07/04?11:31:54???95%:?????????????????0.00
          2021/07/04?11:31:54???99%:?????????????????0.00
          2021/07/04?11:31:54???99.9%:???????????????0.00
          2021/07/04?11:31:55???99.9%:???????????????0.00
          ...?...
          2021/07/04?11:31:59?histogram?latency.response
          2021/07/04?11:31:59???count:???????????33244
          2021/07/04?11:31:59???min:?????????????????0
          2021/07/04?11:31:59???max:??????????????9000
          2021/07/04?11:31:59???mean:?????????????4457.20
          2021/07/04?11:31:59???stddev:???????????2793.67
          2021/07/04?11:31:59???median:???????????4000.00
          2021/07/04?11:31:59???75%:??????????????7000.00
          2021/07/04?11:31:59???95%:??????????????9000.00
          2021/07/04?11:31:59???99%:??????????????9000.00
          2021/07/04?11:31:59???99.9%:????????????9000.00
          2021/07/04?11:32:00?histogram?latency.response
          2021/07/04?11:32:00???count:???????????78970
          2021/07/04?11:32:00???min:?????????????????0
          2021/07/04?11:32:00???max:??????????????9000
          2021/07/04?11:32:00???mean:?????????????4465.95
          2021/07/04?11:32:00???stddev:???????????2842.12
          2021/07/04?11:32:00???median:???????????4000.00
          2021/07/04?11:32:00???75%:??????????????7000.00
          2021/07/04?11:32:00???95%:??????????????9000.00
          2021/07/04?11:32:00???99%:??????????????9000.00
          2021/07/04?11:32:00???99.9%:????????????9000.00
          2021/07/04?11:32:01?histogram?latency.response
          2021/07/04?11:32:01???count:??????????124573
          2021/07/04?11:32:01???min:?????????????????0
          2021/07/04?11:32:01???max:??????????????9000
          2021/07/04?11:32:01???mean:?????????????4459.14
          2021/07/04?11:32:01???stddev:???????????2820.38
          2021/07/04?11:32:01???median:???????????4000.00
          2021/07/04?11:32:01???75%:??????????????7000.00
          2021/07/04?11:32:01???95%:??????????????9000.00
          2021/07/04?11:32:01???99%:??????????????9000.00
          2021/07/04?11:32:01???99.9%:????????????9000.00
          ...?...

          Histogram度量輸出的值包括min、max、mean(平均數(shù))、median(中位數(shù))、75、95、99、99.9百分位數(shù)上的度量結(jié)果。

          5) Timer

          最后我們來介紹Timer這個(gè)度量類型。大家千萬(wàn)別被這度量類型的名稱所誤導(dǎo),這并不是一個(gè)定時(shí)器。

          Timer是go-metrics定義的一個(gè)抽象度量類型,它可以理解為Histogram和Meter的“合體”,即既度量一段代碼的執(zhí)行頻率(rate),又給出這段代碼執(zhí)行時(shí)間的數(shù)據(jù)分布。這一點(diǎn)從Timer的實(shí)現(xiàn)亦可以看出來:

          //?https://github.com/rcrowley/go-metrics/blob/master/timer.go

          func?NewTimer()?Timer?{
          ????if?UseNilMetrics?{
          ????????return?NilTimer{}
          ????}
          ????return?&StandardTimer{
          ????????histogram:?NewHistogram(NewExpDecaySample(1028,?0.015)),
          ????????meter:?????NewMeter(),
          ????}
          }

          我們看到一個(gè)StandardTimer是由histogram和meter組成的。我們還是以上面的http server服務(wù)為例,我們這次用Timer來度量:

          //?timer.go

          package?main

          import?(
          ?"log"
          ?"math/rand"
          ?"net/http"
          ?"time"

          ?"github.com/rcrowley/go-metrics"
          )

          func?main()?{
          ?m?:=?metrics.NewTimer()
          ?metrics.GetOrRegister("timer.requests",?m)
          ?go?metrics.Log(metrics.DefaultRegistry,?time.Second,?log.Default())
          ?http.HandleFunc("/",?func(w?http.ResponseWriter,?r?*http.Request)?{
          ??i?:=?rand.Intn(10)
          ??m.Update(time.Microsecond?*?time.Duration(i))
          ?})
          ?http.ListenAndServe(":8080",?nil)
          }

          大家可以看到在這里我們同樣用隨機(jī)數(shù)模擬請(qǐng)求的處理時(shí)間并傳給Timer的Update方法。運(yùn)行這段代碼并用hey壓測(cè):

          $go?run?timer.go
          2021/07/04?17:13:47?timer?timer.requests
          2021/07/04?17:13:47???count:???????????13750
          2021/07/04?17:13:47???min:?????????????????0.00ns
          2021/07/04?17:13:47???max:??????????????9000.00ns
          2021/07/04?17:13:47???mean:?????????????4406.61ns
          2021/07/04?17:13:47???stddev:???????????2785.11ns
          2021/07/04?17:13:47???median:???????????4000.00ns
          2021/07/04?17:13:47???75%:??????????????7000.00ns
          2021/07/04?17:13:47???95%:??????????????9000.00ns
          2021/07/04?17:13:47???99%:??????????????9000.00ns
          2021/07/04?17:13:47???99.9%:????????????9000.00ns
          2021/07/04?17:13:47???1-min?rate:??????????0.00
          2021/07/04?17:13:47???5-min?rate:??????????0.00
          2021/07/04?17:13:47???15-min?rate:?????????0.00
          2021/07/04?17:13:47???mean?rate:???????13748.57
          2021/07/04?17:13:48?timer?timer.requests
          2021/07/04?17:13:48???count:???????????56584
          2021/07/04?17:13:48???min:?????????????????0.00ns
          2021/07/04?17:13:48???max:??????????????9000.00ns
          2021/07/04?17:13:48???mean:?????????????4442.61ns
          2021/07/04?17:13:48???stddev:???????????2895.66ns
          2021/07/04?17:13:48???median:???????????4000.00ns
          2021/07/04?17:13:48???75%:??????????????7000.00ns
          2021/07/04?17:13:48???95%:??????????????9000.00ns
          2021/07/04?17:13:48???99%:??????????????9000.00ns
          2021/07/04?17:13:48???99.9%:????????????9000.00ns
          2021/07/04?17:13:48???1-min?rate:??????????0.00
          2021/07/04?17:13:48???5-min?rate:??????????0.00
          2021/07/04?17:13:48???15-min?rate:?????????0.00
          2021/07/04?17:13:48???mean?rate:???????28289.23
          2021/07/04?17:13:49?timer?timer.requests
          2021/07/04?17:13:49???count:??????????102426
          2021/07/04?17:13:49???min:?????????????????0.00ns
          2021/07/04?17:13:49???max:??????????????9000.00ns
          2021/07/04?17:13:49???mean:?????????????4436.77ns
          2021/07/04?17:13:49???stddev:???????????2892.85ns
          2021/07/04?17:13:49???median:???????????4000.00ns
          2021/07/04?17:13:49???75%:??????????????7000.00ns
          2021/07/04?17:13:49???95%:??????????????9000.00ns
          2021/07/04?17:13:49???99%:??????????????9000.00ns
          2021/07/04?17:13:49???99.9%:????????????9000.00ns
          2021/07/04?17:13:49???1-min?rate:??????????0.00
          2021/07/04?17:13:49???5-min?rate:??????????0.00
          2021/07/04?17:13:49???15-min?rate:?????????0.00
          2021/07/04?17:13:49???mean?rate:???????34140.68

          我們看到Timer度量的輸出也的確是Histogram和Meter的聯(lián)合體!

          3. 小結(jié)

          通過go-metrics包,我們可以很方便地為一個(gè)Go應(yīng)用添加度量指標(biāo),go-metrics提供的meter、histogram可以覆蓋Go應(yīng)用基本性能指標(biāo)需求(吞吐性能、延遲數(shù)據(jù)分布等)。go-metrics還支持各種指標(biāo)值導(dǎo)出的,只是這里沒有提及,大家可以到go-metrics官網(wǎng)了解詳情。

          本文涉及的源碼可以在這里下載[5]?- https://github.com/bigwhite/experiments/tree/master/go-metrics

          參考資料

          [1]?

          本文永久鏈接:?https://tonybai.com/2021/07/06/add-metrics-for-go-application-using-go-metrics

          [2]?

          Coda Hale's Metrics library:?https://github.com/dropwizard/metrics

          [3]?

          Coda Hale's Metrics library的項(xiàng)目文檔:?https://metrics.dropwizard.io/4.2.0/manual/core.html

          [4]?

          hey工具:?https://github.com/rakyll/hey/

          [5]?

          這里下載:?https://github.com/bigwhite/experiments/tree/master/go-metrics

          [6]?

          改善Go語(yǔ)?編程質(zhì)量的50個(gè)有效實(shí)踐:?https://www.imooc.com/read/87

          [7]?

          Kubernetes實(shí)戰(zhàn):高可用集群搭建、配置、運(yùn)維與應(yīng)用:?https://coding.imooc.com/class/284.html

          [8]?

          我愛發(fā)短信:?https://51smspush.com/

          [9]?

          鏈接地址:?https://m.do.co/c/bff6eed92687



          推薦閱讀


          福利

          我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù)?ebook?獲?。贿€可以回復(fù)「進(jìn)群」,和數(shù)萬(wàn) Gopher 交流學(xué)習(xí)。

          瀏覽 78
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线观看黄色小电影 | 人妻免费视频 | 校花被操视频 | 操片豆花视频在线观看 | 视频在线观看一区 |