手写一个 http 性能测试工具(golang 实现)
发布于: 2020 年 07 月 22 日
一个简单的类似ab的性能测试工具。
输入要测试的URL、并发数、总请求数。
输出平均响应时间和95分位响应时间。
单元测试:
package benchtestimport ( "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 benchtestimport ( "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, }}
划线
评论
复制
发布于: 2020 年 07 月 22 日阅读数: 66
2流程序员
关注
还未添加个人签名 2020.03.18 加入
还未添加个人简介
评论