写点什么

架构师训练营第七周作业

用户头像
zamkai
关注
发布于: 2021 年 01 月 11 日

作业 1

性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?


根据队列理论(Queue theory),系统的并发请求数(N)、系统的吞吐量(X)以及请求的响应时间(R)之间,在系统处于稳定状态时,它们之间的关系为:


N = X * R


另外,响应时间 R 等于请求在系统中的等待时间(W)加上实际处理时间(S),即:


R = W + S


根据上面的公式,


  1. 当系统的并发请求数 N 低于系统资源允许的峰值时,请求的平均响应时间 R 基本保持不变,随着请求数的增长,吞吐量 X 则相应提高;


  1. 当系统的并发请求数 N 超过系统的处理能力峰值时,

  • 系统内的资源使用率会提高,请求对资源的竞争更激烈,请求的平均等待时间会增加,所以响应时间 R 会增大;

  • 此时不能及时处理的请求都会在各种形式的队列(线程队列、网卡缓存)中等待,系统仍然能够稳定工作,所以这种状态下吞吐量 X 基本保持不变;


  1. 当系统并发请求继续增长时,可能发生以下情况:

  • 系统的设计存在缺陷,缺少降级等保护机制,请求数超过某些资源的处理能力(比如超过队列的最大容量),导致资源和系统的不可用;

  • 系统通过降级、熔断等机制,拒绝执行某些请求,这样响应时间 R 和吞吐量 X 能够维持在一个稳定的水平,但是另外一个性能指标:请求拒绝执行比例将增长。


用你熟悉的编程语言写一个 Web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 


测试工具(benchmark)

package benchmark
import ( "fmt" "io/ioutil" "net/http" "sort" "sync" "time")
// Report benchmark reporttype Report struct { // url to be tested url string
// how many requests were sent in test times int
// latency of 95% requests latency95 float64}
//HTTPBenchmark HTTPBenchmark generate report by invoking http requests and evalaluting responsesfunc HTTPBenchmark(url string, times int) Report { if times <= 0 { return Report{url, times, -1} }
var collector []chan float64 = make([]chan float64, times) var latch sync.WaitGroup
latch.Add(times) for invoke := 0; invoke < times; invoke++ { collector[invoke] = make(chan float64, 1) go requestHTTP(url, &latch, collector[invoke]) } fmt.Printf("Started %d jobs and waiting for the results\n", times) latch.Wait() fmt.Printf("All %d jobs were finished\n", times)
var responses []float64 = make([]float64, times) for invoke, collected := range collector { responses[invoke] = <-collected }
sort.Slice(responses, func(r1, r2 int) bool { return responses[r1] < responses[r2] })
var total float64 for r := 0; r < int(0.95*float64(times)); r++ { total = total + responses[r] }
return Report{ url, times, total / float64(times)}}
func requestHTTP(url string, latch *sync.WaitGroup, ch chan<- float64) { defer latch.Done()
start := time.Now() rsp, err := http.Get(url) var elapsed float64 = time.Since(start).Seconds()
if err != nil { fmt.Printf("failed to get response from '%s', detail: %s\n", url, err) } else { body, _ := ioutil.ReadAll(rsp.Body) fmt.Printf("get response from '%s' (lenth: '%d') in %.2f seconds \n", url, len(body), elapsed) }
ch <- elapsed close(ch)}
复制代码

单元测试

package benchmark
import ( "fmt"
. "github.com/onsi/ginkgo")
var _ = Describe("http benchamark test", func() { When("Test baidu by 100 concurrent requests", func() { var report Report = HTTPBenchmark("http://www.baidu.com", 100) fmt.Printf("%v", report) })})
复制代码

作业二(学习总结)

软件性能


响应时间/吞吐量/并发请求

这里老师介绍了性能的主要指标:响应时间和吞吐量,并说明了两者和并发请求数量之间的关系。


我之前对这个概念的理解比较模糊,在老师介绍之后,我特意找了一本相关的书籍(`Software Performanc and Scalability`),该书以队列理论为基础,详细说明了响应时间、吞吐量、并发请求以及系统资源使用率之间的关系。我决定后面两周把这本书学习完。


性能测试

性能验证测试

验证系统能否达到预期的性能设计指标,即:系统能否基于一定的资源,在给定的负荷下,达到预期的性能指标。


负载测试

找到/验证系统的最大有效负载,当负载超过该值时,系统指标开始下降。


压力测试

找到/验证系统的最大承受能力,当负载超过该值时,系统不再可用。


稳定性测试

验证系统可以在特性环境下、使用给定资源,能够长时间的在给定并发请求压力下稳定工作。


全链路压力测试

对系统进行的端到端的压力测试,目的是找到系统的处理瓶颈。


大致方法是,模拟用户真实行为,构造真实数量的并发访问,记录系统执行过程中的执行路径,各个环节、中间件的响应时间,得到系统的性能 profile。通过分析该 profile,找到处理瓶颈,为容量规划和性能优化提供依据。


性能优化思想

基于性能测试的优化

优化必须基于测试结果。


  1. 构造/执行性能测试;

  2. 分析测试结果;

  3. 优化;

  4. 继续执行测试,验证优化结果,直到指标达到预期


分层优化

影响系统性能的因素包括硬件、软件和网络,性能优化时需要全面、综合考虑这些因素。这些因素大致可以分为以下层面:


  • 硬件

  • 操作系统

  • 虚拟机/容器

  • 网络

  • 中间件

  • 架构

  • 代码


性能优化技巧


操作系统


并发/异步


用户头像

zamkai

关注

还未添加个人签名 2018.02.24 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第七周作业