使用代码热点诊断Golang应用慢调用问题

ARMS代码热点作为一种监控诊断工具,通过持续剖析技术定时采集请求线程堆栈快照,真实还原代码执行的第一现场。

使用场景

  • 当促销活动出现慢调用时,ARMS代码热点可为您快速定位问题代码。

  • 当系统出现大量慢调用时,ARMS代码热点可为您自动保存第一现场。

  • 当业务太复杂,偶发性慢调用无法复现时,ARMS代码热点可为您还原代码真实方法层面的执行轨迹。

  • 当调用链中因为缺失对应用代码非框架层面的方法埋点时,代码热点帮您还原对应缺失埋点的实际方法调用耗时。

前提条件

说明

当前代码热点的功能仅支持On CPU场景。

开启代码热点

  1. 登录ARMS控制台,在左侧导航栏选择应用监控 > 应用列表

  2. 应用列表页面顶部选择目标地域,然后单击目标应用名称。

    说明

    语言列的图标含义如下:

    Java图标:接入应用监控的Java应用。

    image:接入应用监控的Golang应用。

    image:接入应用监控的Python应用。

    -:接入可观测链路 OpenTelemetry 版的应用。

  3. 在左侧导航栏中单击应用设置,然后单击自定义配置页签。

  4. 持续剖析区域开启总开关,然后开启CPU热点代码热点开关。

  5. 在页面底部单击保存

    无需重启应用即可生效。

通过调用链分析查看代码热点数据

示例代码:

package main

import (
	"log"
	"net/http"
	"strconv"
)

var client = http.Client{}

func adRedisServer(w http.ResponseWriter, r *http.Request) {
	log.Printf("request to redis server")
	r.Header.Add("times", strconv.Itoa(onCpu()))
	w.Write([]byte("Hello World"))
}

func onCpu() int {
	var header map[string]int
	header = make(map[string]int)
	sum := 1
	for i := 0; i < 10*1024*1024; i++ {
		sum = sum + i
		header["i"] = sum
	}
	return sum
}

func main() {
	http.Handle("/ad-redis-server", http.HandlerFunc(adRedisServer))
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic(err)
	}
}
  1. 登录ARMS控制台,在左侧导航栏选择应用监控 > 应用列表

  2. 应用列表页面顶部选择目标地域,然后单击目标应用名称。

    说明

    语言列的图标含义如下:

    Java图标:接入应用监控的Java应用。

    image:接入应用监控的Golang应用。

    image:接入应用监控的Python应用。

    -:接入可观测链路 OpenTelemetry 版的应用。

  3. 在左侧导航栏中单击接口调用,并在页面右侧选择目标接口,然后单击调用链查询页签。

  4. 调用链查询页签上单击目标TraceId链接。

  5. 详情列中单击放大镜图标,然后单击代码热点页签。

    image

    图中左侧为本次调用中所涉及的所有方法耗时情况列表,右侧为对应方法所有方法栈信息绘制的火焰图。其中:

    • Self列表示方法在自身的调用栈中所消耗的时间或资源,不包括其子方法调用所消耗的时间或资源。可以用于识别哪些方法在自身内部花费了大量的时间或资源。

    • Total列包含方法自身消耗的时间或资源,及其所有子方法调用所消耗的时间或资源。可以帮助了解整个方法调用栈中哪些方法贡献了最多的时间或资源。

    从代码热点火焰图中可以看出耗时比较高的是onCpu()函数,您可以重点关注该函数来定位性能问题。