【Go Web开发】创建自定义性能参数

2022-04-01  本文已影响0人  Go语言由浅入深

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"键值。

上一篇下一篇

猜你喜欢

热点阅读