用 Go 編寫的 HTTP 伺服器儀表化

在本教程中,我們將建立一個簡單的 Go HTTP 伺服器,並透過新增一個計數器指標來對其進行儀表化,以統計伺服器處理的總請求數。

這裡我們有一個簡單的 HTTP 伺服器,其中包含一個 `/ping` 端點,該端點返回 `pong` 作為響應。

package main

import (
   "fmt"
   "net/http"
)

func ping(w http.ResponseWriter, req *http.Request) {
   fmt.Fprintf(w,"pong")
}

func main() {
   http.HandleFunc("/ping", ping)

   http.ListenAndServe(":8090", nil)
}

編譯並執行伺服器

go build server.go
./server

現在在瀏覽器中開啟 `https://:8090/ping`,您應該會看到 `pong`。

Server

現在,讓我們向伺服器新增一個指標,該指標將用於統計對 ping 端點的請求數量。計數器指標型別非常適合此目的,因為我們知道請求計數只會增加而不會減少。

建立一個 Prometheus 計數器

type metrics struct {
	pingCounter prometheus.Counter
}

func newMetrics(reg prometheus.Registerer) *metrics {
	m := &metrics{
		pingCounter: promauto.With(reg).NewCounter(
			prometheus.CounterOpts {
				Name: "ping_request_count",
				Help: "No of requests handled by Ping handler",
			}),
	}
	return m
}

接下來,讓我們更新 ping 處理程式,使用 `metrics.pingCounter.Inc()` 來增加計數器的計數。

func ping(m *metrics) func(w http.ResponseWriter, req *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		m.pingCounter.Inc()
		fmt.Fprintf(w, "pong")
	}
}

然後將指標(在本例中,只有一個計數器)註冊到 Prometheus 登錄檔並暴露這些指標。

func main() {
	reg := prometheus.NewRegistry()
	m := newMetrics(reg)

	http.HandleFunc("/ping", ping(m))
	http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))
	http.ListenAndServe(":8090", nil)
}

`prometheus.MustRegister` 函式將 pingCounter 註冊到預設登錄檔。為了暴露指標,Go Prometheus 客戶端庫提供了 promhttp 包。`promhttp.Handler()` 提供了一個 `http.Handler`,用於暴露在預設登錄檔中註冊的指標。

示例程式碼現在是

package main

import (
	"fmt"
	"net/http"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

type metrics struct {
	pingCounter prometheus.Counter
}

func newMetrics(reg prometheus.Registerer) *metrics {
	m := &metrics{
		pingCounter: promauto.With(reg).NewCounter(
			prometheus.CounterOpts{
				Name: "ping_request_count",
				Help: "No of request handled by Ping handler",
			}),
	}
	return m
}

func ping(m *metrics) func(w http.ResponseWriter, req *http.Request) {
	return func(w http.ResponseWriter, req *http.Request) {
		m.pingCounter.Inc()
		fmt.Fprintf(w, "pong")
	}
}

func main() {
	reg := prometheus.NewRegistry()
	m := newMetrics(reg)

	http.HandleFunc("/ping", ping(m))
	http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{}))
	http.ListenAndServe(":8090", nil)
}

執行示例

go mod init prom_example
go mod tidy
go run server.go

現在訪問 localhost:8090/ping 端點幾次,然後向 localhost:8090/metrics 傳送請求以檢視指標。

Ping Metric

在這裡,`ping_request_count` 顯示 `/ping` 端點被呼叫了 3 次。

預設登錄檔包含 Go 執行時指標的收集器,這就是我們看到 `go_threads`、`go_goroutines` 等其他指標的原因。

我們已經構建了我們的第一個指標匯出器。現在,讓我們更新 Prometheus 配置以從我們的伺服器抓取指標。

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets: ["localhost:9090"]
  - job_name: simple_server
    static_configs:
      - targets: ["localhost:8090"]

prometheus --config.file=prometheus.yml

本頁內容