Golang 性能优化实战

作者:trumanyan,腾讯 CSIG 后台开发工程师

项目背景

网关服务作为统一接入服务,是大部分服务的统一入口。为了避免成功瓶颈,需要对其进行尽可能地优化。因此,特别总结一下 golang 后台服务性能优化的方式,并对网关服务进行优化。

技术背景:

  • 基于 tarsgo 框架的 http 接入服务,下游服务使用 tarsgo 协议进行交互

性能指标

网关服务本身没有业务逻辑处理,仅作为统一入口进行请求转发,因此我们主要关注下列指标

  • 吞吐量:每秒钟可以处理的请求数

  • 响应时间:从客户端发出请求,到收到回包的总耗时

定位瓶颈

一般后台服务的瓶颈主要为 CPU,内存,IO 操作中的一个或多个。若这三者的负载都不高,但系统吞吐量低,基本就是代码逻辑出问题了。

在代码正常运行的情况下,我们要针对某个方面的高负载进行优化,才能提高系统的性能。golang 可通过 benchmark 加 pprof 来定位具体的性能瓶颈。

benchmark 简介

go test -v gate_test.go -run=none -bench=. -benchtime=3s -cpuprofile cpu.prof -memprofile mem.prof
  • -run 知道单次测试,一般用于代码逻辑验证

  • -bench=. 执行所有 Benchmark,也可以通过用例函数名来指定部分测试用例

  • -benchtime 指定测试执行时长

  • -cpuprofile 输出 cpu 的 pprof 信息文件

  • -memprofile 输出 heap 的 pprof 信息文件。

  • -blockprofile 阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置

  • -mutexprofile 互斥锁分析,报告互斥锁的竞争情况

benchmark 测试用例常用函数
  • b.ReportAllocs() 输出单次循环使用的内存数量和对象 allocs 信息

  • b.RunParallel() 使用协程并发测试

  • b.SetBytes(n int64) 设置单次循环使用的内存数量

pprof 简介

生成方式
  • runtime/pprof: 手动调用如runtime.StartCPUProfile或者runtime.StopCPUProfile等 API 来生成和写入采样文件,灵活性高。主要用于本地测试。

  • net/http/pprof: 通过 http 服务获取 Profile 采样文件,简单易用,适用于对应用程序的整体监控。通过 runtime/pprof 实现。主要用于服务器端测试。

  • go test: 通过 go test -bench . -cpuprofile cpuprofile.out生成采样文件,主要用于本地基准测试。可用于重点测试某些函数。

查看方式
  • go tool pprof [options][binary] ...

    • --text 纯文本

    • --web 生成 svg 并用浏览器打开(如果 svg 的默认打开方式是浏览器)

    • --svg 只生成 svg

    • --list funcname 筛选出正则匹配 funcname 的函数的信息

    • -http=":port" 直接本地浏览器打开 profile 查看(包括 top,graph,火焰图等)

  • go tool pprof -base profile1 profile2

    • 对比查看 2 个 profile,一般用于代码修改前后对比,定位差异点。

  • 通过命令行方式查看 profile 时,可以在命令行对话中,使用下列命令,查看相关信息

    • flat  flat%   sum%        cum   cum%
       5.95s 27.56% 27.56%      5.95s 27.56%  runtime.usleep
       4.97s 23.02% 50.58%      5.08s 23.53%  sync.(*RWMutex).RLock
       4.46s 20.66% 71.24%      4.46s 20.66%  sync.(*RWMutex).RUnlock
       2.69s 12.46% 83.70%      2.69s 12.46%  runtime.pthread_cond_wait
       1.50s  6.95% 90.64%      1.50s  6.95%  runtime.pthread_cond_signal
      
    • flat: 采样时,该函数正在运行的次数*采样频率(10ms),即得到估算的函数运行”采样时间”。这里不包括函数等待子函数返回。

    • flat%: flat / 总采样时间值

    • sum%: 前面所有行的 flat% 的累加值,如第三行 sum% = 71.24% = 27.56% + 50.58%

    • cum: 采样时,该函数出现在调用堆栈的采样时间,包括函数等待子函数返回。因此 flat <= cum

    • cum%: cum / 总采样时间值

    • topN [-cum] 查看前 N 个数据:

  • list ncname 查看某个函数的详细信息,可以明确具体的资源(cpu,内存等)是由哪一行触发的。

pprof 接入 tarsgo

  1. 服务中 main 方法插入代码

    cfg := tars.GetServerConfig()
    profMux := &tars.TarsHttpMux{}
    profMux.HandleFunc("/debug/pprof/", pprof.Index)
    profMux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    profMux.HandleFunc("/debug/pprof/profile", pprof.Profile)
    profMux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
    profMux.HandleFunc("/debug/pprof/trace", pprof.Trace)
    tars.AddHttpServant(profMux, cfg.App+"."+cfg.Server+".ProfObj")
    
  2. taf 管理平台中,添加 servant:ProfObj (名字可自己修改)

  3. 发布服务

查看 tasrgo 服务的 pprof

  1. 保证开发机能直接访问到 tarsgo 节点部署的 ip 和 port。

  2. 查看 profile(http 地址中的 ip,port 为 ProfObj 的 ip 和 port)

    # 下载cpu profile
    go tool pprof http://ip:port/debug/pprof/profile?seconds=120 # 等待120s,不带此参数时等待30s
    
    # 下载heap profile
    go tool pprof http://ip:port/debug/pprof/heap
    
    # 下载goroutine profile
    go tool pprof http://ip:port/debug/pprof/goroutine
    
    # 下载block profile
    go tool pprof http://ip:port/debug/pprof/block
    
    # 下载mutex profile
    go tool pprof http://ip:port/debug/pprof/mutex
    
    # 下载20秒的trace记录(遇到棘手问题时,查看trace会比较容易定位)
     curl http://
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值