压测程序
发布于: 2020 年 07 月 22 日
-----------------------------------------------------------------------------
代码实现:
package mainimport ( "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 []*UrlResultfunc (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
版权声明: 本文为 InfoQ 作者【GalaxyCreater】的原创文章。
原文链接:【http://xie.infoq.cn/article/2609790701a9454ad4980a473】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
还未添加个人签名 2019.04.21 加入
还未添加个人简介
评论