架构师训练营第 0 期第 7 周作业
1、性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?
性能压测的时候,随着并发压力的增加,系统的响应时间变长,吞吐量降低;
原因:
首先先来看 吞吐量 、响应时间 和 并发数 的定义,以及它们之间的关系;
1-1、响应时间
所谓响应时间,就是指 系统 【从发出请求开始】 到 【收到最后响应数据】 需要的时间。响应时间是系统最重要的性能指标,直观的反映系统的快慢。
比如 用户在电商购买商品,从发出支付请求到返回支付结果,中间消耗的时间就是响应时间。
1-2、并发数
系统能够【同时处理】请求的数目,这个数字也反映了系统的负载特性。对于网站而言,并发数即系统并发用户数,指同时提交请求的用户数目。
这里的【同时请求】,是指用户发送请求后,请求到达系统不用等待,系统可以直接处理;
并发数一般与系统硬件资源,如CPU、内存、硬盘、网络IO有关;
1-3、吞吐量
【单位时间】内系统处理的请求数量,体现系统的处理能力。对于网站,可以用“请求数/秒”或者“页面数/秒”来衡量,也可以用“访问人数/天” 或者 “处理的业务数/小时” 等来衡量。
TPS(每秒事务数)也是吞吐量的一个指标,还有 HPS(每秒HTTP请求数),QPS(每秒查询数)等。
1-4、响应时间、并发数 和 吞吐量 之间的关系
从上面的定义中,可以举例,单位时间用【秒】统计:
系统处理的【并发数】为1,【响应时间】为1秒,那么1秒钟可以处理的请求数量就是1,即吞吐量为1;
系统处理的【并发数】为1,【响应时间】为0.5秒,一秒钟可以响应2个请求,系统的吞吐量为2;
系统处理的【并发数】为2,【响应时间】为0.5秒,一秒钟可以响应4个请求,系统的吞吐量为4;
按照上面的推理,得到 响应时间、并发数 和 吞吐量的 关系:
从公式看,系统【响应时间】不变的情况下,【吞吐量】会随着【并发数量】增加而增加;
但是服务器的资源是有限制的,特别是CPU的核数,通常CPU的一个核只能处理一个线程,而当并发请求的线程数量超过CPU核数,其他线程将等待【占用CPU】的线程释放资源,这时才能继续执行。这里要介绍一个重要指标,就是System Load;
所谓 System Load,就是系统负载,指当前【正在被CPU执行】和【等待被CPU执行】的进程数目总和,是反映系统忙闲程度的重要指标。
多核CPU情况下,完美情况是所有CPU都在使用,没有进程在等待处理,所以 System Load的理想值是CPU的数目。
当load值低于CPU数目时,表示CPU有空闲,资源存在浪费;当load值高于CPU数目时,表示进程在排队等待CPU,表示系统资源不足,影响应用程序的执行性能。
回到上面的问题,为什么随着【并发】压力增加,系统【响应时间】会变成,【吞吐量】会降低?
当 System Load数量 高于 CPU数目,此时 请求就需要等待 CPU释放资源,比如原来一个请求处理时间需要100ms,因为资源等待问题,一个请求的【响应时间】变为 200ms,随着【并发数】增加,等待的请求数只能排队,【响应时间】越来越长,从而导致【吞吐量】降低;
下面两张图,反映了随着【并发数】增加,系统【响应时间】和【吞吐量】的变化
查看上图还有个问题,作为架构师,为了保证系统稳定,一般将系统的状态维持在上面 a、b、c 三个点的什么部分?
这看似是设计问题,其实是【经济】问题,当一个系统已经使用解决高并发设计的方法,如 缓存、异步消息队列、数据库分片 等技术,优化空间有限,或者优化需要付出非常昂贵代价时,应该如何选择;
如果公司的资金成本比较充裕,为了保证系统的问题,最好的方式就是水平扩容服务器或者纵向提升服务器性能,也就是提升硬件资源,将系统维持在b点的左边,这样即使系统的请求增加,也有一段缓冲时间;
而如果公司的资金成本不是很宽裕,硬件升级对于公司的支出是很大的负担,维持在b点的右侧,虽然缓冲的余地变少,但是不至于系统立马就挂的情况;
2、用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。
题目分析:
1、输入参数:URL、请求总次数、并发数,这里并发数就是网站一次收到并发的数量,在Java中首先想到多线程,10并发,对应10个线程同时发送请求,可以用【线程池】实现;
2、请求总数是100次,并发10,也就是分10批发送,最后记录100次请求的响应时间;
具体实现如下:
首先,实现一个Http工具,用来发送Http请求,这里需要主要,为了避免重复创建连接带来的性能损耗,在初始化压测时创建【http连接池】,避免每次请求都要创建http连接;其次,考虑到请求超时的问题,要设置建立连接的超时和处理请求的超时时间;
其次,因为使用Java的多线程实现并发,这时创建一个Task,用来发送请求,并且记录单个请求的耗时,并且将耗时作为结果返回,用来最终的性能测试统计,所以这里实现Callable接口;因为一次并发为10,这里CountDownLatch用来记录次数,每请求一次减一;
最后,就是总的性能测试调度代码,构造函数使用【请求URL】,【请求次数】和【并发数】,在构造函数中【初始化线程池】和【Http连接池】,创建记录请求响应时间的列表,定义用来计算【平均时间】和【TP95】的方法,程序如下:
输出结果:
版权声明: 本文为 InfoQ 作者【Arthur】的原创文章。
原文链接:【http://xie.infoq.cn/article/f6cb1dc85eb538055e07d2e36】。未经作者许可,禁止转载。
评论