写点什么

压测程序

用户头像
GalaxyCreater
关注
发布于: 2020 年 07 月 22 日



-----------------------------------------------------------------------------

代码实现:

package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"sort"
"strconv"
"sync"
"time"
)
var MAX_UINT64 uint64 = ^uint64(0)
var (
pressureTimes int = 100 //压测次数
pressureDruation int = 3 // 单次压测时间(单位:秒)
goroutineCnt int = 10
Url string = "https://www.baidu.com" // 请求压测链接
httpTimeout uint = 10 // http超时
)
// 记录http请求结果
type UrlResult struct {
code int // http错误码;0为请求错误
costTime int64 // 响应时间
}
type UrlResultType []*UrlResult
func (n UrlResultType) Len() int {
return len(n)
}
func (n UrlResultType) Swap(i, j int) {
n[i], n[j] = n[j], n[i]
}
func (n UrlResultType) Less(i, j int) bool {
return n[i].costTime < n[j].costTime
}
func httpGet(url string, timeout uint) (code int) {
code = 0
client := &http.Client{
Timeout: time.Duration(timeout) * time.Second,
}
resp, err := client.Get(url)
if err != nil {
fmt.Printf("http get err, url=%s\n", url)
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
fmt.Printf("resp status=%v, url=%s\n", resp.Status, url)
return
}
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("resp ReadAll err : %s\n", err)
return
}
code = resp.StatusCode
return
}
// http请求,并记录请求信息
func httpRequest(url string, timeOut uint) (resp *UrlResult) {
// 记录压测信息
defer func(begin_time int64) {
resp.costTime = time.Now().UnixNano()/1e6 - begin_time
}(time.Now().UnixNano() / 1e6)
resp = &UrlResult{}
resp.code = httpGet(url, timeOut)
return
}
func Stress(goroutineCnt int, runtime int) (respTime int64, average float64, all int) {
var total uint64 = 0
respList := UrlResultType{}
var wg sync.WaitGroup
for i := 0; i < goroutineCnt; i++ {
wg.Add(1)
go func() {
defer wg.Done()
begin_time := time.Now().Second()
for {
resp := httpRequest(Url, httpTimeout)
respList = append(respList, resp)
if total+uint64(resp.costTime) > MAX_UINT64 {
fmt.Println("too big")
}
total += uint64(resp.costTime)
// 已过测试时间
if time.Now().Second()-begin_time > runtime {
break
}
}
}()
}
wg.Wait()
// 统计
sort.Sort(respList)
all = len(respList)
cnt := int(float32(0.95) * float32(all))
return respList[all-cnt].costTime, float64(uint64(total) / uint64(all)), all
}
// ./main 测试次数 线程数
func main() {
if len(os.Args) != 4 {
fmt.Println("invalid args, command: ./main 测试次数 测试时间 线程数 ")
} else {
pressureTimes, _ = strconv.Atoi(os.Args[1])
pressureDruation, _ = strconv.Atoi(os.Args[2])
goroutineCnt, _ = strconv.Atoi(os.Args[3])
}
for i := 0; i < pressureTimes; i++ {
resp, agv, total := Stress(goroutineCnt, pressureDruation)
fmt.Println(`总请求数:`, total, `95%响应时间:`, "ms", resp, `平均响应时间:`, agv, " ms")
}
}

-----------------------------------------------------------------------------

输出结果:



发布于: 2020 年 07 月 22 日阅读数: 47
用户头像

GalaxyCreater

关注

还未添加个人签名 2019.04.21 加入

还未添加个人简介

评论

发布
暂无评论
压测程序