【Go Web 開發】創建自定義性能參數

expvar 處理程序提供的默認信息是一個好的開始。但我們可以通過在 JSON 響應中開放一些額外的定製指標來讓它變得更有用。

爲了說明自定義性能參數,我們先開始一個簡單的,將應用程序的版本號添加到 JSON 響應中。如果你忘記了,版本號是定義在 main.go 文件中的字符串常量值爲:"1.0.0"。

實現的代碼分爲兩個基本步驟:1、使用 expvar 包註冊一個自定義變量。2、需要爲變量賦值。代碼大致爲:

expvar.NewString("version").Set(version)

代碼的第一部分:expvar.NewString("version") 創建一個新的 expvar.String 類型,然後分佈到 expvar 處理程序的 JSON 響應中,名稱爲 "version" 並返回一個指向它的指針。然後我們使用 Set() 方法來爲指針賦值。

需要注意的兩個事情:

下面,我們將前面的代碼集成到 main() 函數中,如下所示:

File: cmd/api/main.go

package main

...

    expvar.NewString("version").Set(version)
    // 添加models字段,引入數據庫模型爲接口處理程序所用
    app := &application{
        config: cfg,
        logger: logger,
        models: data.NewModels(db),
        mailer: mailer.New(cfg.smtp.host, cfg.smtp.port, cfg.smtp.username, cfg.smtp.password, cfg.smtp.sender),
    }

    // 啓動HTTP服務
    err = app.server()
    if err != nil {
        logger.Fatal(err, nil)
    }
}

...

如果你重啓 API 服務並再次訪問 http://localhost:4000/debug/vars,你將在 JSON 中 "version": "1.0.0"。如下所示:

$ 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,
        ...
        "PauseTotalNs": 0,
        "StackInuse": 458752,
        "StackSys": 458752,
        "Sys": 71961616,
        "TotalAlloc": 334776
    },
    "version": "1.0.0"
}

注意:在上面的代碼中我們使用 expvar.NewString() 函數註冊和發佈字符串到 expvar 處理程序。但是 Go 也爲其他一些常見的數據類型提供了函數: NewFloat(), newint() 和 NewMap()。所有這些都以非常相似的方式工作,我們將在下一節中使用它們。

動態性能參數

有時候返回的參數需要調用其他代碼或做一些預處理生成必要信息。expvar.Puhlish() 函數能實現這個功能,將函數的運行結果發佈到 JSON 響應中。

例如,你想將 Go 的 runtime.NumGoroutine() 函數返回的當前活躍的 goroutine 數量添加到 JSON 響應中,可以像下面這樣寫代碼:

expvar.Publish("goroutine", expvar.Func(func() interface{} {
    return runtime.NumGoroutine()
}))

需要指出的是這裏函數返回的 interface{} 值必須能被正確序列化爲 JSON。如果無法序列化成 JSON,expvar 的結果中會忽略該值,GET /debug/var 響應內容將不完整。任何錯誤都將被安靜地丟棄。

在上面的代碼中,runtime.NumGoroutine() 返回的是一個普通 int 類型,將被編碼爲 JSON 數字。因此不會出現問題。

下面我們將這些代碼添加到 main() 函數中,以及其他兩個函數:

File:cmd/api/main.go

package main

    ...

    expvar.NewString("version").Set(version)

    //發佈goroutines數量
    expvar.Publish("goroutines", expvar.Func(func() interface{} {
        return runtime.NumGoroutine()
    }))

    //發佈數據庫連接池數據統計
    expvar.Publish("database", expvar.Func(func() interface{} {
        return db.Stats()
    }))

    //發佈當前時間戳
    expvar.Publish("timestamp", expvar.Func(func() interface{} {
        return time.Now().Unix()
    }))

    app := &application{
        config: cfg,
        logger: logger,
        models: data.NewModels(db),
        mailer: mailer.New(cfg.smtp.host, cfg.smtp.port, cfg.smtp.username, cfg.smtp.password, cfg.smtp.sender),
    }

    // 啓動HTTP服務
    err = app.server()
    if err != nil {
        logger.Fatal(err, nil)
    }
}

...

如果你重啓 API 服務,在瀏覽器中打開 GET /debug/vars 接口,你將看到響應的 JSON 值新增的 "database","goroutines" 和 "timestamp" 鍵值。

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