本书未发布

Go - wrk压测 - pprof

未匹配的标注

第一步:golang 支持 pprof#

package main

import (
    "net/http"
    _ "net/http/pprof"  //这一行不能少
)

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

第二步:访问 web#

http://127.0.0.1:6060/debug/pprof/

第三步:分析 pprof#

(1)每隔 60s 统计一次 cpu 耗时,并且在 web 上可视化。

go tool pprof http://localhost:6060/debug/pprof/profile\?seconds\=60
(pprof) help
(pprof) web

(2)也可以点击第二步的页面上的 profile,下载文件。然后执行命令:

go tool pprof path_of_pprof
(pprof) web

第四步:压测分析 pprof#

示例代码:

func BenchmarkBenchRequests(b *testing.B) {
    b.ResetTimer()
    b.SetParallelism(50) //设置并发量
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            req()
        }
    })
    b.StopTimer()
}
go test -bench=. -run=none -benchmem -benchtime=5s -cpuprofile=cpu_profile.out
go tool pprof -http="127.0.0.1:8080" cpu_profile.out

其他#

记录一次实际分析 case,从 mac 打包好代码发布到 dev 服务器,然后在 dev 服务器启动打包好的二进制,并且通过另外一个 go 项目压测。

在 mac 上执行时,必须先转成 linux 二进制文件

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build

然后按照上面的 1/2/3/4 步执行。可以在本地直接访问 dev 服务器,所以就可以这样:

go tool pprof http://192.168.98.10:6060/debug/pprof/profile\?seconds\=60
(pprof) web

分析到最后,猜测是因为 append 切片时导致的问题。通过压测发现 append 的长度直接影响性能,长度差了一半,性能也就差了一半。那接下来的问题就是如何优化 append 操作。

可以在代码中用 pprof 的函数监控某个函数的使用时间,代码如下:

func main() {
  f, _ := os.OpenFile("cpu.profile", os.O_CREATE|os.O_RDWR, 0644)
  defer f.Close()
  pprof.StartCPUProfile(f)
  defer pprof.StopCPUProfile()

  n := 10
  for i := 1; i <= 5; i++ {
    fmt.Printf("fib(%d)=%d\n", n, fib(n))
    n += 3 * i
  }
}

封装了 pprof 的包#

runtime/pprof 使用起来有些不便,因为要重复编写打开文件,开启分析,结束分析的代码。所以出现了包装了 runtime/pprof 的库:pkg/profilepkg/profile 的 GitHub 仓库地址为:https://github.com/pkg/profile。`pkg/profile` 只是对 `runtime/pprof` 做了一层封装,让它更好用。使用 `pkg/profile` 可以将代码简化为一行。使用前需要使用 `go get github.com/pkg/profile` 获取这个库。

defer profile.Start().Stop()

wrk 压测#

go 压测可以对比相同代码的处理性能,但是如果是两个方案的 TPS/QPS 对比,则 Go 压测是没办法直接做到。于是用 wrk 做压测。

wrk -t 1 -c 1 -d 1s --timeout 5s --latency  -s post.lua http://192.168.0.1:8000/xxx
# 参数调优
-t 服务器的CPU核数
-c 并发数量

Go - wrk压测 - pprof

Running 30s test @ http://www.bing.com (压测时间30s)

  8 threads and 200 connections (共8个测试线程,200个连接)

  Thread Stats   Avg      Stdev     Max   +/- Stdev
              (平均值) (标准差)(最大值)(正负一个标准差所占比例)
    Latency    46.67ms  215.38ms   1.67s    95.59%
    (延迟)
    Req/Sec     7.91k     1.15k   10.26k    70.77%
    (处理中的请求数, Req/Sec * connections 是发送的请求数量)

  Latency Distribution (延迟分布)
     50%    2.93ms
     75%    3.78ms
     90%    4.73ms
     99%    1.35s (99分位的延迟:%99的请求在1.35s以内)
  1790465 requests in 30.01s, 684.08MB read (30.01秒内共处理完成了1790465个请求,读取了684.08MB数据)
Requests/sec:  59658.29 (平均每秒处理完成59658.29个请求)
Transfer/sec:     22.79MB (平均每秒读取数据22.79MB

post.lua

wrk.method = "POST"

local reqURL = "http://192.168.98.10:8060/account/v2/action/bookkeeping/pg"
wrk.headers["Content-Type"] = "application/json"

local uuid = require("uuid")
function request()
    wrk.body = 'JSON'..uuid()..'JSON'
    return wrk.format('POST', reqURL, nil, body)
end

安装 wrk

git clone --depth=1 https://github.com/wg/wrk.git wrk
cd wrk
make
// move the executable to somewhere in your PATH
sudo cp wrk /usr/local/bin

安装 uuid:

luarocks install uuid

然后在 wrk 包底下执行:

cp  /usr/local/share/lua/5.1/uuid_0_3_1-uuid.lua .
mv uuid_0_3_1-uuid.lua uuid.lua

然后就可以用 uuid 了!

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 查看所有版本


暂无话题~