【Go Web 開發】性能參數

當你的應用程序在生產環境中運行並處理實際請求時,如果您正在進行有針對性的負載測試,您可能想要深入瞭解程序是如何執行的,以及它正在使用哪些資源。

例如,你可能想回答以下問題:

深入瞭解這些內容可以幫助您瞭解軟硬件的配置選擇,並作爲潛在問題 (如內存泄漏) 的早期預警信號。

爲了幫助實現這一點,Go 的標準庫包含了 expvar 包,它可以讓你在運行時很容易地整理和查看不同的應用程序性能指標。

在本文你將學習到:

使用 Expvar 開放性能參數

由於 expvar 包提供了 expvar.handler() 函數,該函數返回一個應用程序指標的 HTTP 處理程序,因此查看 API 服務的指標變得很容易。

默認情況下,這個處理程序顯示關於內存使用的信息,以及啓動應用程序時使用的命令行參數,所有這些都以 JSON 格式輸出。

所以我們要做的第一件事就是把這個 handler 處理函數掛載到一個新的 GET /debug/vars 接口,像這樣:

qUyBzN

File:cmd/api/routes.go

package main

...

func (app *application) routes() http.Handler {
    router := httprouter.New()

    router.NotFound = http.HandlerFunc(app.notFoundResponse)
    router.MethodNotAllowed = http.HandlerFunc(app.methodNotAllowedResponse)

    router.HandlerFunc(http.MethodGet, "/v1/healthcheck", app.healthcheckHandler)

    router.HandlerFunc(http.MethodGet, "/v1/movies", app.requirePermission("movies:read", app.listMoviesHandler))
    router.HandlerFunc(http.MethodPost, "/v1/movies", app.requirePermission("movies:write", app.createMovieHandler))
    router.HandlerFunc(http.MethodGet, "/v1/movies/:id", app.requirePermission("movies:read", app.showMovieHandler))
    router.HandlerFunc(http.MethodPatch, "/v1/movies/:id", app.requirePermission("movies:write", app.updateMovieHandler))
    router.HandlerFunc(http.MethodDelete, "/v1/movies/:id", app.requirePermission("movies:write", app.deleteMovieHandler))

    router.HandlerFunc(http.MethodPost, "/v1/users", app.registerUserHandler)
    router.HandlerFunc(http.MethodPut, "/v1/users/activated", app.activateUserHandler)
    router.HandlerFunc(http.MethodPost, "/v1/tokens/authentication", app.createAuthenticationTokenHandler)

    //註冊新的接口指向expvar處理程序
    router.Handler(http.MethodGet, "/debug/vars", expvar.Handler())
    return app.recoverPanic(app.enableCORS(app.rateLimit(app.authenticate(router))))
}

提示:使用 GET /degbu/var 作爲 expvar 處理程序的 Endpoint 是慣例用法不是必須的。如果你不喜歡,可以使用其他接口名稱例如 GET /v/metrics 來代替。

下面來測試下,啓動應用程序,爲了演示傳入一些命令行參數:

$ go run ./cmd/api  -limiter-enable=false -port=4000
{"level":"INFO","time":"2022-01-12T03:16:43Z","message":"database connection pool established"}
{"level":"INFO","time":"2022-01-12T03:16:43Z","message":"starting server","properties":{"addr":":4000","env":"development"}}

如果你訪問 http://localhost:4000/debug/vars,將看到 JSON 響應內容包含應用程序運行時的指標信息:

$curl http://localhost:4000/debug/vars -s | python -m json.tool
{
    "cmdline": [
        "/var/folders/x6/8wtj7zfd7r59wpk5fmjln2p40000gn/T/go-build3315447716/b001/exe/api",
        "-limiter-enable=false",
        "-port=4000"
    ],
    "memstats": {
        "Alloc": 545376,
        "BuckHashSys": 3860,
        "BySize": [
            {
                "Frees": 0,
                "Mallocs": 0,
                "Size": 0
            },
        ...
            }
        ],
        "DebugGC": false,
        "EnableGC": true,
        "Frees": 177,
        "GCCPUFraction": 0,
        "GCSys": 4011248,
        "HeapAlloc": 545376,
        "HeapIdle": 65167360,
        "HeapInuse": 1482752,
        "HeapObjects": 2236,
        "HeapReleased": 64937984,
        "HeapSys": 66650112,
        "LastGC": 0,
        "Lookups": 0,
        "MCacheInuse": 9600,
        "MCacheSys": 16384,
        "MSpanInuse": 37536,
        "MSpanSys": 49152,
        "Mallocs": 2413,
        "NextGC": 4473924,
        "NumForcedGC": 0,
        "NumGC": 0,
        "OtherSys": 1034252,
        "PauseEnd": [

可以看到 JSON 包含兩個頂層鍵值分別爲:"cmdline" 和 "memstats"。我們簡單瞭解下這些鍵。

"cmdline" 鍵包含應用程序的命令行參數列表,以程序名稱爲首元素。這本質上是 os.Args 變量的 JSON 表示,如果您想要確切地瞭解在啓動應用程序時使用了哪些非默認設置,那麼它很有用。

"memstats" 鍵包含即時內存使用快照,是由 runtime.MemStats() 函數返回的。關於這些值得文檔和描述可以查看這裏 [https://golang.org/pkg/runtime/#MemStats],但最重要的是下面幾個:

提示:如果上面有你不熟悉的字段,我強烈建議你閱讀 "Understanding Allocations in Go" 文章介紹了 Go 如何分配內存以及堆棧的概念。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/UBSLoVqTVpnXmHhuIBYOyA