手写一个 http 性能测试工具(golang 实现)

用户头像
2流程序员
关注
发布于: 2020 年 07 月 22 日

一个简单的类似ab的性能测试工具。

输入要测试的URL、并发数、总请求数。

输出平均响应时间和95分位响应时间。

单元测试:

package benchtest
import (
"testing"
)
func TestCon10(t *testing.T) {
url := "https://www.baidu.com"
concurrency := uint(10)
requestNum := uint(100)
res := BenchWeb(url, "GET", requestNum, concurrency)
t.Log(res)
}
func TestCon100(t *testing.T) {
url := "https://www.baidu.com"
concurrency := uint(100)
requestNum := uint(1000)
res := BenchWeb(url, "GET", requestNum, concurrency)
t.Log(res)
}

实现:

package benchtest
import (
"math"
"net/http"
"sort"
"sync"
"time"
)
type BTReport struct {
Url string
Concurrency uint
Requests uint
TimeTotal float64
CompleteRequests uint
FailedRequests uint
ResponseTimeAvg float64
ResponseTime95 float64
}
type onceReqReport struct {
elapsed time.Duration
success bool
}
// 发起单个http请求
func sendRequest(url string, method string, resultChan chan *onceReqReport, wg *sync.WaitGroup) {
res := onceReqReport{}
t0 := time.Now()
request, _ := http.NewRequest(method, url, nil)
client := http.Client{}
resp, _ := client.Do(request)
if resp.StatusCode >= 400 {
res.success = false
} else {
res.success = true
}
t1 := time.Since(t0)
res.elapsed = t1
resultChan <- &res
wg.Done()
}
// 发起批量请求,并等待所有结果返回
func concurRequest(concurrency uint, url string, method string, resultChan chan *onceReqReport) {
wg := sync.WaitGroup{}
for i := 0; i < int(concurrency); i++ {
go sendRequest(url, method, resultChan, &wg)
wg.Add(1)
}
wg.Wait()
}
// 收集数据
func collecter(resChan chan *onceReqReport, result []*onceReqReport) {
for item := range resChan {
result = append(result, item)
}
}
// 统计
func static(result []*onceReqReport) (failCount uint, time95, avg float64) {
elapseSet := make([]float64, 0)
failCount = uint(0)
sum := 0.0 // 总耗时
for _, r := range result {
e := r.elapsed.Seconds()
elapseSet = append(elapseSet, e)
sum += e
if !r.success {
failCount++
}
}
// 排序
sort.Float64s(elapseSet)
// 算95分位
idx := math.Floor(float64(len(result)) * 0.95)
time95 = elapseSet[int(idx)]
// 算平均值
avg = sum / float64(len(result))
return
}
// web性能压测
func BenchWeb(url string, method string, requestNum uint, concurrency uint) *BTReport {
// todo:检查url
// 按并发数发起请求
count := requestNum / concurrency // 需要发起并发的次数
if requestNum%concurrency != 0 { // 有余数就要多一次
count++
}
resultChan := make(chan *onceReqReport, concurrency) // 结果通过Chan输送
result := make([]*onceReqReport, 0)
go collecter(resultChan, result) // 收集结果
t0 := time.Now()
for i := 0; i < int(count); i++ {
concurRequest(concurrency, url, method, resultChan) // 并发请求
}
tn := time.Since(t0)
// 统计结果
failCount, time95, avg := static(result)
return &BTReport{
Url: url,
Concurrency: concurrency,
Requests: requestNum,
TimeTotal: tn.Seconds(),
CompleteRequests: requestNum - failCount,
FailedRequests: failCount,
ResponseTimeAvg: avg,
ResponseTime95: time95,
}
}



用户头像

2流程序员

关注

还未添加个人签名 2020.03.18 加入

还未添加个人简介

评论

发布
暂无评论
手写一个http性能测试工具(golang实现)