文档章节

跟我一起认识Little's Law

zjg23
 zjg23
发布于 10/18 14:32
字数 2844
阅读 2502
收藏 45

1.前言

开发的同学或多或少都会跟“性能”这个玩意打交道,本文将要介绍的Little's Law跟衡量性能的常见指标关系密切,所以在引出今天的主角Little's Law之前,有必要先统一一下我们描述“性能”的“基本语言”,毕竟语言不通是没法交流的不是。另外,以下叙述都是我的个人理解,不当之处请指正。

2.“性能”的“基本语言”

不同的服务设备对性能的定义也不同,例如CPU主要看主频,磁盘主要看IOPS。本文主要针对后端的软件服务性能(比如api服务,数据库服务等)展开讨论。限定好范围后就应该给出一个性能的定义了:性能就是服务的处理请求的能力。衡量性能的指标常见的有三个:并发用户数、吞吐量、响应时间。

2.1并发用户数

指真正对服务发送请求的用户数量,需要注意和在线用户数的区别; 比如,某一时刻,在线用户数为1000,其中只有100个用户的操作触发了与远端服务的交互, 那么这时对远端服务来说,并发用户数是100,而不是1000。

2.2吞吐量

单位时间内处理的请求数。

2.3响应时间

对应的英文是response time,也有的地方用 latency表示,即延迟。 需要统计一个时间段内的响应时间,求出特征值来表示响应时间。 常见的特征值包括平均值、最大值、最小值、分位值。

3.主角Little's Law登场

3.1 Little's Law的定义

稳定的系统中同时被服务的用户数量等于用户到达系统的速度乘以每个用户在系统中驻留的时间,适用于所有需要排队的场景。 对应公式表示为:

N = X * R,其中
N 表示系统中同时活动的用户,
X 表示用户相继到达系统的速率,在稳定(这个词非常重要!!!)状态(用户到达系统的速度等于用户离开系统的速度)时即为系统吞吐量,
R 表示每个用户在系统中平均的驻留时间。

比如说,你正在排队进入一个体检中心,你可以通过估计人们进入的速率来知道自己还要等待多长时间。

体检中心能容纳约600人,每个人完成体检的时间是2个小时,
即R=2小时,N=600人,根据公式计算:
X=N/R=600人/2小时=300人/小时
所以以每小时300人的速度进入。
如果现在你的前面还有300个人,那么大约还要等上一个小时才会进入体检中心。

3.2 Little's Law与性能指标的关系

前一部分说的三个指标的关系可以用Little's Law来表示,因为对用户请求不断发送到服务端进行处理的情况来说,就是一种排队的场景,把Little's Law具体到这种场景那么对应的公式为:

并发数=吞吐量*响应时间

3.3 通过实例感受Little's Law的存在

下面主要从接口服务和mysql服务两个实例来观察Little's Law的存在。

3.3.1 接口服务的实例

3.3.1.1 准备过程介绍
  1. 基于springboot暴露一个接口 接口本身会根据参数值休眠一段时间,这样客户端的压测工具就可以控制接口的响应时间了。
@RestController
public class ApiLatency {

    @RequestMapping("/test/latency/{ms}")
    public String latency(@PathVariable long ms) {

        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "Hello World!";
    }
}
  1. 通过jmeter设置不同的并发数对上面的接口进行压测
3.3.1.2 结果展示与分析

初始阶段响应时间基本稳定,吞吐量随着并发数的增加而增加; 随着并发数增加,系统到达“拐点”,吞吐量开始出现下降的趋势,同时响应时间也开始增大;继续增加并发数,系统负载超负荷,从而进入过饱和区,此时响应时间急剧增大,吞吐量急剧下降。在“拐点”之前和刚进入拐点这段区域,此时可以认为系统为“稳定”的,此时并发数、吞吐量、平均响应时间是符合Little's Law公式的。

3.3.2 mysql服务的实例

3.3.2.1 准备过程介绍
  1. 准备一个腾讯云mysql服务(5.6版本,配置为2核4G)和一台云服务器(腾讯云内网测试)
  2. 用sysbench(0.5版本)对mysql服务进行测试
## 数据预置
sysbench --mysql-host=192.168.0.10 --mysql-port=3306 --mysql-user=root --mysql-password=test --mysql-db=loadtest --mysql-table-engine=innodb --test=/usr/local/share/sysbench/tests/include/oltp_legacy/oltp.lua --oltp_tables_count=8 --oltp-table-size=4000000  --rand-init=on prepare

## 执行shell脚本进行测试
for i in 5 7 8 10 12 25 50 128 200 400 700 1000
do
sysbench --mysql-host=192.168.0.10 --mysql-port=3306 --mysql-user=root --mysql-password=test --mysql-db=loadtest  --test=/usr/local/share/sysbench/tests/include/oltp_legacy/oltp.lua --oltp_tables_count=8 --oltp-table-size=4000000 --num-threads=${i} --oltp-read-only=off --rand-type=special --max-time=180 --max-requests=0 --percentile=99 --oltp-point-selects=4 --report-interval=3 --forced-shutdown=1 run | tee -a sysbench.${i}.oltp.txt
done

## 清理数据
sysbench --mysql-host=192.168.0.10 --mysql-port=3306 --mysql-user=root --mysql-password=test --mysql-db=loadtest --mysql-table-engine=innodb --test=/usr/local/share/sysbench/tests/include/oltp_legacy/oltp.lua --oltp_tables_count=8 --oltp-table-size=4000000  --rand-init=on cleanup

## 脚本中参数的含义
--oltp_tables_count=8,表示本次用于测试的表数量为8张。
--oltp-table-size=4000000,表示本次测试使用的表行数均为400万行。
--num-threads=n,表示本次测试的客户端连接并发数为n。
--oltp-read-only=off ,off 表示测试关闭只读测试模型,采用读写混合模型。
--rand-type=special,表示随机模型为特定的。
--max-time=180,表示本次测试的执行时间180秒。
--max-requests=0,0 表示不限制总请求数,而是按 max-time 来测试。
--percentile=99,表示设定采样比例,默认是95%,即丢弃1%的长请求,在剩余的99%里取最大值。
--oltp-point-selects=4,表示 oltp 脚本中 sql 测试命令,select 操作次数为4,默认值为1。
3.3.2.2 结果展示与分析

初始阶段响应时间基本稳定,吞吐量随着并发数的增加而增加; 随着并发数增加,系统到达“拐点”,吞吐量开始出现下降的趋势,同时响应时间也开始增大;继续增加并发数,系统负载超负荷,从而进入过饱和区,此时响应时间急剧增大,吞吐量急剧下降。在“拐点”之前和刚进入拐点这段区域,此时可以认为系统为“稳定”的,此时并发数、吞吐量、平均响应时间是符合Little's Law公式的。

4.总结

4.1 Little's Law公式系统“稳定”时成立

基于前述的两个实测的例子,对于并发数、吞吐量、响应时间三者的关系,我们可以用上图表示。

  • 刚开始为“线性增长区”,此时响应时间基本稳定,吞吐量随着并发用户数的增加而增加;
  • 当系统的资源利用率饱和时,系统到达“拐点”,随着并发用户数增加,吞吐量开始出现下降的趋势,同时响应时间也开始增大;
  • 继续增加并发用户数,系统负载超负荷,从而进入过饱和区,此时响应时间急剧增大,吞吐量急剧下降。

在“拐点”之前和刚进入拐点这段区域,此时可以认为系统为“稳定”的,此时并发数、吞吐量、平均响应时间是符合Little's Law公式的。

4.2 并发数并不是实际用户数

比如你这样设置jmeter的线程数为80,测出的结果并不是说你的服务在80个用户使用情况下的性能表现,实际场景中可能1000个真实用户产生的压力也没有这里的80个线程(或者叫虚拟用户数)产生的压力大。我倾向于把并发数理解为一种压力的度量,80的并发对服务的压力肯定是大于60的并发对服务的压力的。

4.3 低延迟(响应时间)不一定高吞吐,高延迟(响应时间)也不一定低吞吐

  • 假如一个程序只有1个线程,这个线程每秒可以处理10次事件,那么我们说这个程序处理单次事件的延迟为100ms,吞吐为10次/秒。
  • 假如一个程序有4个线程,每个线程每秒可以处理5次事件,那么我们说这个程序处理单次事件的延迟为200ms,吞吐为20次/秒。
  • 假如一个程序有1个线程,每个线程每秒可以处理20次事件,那么我们说这个程序处理单次事件的延迟为50ms,吞吐为20次/秒。

由Little's Law我们知道,并发数=吞吐量*响应时间,所以延迟和吞吐的关系是受并发数影响的,抛开并发数去找另外两者的关系是没有规律的。

4.4 响应时间要和吞吐量挂钩

性能如果只看吞吐量,不看响应时间是没有意义的。从前面的分析我们知道,随着并发数的逐渐增加,吞吐量有一个先上升再下降的过程,也就是存在同一个吞吐量的值,在不同并发下,会对应不同的响应时间。比如某接口吞吐量为10000TPS,响应时间达到5秒,那这个10000TPS也没什么意义了。

4.5 响应时间、吞吐量和成功率要挂钩

比如在接口测试中,当并发数达到4000时,错误率达到了40%,那么此时的1270.8TPS就没什么意义了。

4.6 又多又快又好

我理解的服务的性能就是又多又快又好的处理请求,“多”就是吞吐量大,“快”就是响应时间短,“好”就是错误率尽量低。

4.7 last but not least

在Little's Law中我们一直用的响应时间是“平均响应时间”,而实际工作中我们通常用响应时间的“分位值”来作为响应时间的统计值来衡量性能的,平均值只是作为一个辅助参考。原因你应该懂得,比如“平均工资”通常没多大参考价值,有可能很多人是被平均的。

5.扩展

Eric Man Wong 于2004年发表的《Method for Estimating the Number of Concurrent Users》论文中介绍了一种对系统并发用户数估算的公式:

这个公式和Little's Law是等价的,具体论述过程参考Eric's并发用户数估算与Little定律的等价性

6.参考

© 著作权归作者所有

zjg23

zjg23

粉丝 22
博文 127
码字总数 45328
作品 0
济南
程序员
私信 提问
加载中

评论(5)

马晓陈
👍
马晓陈
我看你说的线程数为80,可能比实际场景1000个用户同时访问压力还大。那怎么能看出线程数为80具体能承受多少用户?
zjg23
zjg23 博主
你的问题很好,但是对我来说有点大。我说下我的理解:并发80的虚拟用户到底在实际业务中等同于多少真实用户,取决于你的业务,或者说用户在你的业务上的行为模式。对于已上线的系统来说,可以通过日志分析等方法获取用户的行为信息和并发数据,然后跟你的性能测试数据比较;对于未上线的全新系统来说,可以参考类似系统来建立性能测试的模型,分析性能结果,这里的分析的作用更倾向于看当前系统性能是否满足性能指标的要求。
马晓陈
我不是特别明白你说的分析性能结果,这个我理解是假如,我现在有个接口想测试性能,线程数设置为1000,跑着跑着就报错了,我该怎么判断?
zjg23
zjg23 博主
你是想说怎么判断接口的性能瓶颈么?如果是的话,我的理解是这样的:线程数为1000,错误率大于0说明接口已经处于“饱和区”了,通常这时接口的响应时间也比较大,对应的TPS也没太大意义;建议参考3.3.1.2部分,逐渐减小并发数,找到接口的“拐点”,如3.3.1.2部分,可认为“拐点”在并发数为200时出现,在这个压力下(并发数为200)再分析性能瓶颈在哪里。
《纽约时报》系列报道:《依法治国》之三(Rule by Law)

绝望的寻找正义:他的对手是一个国家 作者: JIM YARDLEY 原载2005年11月12日《纽约时报》 巢湖,中国 ---- 他绝望了,再也借不到钱把儿子的官司打下去了。谢裕君走进一家医院。他知道中国有...

阮一峰
2006/04/21
0
0
《纽约时报》系列报道:《依法治国》之一(Rule by Law)

4月19日,2006年度的普利策新闻奖公布了。其中的国际报道奖授予了《纽约时报》的两位记者,他们的作品是一组报道中国司法制度现状、名为《依法治国》(Rule by Law)的系列报道,一共8篇。 ...

阮一峰
2006/04/19
0
0
Get Work Done: Strategies for Getting More Efficient and Finishing

For the second week in a row, I'm tackling reader question Monday a little late. This time, my excuse involves the mini-move my wife and I made over the weekend that I originall......

Erik Dietrich
2017/11/30
0
0
《纽约时报》系列报道:《依法治国》之四(Rule by Law)

一位考验中国法院的法官:她改变了历史 作者:JIM YARDLEY 原载2005年11月28日《纽约时报》 在法院的档案室里,李慧娟法官恰巧遇见一个办事员,后者接到紧急命令,来查找一个关于种子价格的普...

阮一峰
2006/04/22
0
0
八个案件八句话

前一段时间,我转载了《纽约时报》2005年的系列报道《依法治国》,一共8篇。 毕竟是普利策奖的得奖作品,可谓篇篇精彩。这些报道对中国司法制度的认识、对中国社会状况的熟悉,不要说是外国人...

阮一峰
2006/05/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

方法重载和重写是什么?有什么区别?

重写:在子类中将父类的成员方法的名称保留,重新编写成员方法的实现内容,更改方法的访问权限,修改返回类型的为父类返回类型的子类。 一些规则: 重写发生在子类继承父类 参数列表必须完全...

ConstXiong
8分钟前
2
0
Spring-Framework 目录

ls spring-orm/src/main/java/org/springframework/orm/hibernate5/ ObjectRetrievalFailureException.java jpa/ ......

MtrS
27分钟前
3
0
大学慕课

Visual C,Turbo C,Dev C的关系 不管是 Visual C、Turbo C 还是 Dev C,本质都是C语言,不存在高下之分。 三种叫法不同是因为 C 语言在三种不同的开发环境中拥有一些不同的开发习惯的区别。...

电子197徐泽彬
45分钟前
3
0
GC偏方 强行fullgc

转自 https://www.jianshu.com/p/be5389ca93f7 FullGC这么恐怖,有办法缓解么,或者说尽量避免它在白天,甚至业务高峰期出现?有!笔者给你分享一个歪门邪道,不记得是多少年前,在哪里道听途...

os_m
49分钟前
4
0
源码分析Mybatis MappedStatement的创建流程

上文源码分析Mybatis MapperProxy创建流程重点阐述 MapperProxy 的创建流程,但并没有介绍 *.Mapper.java(UserMapper.java) 是如何与 *Mapper.xml 文件中的 SQL 语句是如何建立关联的。本文将...

中间件兴趣圈
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部