《架构师训练营》第七周命题作业
发布于: 2020 年 07 月 18 日
1、性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
压测初期,系统资源在可以接受的范围内,此时系统响应时间会相对比较稳定不会随并发压力的增加而增加,吞吐量会随并发数的增加而增加。
持续增加并发压力,到达系统资源使用的临界值,系统响应时间会逐渐变长,吞吐量逐渐边少,直至系统崩溃。
2、压测工具
2.1 代码实现
使用 go 语言开发,程序设计思路如下:
使用 goruntine 模拟并发请求,用一个 goruntine 等待其他并发的处理结果,通过 channel 将请求结果发送到负责处理结果的 goruntine 统计、处理。
request
request 用来发送请求,只关心请求有没有成功。
func request(url string) error { response, err := http.Get(url) defer func() { if response != nil && response.Body != nil { _ = response.Body.Close() } }() if err != nil { return err } if response.StatusCode != http.StatusOK { return errors.New(fmt.Sprintf("Error response code: %d", response.StatusCode)) } return nil}
runner
runner 用来顺序执行指定个数的请求,并将结果通过 channel 发送出去
type Response struct { label string elapsed int64 err error}func runner(count int, url string, resChan chan Response, wg *sync.WaitGroup, label string) { for i := 0; i < count; i++ { start := time.Now() err := request(url) elapsed := time.Since(start) resChan <- Response{ elapsed: elapsed.Milliseconds(), err: err, label: fmt.Sprintf("%s-%d", label, i), } } wg.Done()}
receiver
receiver 用来接收、统计请求结果
func receiver(recvChan chan Response) { var ( resArr []Response totalCount, successCount, failedCount int totalTime, _95TotalTime int64 ) for { totalCount++ res, ok := <-recvChan if !ok { break } if res.err != nil { failedCount++ } else { successCount++ } totalTime += res.elapsed log.Printf("[%s\t%d\t]\tResponse takes %dms", res.label, totalCount, res.elapsed) resArr = append(resArr, res) } log.Printf("Toal success count: %d, failed count: %d", successCount, failedCount) log.Printf("Average time: %dms", totalTime/int64(totalCount)) sort.Slice(resArr, func(i, j int) bool { return resArr[i].elapsed < resArr[j].elapsed }) _95Count := totalCount * 95 / 100 for i := 0; i < _95Count; i++ { _95TotalTime += resArr[i].elapsed } log.Printf("95%% average time: %dms", _95TotalTime/int64(_95Count))}
LoadRun
LoadRun 用来启动测试
func LoadRun(currency, count int, url string) { wg := sync.WaitGroup{} wg.Add(currency) resChan := make(chan Response, 10) for i := 0; i < currency; i++ { label := fmt.Sprintf("goroutine-%d", i) go runner(count, url, resChan, &wg, label) } go receiver(resChan) wg.Wait() close(resChan) time.Sleep(time.Second)}
2.2 测试结果
// https://www.baidu.com2020/07/18 14:30:34 Toal success count: 1000, failed count: 02020/07/18 14:30:34 Average time: 344ms2020/07/18 14:30:34 95% average time: 333ms// https://www.163.com2020/07/18 14:45:34 Toal success count: 0, failed count: 10002020/07/18 14:45:34 Average time: 374ms2020/07/18 14:45:34 95% average time: 361ms// https://www.qq.com2020/07/18 14:47:12 Toal success count: 1000, failed count: 02020/07/18 14:47:12 Average time: 375ms2020/07/18 14:47:12 95% average time: 334ms// https://www.taobao.com2020/07/18 14:49:08 Toal success count: 1000, failed count: 02020/07/18 14:49:08 Average time: 838ms2020/07/18 14:49:08 95% average time: 793ms
划线
评论
复制
发布于: 2020 年 07 月 18 日 阅读数: 29
黑
关注
还未添加个人签名 2018.06.14 加入
还未添加个人简介
评论