You need to enable JavaScript to run this app.
导航

Golang 应用接入

最近更新时间2024.03.01 11:23:08

首次发布时间2023.05.15 15:53:28

Prometheus 提供了 官方版 Golang 库 用于采集并暴露监控数据,本文为您介绍如何使用官方版 Golang 库来暴露 Golang runtime 相关的数据,以及其它一些基本简单的示例,并使用托管 Prometheus 服务来采集和展示指标数据。

说明

Golang Client API 相关的文档详见 GoDoc

安装依赖

您可以通过 go get 命令来安装相关依赖,示例如下:

go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/collectors
go get github.com/prometheus/client_golang/prometheus/promhttp

运行时指标

  1. 创建一个 HTTP 服务,路径使用 /metrics。可以直接使用 prometheus/promhttp 里提供的 Handler 函数。

    如下是一个简单的示例,通过 http://localhost:2023/metrics 暴露 Golang 应用的一些默认指标数据,包括:运行时指标、进程相关指标以及构建相关的指标。

package main

import (
        "math"
        "math/rand"
        "net/http"
        "time"

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

func main() {
        // Create a new registry.
        reg := prometheus.NewRegistry()

        // Add Go module build info.
        reg.MustRegister(collectors.NewBuildInfoCollector())
        // Add go runtime metrics and process collectors.
        reg.MustRegister(
                collectors.NewGoCollector(),
                collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
        )

        http.Handle("/metrics", promhttp.HandlerFor(
                reg, promhttp.HandlerOpts{},
        ))
        http.ListenAndServe(":2023", nil)
}
  1. 执行以下命令,启动应用。
go run main.go
  1. 执行以下命令,即可查看运行时的指标数据。
curl http://localhost:2023/metrics

应用层指标

  1. 上述示例仅仅暴露了一些基础的内置指标。应用层面的指标还需要额外添加。
    如下示例暴露了一个名为 rpc_durations_seconds 的指标,用于对服务的 RPC 延迟进行统计。
package main

import (
        "math"
        "math/rand"
        "net/http"
        "time"

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

var rpcDurations = prometheus.NewSummaryVec(
        prometheus.SummaryOpts{
                Name:       "rpc_durations_seconds",
                Help:       "RPC latency distributions.",
                Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
        },
        []string{"service"},
)

func main() {
        // Create a new registry.
        reg := prometheus.NewRegistry()

        // Add Go module build info.
        reg.MustRegister(collectors.NewBuildInfoCollector())
        // Add go runtime metrics and process collectors.
        reg.MustRegister(
                collectors.NewGoCollector(),
                collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
        )

        reg.MustRegister(rpcDurations)

        start := time.Now()

        oscillationFactor := func() float64 {
                return 2 + math.Sin(math.Sin(2*math.Pi*float64(time.Since(start))/float64(10*time.Minute)))
        }

        // Periodically record some sample latencies for the three services.
        go func() {
                for {
                        v := rand.Float64() * 0.0002
                        rpcDurations.WithLabelValues("uniform").Observe(v)
                        time.Sleep(time.Duration(100*oscillationFactor()) * time.Millisecond)
                }
        }()

        go func() {
                for {
                        v := (rand.NormFloat64() * 0.0002) + 0.00001
                        rpcDurations.WithLabelValues("normal").Observe(v)
                        time.Sleep(time.Duration(75*oscillationFactor()) * time.Millisecond)
                }
        }()

        go func() {
                for {
                        v := rand.ExpFloat64() / 1e6
                        rpcDurations.WithLabelValues("exponential").Observe(v)
                        time.Sleep(time.Duration(50*oscillationFactor()) * time.Millisecond)
                }
        }()

        http.Handle("/metrics", promhttp.HandlerFor(
                reg, promhttp.HandlerOpts{},
        ))
        http.ListenAndServe(":2023", nil)
}
  1. 执行以下命令,启动应用。
go run main.go
  1. 执行以下命令,即可查看运行时的指标数据。
curl http://localhost:2023/metrics

从输出结果我们可以看到 rpc_durations_seconds 计数器相关的信息,包括帮助文档、类型信息、指标名和当前值。

# HELP rpc_durations_seconds RPC latency distributions.
# TYPE rpc_durations_seconds summary
rpc_durations_seconds{service="exponential",quantile="0.5"} 7.427294276581254e-07
rpc_durations_seconds{service="exponential",quantile="0.9"} 2.3157390817424027e-06

监控 Golang 应用示例

上面的示例仅展示了如何使用 Prometheus Golang 库来暴露应用的指标数据,但暴露的监控指标数据还需要通过托管 Prometheus 服务进行统一的采集的存储,进一步才能实现数据的监控和告警。

打包应用

  1. Golang 应用可以使用如下形式的 Dockerfile 打包为镜像,方便部署在容器服务 VKE 集群中。

说明

该 Dockerfile 仅为示例,您需要按需修改里面的参数。

FROM golang:1.19 as builder
COPY . /go/src/demo
WORKDIR /go/src/demo
RUN go env -w GOPROXY=https://goproxy.cn,direct && \
    go mod init && \
    go mod tidy && \
    go mod vendor && \
    go build -v -o /golang-demo

FROM buildpack-deps:bullseye-curl
RUN mkdir -p /app
COPY --from=builder /golang-demo /app
WORKDIR     /app
ENV TZ Asia/Shanghai
EXPOSE 2023
ENTRYPOINT  ["/app/golang-demo"]

  1. 镜像创建完成后,可以上传至 火山引擎 镜像仓库 中使用。也可以使用其他公有云或自建镜像仓库。

说明

火山引擎镜像仓库的镜像推送方式,请参见 推送和拉取镜像

部署应用

您可以使用镜像仓库中的镜像,在容器服务 VKE 集群中部署应用。步骤如下:

  1. 登录 容器服务控制台
  2. 在左侧菜单栏中选择 集群,并在右侧集群列表中选择目标集群。
  3. 单击集群名称,进入集群配置页面。
  4. 在左侧菜单栏中选择 工作负载 > 无状态负载。 单击 使用 Yaml 创建 ,部署应用。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: golang-demo # 配置应用的名称
  namespace: volcano-metrics # 配置应用所在的命名空间
  labels:
    app: golang-demo # 配置应用的标签
spec:
  replicas: 2 # 配置应用副本数
  selector:
    matchLabels:
      app: golang-demo
  template:
    metadata:
      labels:
        app: golang-demo
    spec:
      containers:
      - name: golang-demo # 配置容器名称
        image: doc-cn-beijing.cr.volces.com/vmp/golang-demo:1.0 # 配置应用镜像的地址和版本
        ports:
        - containerPort: 2023 # 配置容器端口
  1. 在集群管理页面的左侧导航栏中,选择 服务与路由 > 服务,单击 使用 Yaml 创建 ,配置服务进行负载均衡和服务发现。
apiVersion: v1
kind: Service
metadata:
  name: golang-service-demo
  namespace: volcano-metrics # 配置服务所在的命名空间
  labels: 
    app: golang-service-demo # 配置服务的标签
spec:
  selector:
    app: golang-demo
  ports:
    - protocol: TCP
      port: 2023
      targetPort: 2023
      name: metrics # 配置服务端口名称
  type: ClusterIP

配置服务发现

当应用部署并正常运行后,可以使用 ServiceMonitor 配置服务发现,允许 Agent 采集该应用的指标。具体的操作步骤如下:

  1. 在左侧菜单栏中选择 工作负载 > 对象浏览器。 单击 使用 Yaml 创建 ,通过 ServiceMonitor 配置服务发现。
    • 类型 下拉菜单中选择 自定义
    • Yaml 配置框内输入 Yaml 配置。
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: golang-demo    # 填写一个唯一名称
  namespace: default # 配置 ServiceMonitor 命名空间
  labels: 
    volcengine.vmp: "true" # 配置 ServiceMonitor 的标签,允许被 Prometheus-agent 发现
spec:
  endpoints:
  - interval: 30s
    port: metrics # 配置服务端口号
    path: /metrics # 填写指标暴露的 URI 路径,不填默认为 /metrics
    relabelings:
    - action: replace
      sourceLabels:  [__meta_kubernetes_pod_label_app]
      targetLabel: application
  namespaceSelector:
    matchNames:
    - volcano-metrics # 配置为服务所在的命名空间
  selector:
    matchLabels:
      app: golang-service-demo # 配置服务的 Label 值,以定位目标服务

查看监控数据

您可以使用托管 Prometheus 服务的 Explore 功能来查看监控指标数据。详情请参见 指标查询
也可以使用 Grafana 读取托管 Prometheus 服务中存储的数据,并创建指标大盘。
alt