微服务性能分析工具 Pyroscope 初体验

Go 自带接口性能分析工具 pprof,较为常用的有以下 4 种分析:

  • CPU Profiling: CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置;
  • Memory Profiling: 内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏;
  • Block Profiling: 阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置;
  • Mutex Profiling: 互斥锁分析,报告互斥锁的竞争情况。

接入方式:

go 复制代码
package main

import (
    "net/http"
    _ "net/http/pprof"
)

func main() {
    http.ListenAndServe("0.0.0.0:6060", nil)
}

它使用默认的 http.DefaultServeMux 结构,注册了 /debug/pprof/ 路由,在浏览器访问可以访问 CPU/Memory/Block/Mutex/Goroutine 等性能分析页面。

对于线上服务来说,需要针对该路由做好限制,否则可能直接暴露到系统外部,造成数据安全问题。

如果是内部服务,自己电脑的浏览器看不到页面,就很麻烦了。而 Pyroscope 这个项目就非常爽~

它有一个非常漂亮的 UI 界面,展示 Agent 采集的数据,能直观地展示程序各个函数的调用耗时,从而找出性能瓶颈。

架构图如下:

接入方式也非常简单,本地搭建服务的话(macOS),输入以下命令:

bash 复制代码
brew install pyroscope-io/brew/pyroscope
pyroscope server

对应的服务需要加入以下代码:

go 复制代码
package main

import (
    "github.com/pyroscope-io/client/pyroscope"
)

func initPyroScope() {
    runtime.SetMutexProfileFraction(5)
    runtime.SetBlockProfileRate(5)
    _, _ = pyroscope.Start(pyroscope.Config{
        ApplicationName: app.ServerName,                 // 应用名称
        ServerAddress:   "http://pyroscope.test.com.cn", // 上报地址
        Logger:          pyroscope.StandardLogger,
        Tags:            map[string]string{"hostname": os.Getenv("HOSTNAME")},
        ProfileTypes: []pyroscope.ProfileType{
            pyroscope.ProfileCPU,
            pyroscope.ProfileAllocObjects,
            pyroscope.ProfileAllocSpace,
            pyroscope.ProfileInuseObjects,
            pyroscope.ProfileInuseSpace,
            pyroscope.ProfileGoroutines,
            pyroscope.ProfileMutexCount,
            pyroscope.ProfileMutexDuration,
            pyroscope.ProfileBlockCount,
            pyroscope.ProfileBlockDuration,
        },
    })
}

func main() {
    initPyroScope()
    // ...
}

其中,ApplicationNameServerAddress 需要自行替换。

如果是本地,ServerAddress 请改成 "http://127.0.0.1:4040",接着运行 benchmark 压测:

bash 复制代码
ab -c 100 -n 10000 'http://127.0.0.1:8099/api/xxx-service/v1/yyy/get_test?gid=23333'

可以得到火焰图(好漂亮啊):

此时可以看到最耗时的是 HTTP 服务的调用,还有 JSON 的序列化:

说明我们的程序接口,在某个输入参数的情况下,没有出现逻辑上的瓶颈。

我们可以多变换输入参数,根据业务逻辑找到最复杂最消耗性能的模块,有针对性进行性能优化。


文章来源于本人博客,发布于 2022-06-12,原文链接:https://imlht.com/archives/391/

相关推荐
会周易的程序员13 小时前
aiDgePLC iec61131 虚拟机 完整使用文档
c++·物联网·架构·st·iec61131
宇擎智脑科技15 小时前
DeepSeek Harness 架构解析:MCP 和 Skill 如何被统一为 Cordis 插件
架构·deepseek·harness·dsh
这个DBA有点耶16 小时前
分布式数据库到底该不该上?从判断标准到架构选型的实战思考
数据库·架构·dba
楚识科技17 小时前
破除通用瓶颈——企业级OCR定制化开发的架构思维与实战范式
架构·ocr
刘立军17 小时前
RESTful 与契约优先:规范接口定义,统一接口设计范式
后端·架构·ai编程
heimeiyingwang17 小时前
【架构实战】分布式事务:从CAP定理到Seata实战,一文讲透跨服务数据一致性
分布式·架构
独孤九剑打醒他18 小时前
RGB‑TOT 全架构系统仿真:红外波长簇光通信完整验证
架构
这个DBA有点耶19 小时前
从库延迟的“二次放大”效应:一次大事务,拖垮整个读写分离
数据库·mysql·架构
张宇Joaquin20 小时前
高性能模板库Eigen架构分析及性能优化实践
性能优化·架构
AI产品测评官21 小时前
AI 招聘系统的三代技术演进:从 DOM 注入到视觉语义读取的架构拆解
人工智能·架构·求职招聘