菜单
开源

设置 Go 性能分析(拉取模式)

在 pull 模式下,采集器 Grafana Alloy 会定期从 Golang 应用程序检索 profile,特别是针对 /debug/pprof/* 端点。

要设置 Golang pull 模式 profiling,您需要

  1. 暴露 pprof 端点。
  2. 安装一个采集器,例如 Grafana Alloy。
  3. 准备采集器的配置文件。
  4. 启动采集器。

暴露 pprof 端点

确保您的 Golang 应用程序暴露 pprof 端点。

  1. 获取 godeltaprof

    bash
    go get github.com/grafana/pyroscope-go/godeltaprof@latest
  2. 在应用程序启动时导入 net/http/pprofgodeltaprof/http/pprof 包。

    Go
    import _ "net/http/pprof"
    import _ "github.com/grafana/pyroscope-go/godeltaprof/http/pprof"

安装采集器

您可以使用示例 Alloy 采集器配置文件将数据发送到 Pyroscope。

要安装 Alloy,请参阅 Grafana Alloy 安装

准备采集器配置文件

在 Alloy 配置文件中,您至少需要添加两个块:pyroscope.writepyroscope.scrape

  1. 添加 pyroscope.write 块。

    alloy
    pyroscope.write "write_job_name" {
            endpoint {
                    url = "https://127.0.0.1:4040"
            }
    }
  2. 添加 pyroscope.scrape 块。

    alloy
    pyroscope.scrape "scrape_job_name" {
            targets    = [{"__address__" = "localhost:4040", "service_name" = "example_service"}]
            forward_to = [pyroscope.write.write_job_name.receiver]
    
            profiling_config {
                    profile.process_cpu {
                            enabled = true
                    }
    
                    profile.godeltaprof_memory {
                            enabled = true
                    }
    
                    profile.memory { // disable memory, use godeltaprof_memory instead
                            enabled = false
                    }
    
                    profile.godeltaprof_mutex {
                            enabled = true
                    }
    
                    profile.mutex { // disable mutex, use godeltaprof_mutex instead
                            enabled = false
                    }
    
                    profile.godeltaprof_block {
                            enabled = true
                    }
    
                    profile.block { // disable block, use godeltaprof_block instead
                            enabled = false
                    }
    
                    profile.goroutine {
                            enabled = true
                    }
            }
    }
  3. 保存对文件的更改。

启动采集器

  1. 启动本地 Pyroscope 实例以进行测试

    bash
    docker run -p 4040:4040 grafana/pyroscope
  2. 要启动 Alloy v1.2 及更高版本:将 configuration.alloy 替换为您的配置文件名
    alloy run configuration.alloy

  3. 打开浏览器访问 https://127.0.0.1:4040。页面应列出 profile。

示例

发送数据到 Grafana Cloud

您的 Grafana Cloud URL、用户名和密码可以在 grafana.com 上您的 stack 的 Pyroscope 的“详细信息页”中找到。在此页面上,创建一个令牌并将其用作基本身份验证密码。

alloy
pyroscope.write "write_job_name" {
        endpoint {
                url = "<Grafana Cloud URL>"

                basic_auth {
                        username = "<Grafana Cloud User>"
                        password = "<Grafana Cloud Password>"
                }
        }

}

发现 Kubernetes 目标

  1. 选择所有 pod
alloy
discovery.kubernetes "all_pods" {
        role = "pod"
}
  1. 删除未运行的 pod,创建 namespacepodnodecontainer 标签。基于 namespacecontainer 标签组合 service_name 标签。仅选择与正则表达式模式 (ns1/.*)|(ns2/container-.*0) 匹配的服务。

    alloy
    
    discovery.relabel "specific_pods" {
            targets = discovery.kubernetes.all_pods.targets
    
            rule {
                    action        = "drop"
                    regex         = "Succeeded|Failed|Completed"
                    source_labels = ["__meta_kubernetes_pod_phase"]
            }
    
            rule {
                    action        = "replace"
                    source_labels = ["__meta_kubernetes_namespace"]
                    target_label  = "namespace"
            }
    
            rule {
                    action        = "replace"
                    source_labels = ["__meta_kubernetes_pod_name"]
                    target_label  = "pod"
            }
    
            rule {
                    action        = "replace"
                    source_labels = ["__meta_kubernetes_node_name"]
                    target_label  = "node"
            }
    
            rule {
                    action        = "replace"
                    source_labels = ["__meta_kubernetes_pod_container_name"]
                    target_label  = "container"
            }
    
            rule {
                    action        = "replace"
                    regex         = "(.*)@(.*)"
                    replacement   = "${1}/${2}"
                    separator     = "@"
                    source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
                    target_label  = "service_name"
            }
    
            rule {
                    action        = "keep"
                    regex         = "(ns1/.*)|(ns2/container-.*0)"
                    source_labels = ["service_name"]
            }
    }
  2. 使用 discovery.relabel.specific_pods.output 作为 pyroscope.scrape 块的目标。

    alloy
        pyroscope.scrape "scrape_job_name" {
                targets    = discovery.relabel.specific_pods.output
                ...
        }

暴露 pprof 端点

如果您不使用 http.DefaultServeMux,您可以将 /debug/pprof/* 处理程序注册到您自己的 http.ServeMux

Go
var mux *http.ServeMux
mux.Handle("/debug/pprof/", http.DefaultServeMux)

或者,如果您使用 gorilla/mux

Go
var router *mux.Router
router.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux)

参考