1. 什么是代码压测和负载测试
代码压测是指利用各种工具模拟多用户同时请求访问系统,在短时间内模拟系统的高并发访问情况,测试系统在峰值状态下是否能够承受用户访问量的冲击,以此来确定系统的性能和稳定性。
负载测试则是指确定系统最大负荷容量的测试,即测试系统在多大的负载下会崩溃,通过这个测试,可以确定系统在最坏情况下的一个临界点,帮助开发人员优化系统架构和调整硬件配置。
2. Go语言中进行代码压测和负载测试的工具
2.1 Go语言自带的并发测试工具
Go语言中自带了一个 non-testing 的测试框架,可以用来做并发/压力测试。使用该框架非常简单,只需在测试函数上加上go test -bench="."即可进行测试。
func BenchmarkHello(b *testing.B) {
for i := 0; i < b.N; i++ {
fmt.Sprintf("hello")
}
}
在控制台执行命令:go test -bench="."即可开始测试。
2.2 vegeta工具
Vegeta是一个基于Go语言编写的高性能HTTP负载测试工具,整个工具使用Go语言的协程和socket通讯并发的模拟HTTP请求,并统计、输出请求结果的结果。Vegeta的性能非常高效,可以输出高质量的压测数据,并且非常容易使用和定制。
Vegeta只支持HTTP协议。
下面是一段具体的使用Vegeta进行压力测试的代码:
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/tsenart/vegeta/lib"
)
func main() {
rate := vegeta.Rate{Freq: 100, Per: time.Second}
duration := 4 * time.Second
targeter := vegeta.NewStaticTargeter(vegeta.Target{
Method: "GET",
URL: "http://localhost:8080/foo",
})
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration, "Some description") {
metrics.Add(res)
}
metrics.Close()
fmt.Printf("MaxLatency: %s\n", metrics.Latencies.Max)
fmt.Printf("99th percentile Latency: %s\n", metrics.Latencies.P99)
fmt.Printf("Mean Latency: %s\n", metrics.Latencies.Mean)
fmt.Printf("Request count: %d\n", metrics.Requests)
fmt.Printf("Requests per second: %f\n", float64(metrics.Requests)/metrics.Duration.Seconds())
fmt.Printf("Bytes In per second: %f\n", float64(metrics.BytesIn)/metrics.Duration.Seconds())
fmt.Printf("Bytes Out per second: %f\n", float64(metrics.BytesOut)/metrics.Duration.Seconds())
fmt.Printf("Errors: %d (%.5f%%)\n", metrics.Errors.Len(), (float64(metrics.Errors.Len())/float64(metrics.Requests))*100)
statusCodes := make(map[string]int)
for _, code := range metrics.StatusCodes {
statusCodes[code]++
}
fmt.Println("Status Codes:")
for code, count := range statusCodes {
fmt.Printf("\t%s: %d\n", code, count)
}
}
运行程序后可以获得以下结果:
MaxLatency: 681.945954ms
99th percentile Latency: 413.857007ms
Mean Latency: 87.701504ms
Request count: 397
Requests per second: 100.542390
Bytes In per second: 41112.339955
Bytes Out per second: 10296.156525
Errors: 0 (0.00000%)
Status Codes:
200: 397
2.3 Go-stress-testing工具
Go-stress-testing是一个使用Go编写的简单易用的负载测试工具,可以对HTTP、WebSocket等协议进行测试。
以下是使用Go-stress-testing进行压测的例子:
package main
import (
"fmt"
"strconv"
"github.com/iaping/go-stress-testing/maker"
"github.com/iaping/go-stress-testing/runner"
)
func main() {
fr := maker.NewFastHTTPReuqest([]string{"http://localhost:8080/foo"})
fr.SetBody("key=value")
task := maker.NewTask()
for i := 0; i < 1000; i++ {
task.AddRequest(fr)
}
task.SetMaxRequestCount(10000)
task.SetMaxWorkerCount(1000)
task.SetLogger(runner.NewPrinterLogger())
err := task.Run()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("All task finished.")
result := task.GetResult()
fmt.Printf("Result: code: %d, calls: %d, req/sec: %d\n", result.ResCode, result.Calls, result.Calls/result.Time)
statusCodes := result.GetStatusCodeCount()
for i, v := range statusCodes {
fmt.Println("Code:", i, ", Count:", v)
}
}
3. 总结
Go语言是一个轻量级且高效的语言,拥有非常强大的并发能力,因此可以非常好地支持代码压测和负载测试。本篇文章介绍了Go语言中三个常用的工具:Go语言自带的并发测试工具、Vegeta工具和Go-stress-testing工具,这些工具都有其自身的特点和适用场景,在实际项目中可根据需要进行选择使用。