美文网首页
【Go Web开发】创建自定义性能参数

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

作者: Go语言由浅入深 | 来源:发表于2022-04-01 22:35 被阅读0次

    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()方法来为指针赋值。

    需要注意的两个事情:

    • expvar.String类型是并发安全的。因此,如果有需要,可以在你的处理程序中对其值进行处理。
    • 如果你试图注册两个相同名称的expvar变量,当注册重复的变量,会导致运行时panic。

    下面,我们将前面的代码集成到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()函数中,以及其他两个函数:

    • 发布关于数据库连接池状态的信息(例如空闲和正在使用的连接数)通过db.Stats()方法。
    • 以秒为单位发布当前Unix时间戳。

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

    相关文章

      网友评论

          本文标题:【Go Web开发】创建自定义性能参数

          本文链接:https://www.haomeiwen.com/subject/ndjzjrtx.html