写点什么

跟我一起认识 Little’s Law

  • 2019-10-28
  • 本文字数:3899 字

    阅读完需:约 13 分钟

跟我一起认识Little’s Law

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 暴露一个接口


接口本身会根据参数值休眠一段时间,这样客户端的压测工具就可以控制接口的响应时间了。


@RestControllerpublic 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 1000dosysbench --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.txtdone
## 清理数据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.参考


2019-10-28 13:503332

评论

发布
暂无评论
发现更多内容

被MySQL慢日志查询搞废了?3分钟教你快速定位慢查询问题!

观测云

云计算

透过 3.0 Preview 看 Dubbo 的云原生变革

阿里巴巴云原生

容器 运维 云原生 dubbo 应用服务中间件

我在阿里实习做开源

阿里巴巴云原生

阿里巴巴 云原生 dubbo 个人提升 中间件

报名倒计时 | 有道技术沙龙,聊聊明星语音背后的故事

有道技术团队

活动

力扣(LeetCode)刷题,简单题(第13期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

2021最新分享三面百度提前批(Java开发岗)面经 已拿Offer

比伯

Java 编程 架构 面试 程序人生

从解决Github TimeOut到经典面试题:从输入URL到浏览器显示页面发生了什么?

秦怀杂货店

GitHub TCP 网络 HTTP DNS

百度直播消息服务架构实践

百度Geek说

手机 直播 移动端

阿里面试官:Android开发真等于废人?已拿offer附真题解析

欢喜学安卓

android 程序员 面试 移动开发

程序员去大公司面试,小程序FMP优化实录,已拿offer入职

欢喜学安卓

android 程序员 面试 移动开发

实现跨生态互联,区块链赋能智能家居新体验

旺链科技

区块链应用 智能家居

Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题

阿里巴巴云原生

Java 微服务 云原生 seata Go 语言

行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug

蚂蚁集团移动开发平台 mPaaS

android webview mPaaS 离线包 UC内核

困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

不脱发的程序猿

28天写作 硬件设计 嵌入式软件 单片机 3月日更

单账户实时记账能力达2万笔每秒 蚂蚁启用新一代高性能记账引擎

DT极客

LeetCode题解:92. 反转链表 II,迭代,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

字节抖音iOS客户端实习 123hr面 面经

iOSer

ios 字节跳动 面试 抖音

为什么python中程序的结果会一直输出,需要怎么解决

Emotion

这个GItHub上的Java项目开源了,2021最全的Java架构面试复习指南

Java 程序员 面试

可能是绝唱!阿里资深工程师深度解读Netty底层核心源码

Java架构追梦

Java 源码 架构 面试 Netty

OpenKruise 如何实现 K8s 社区首个规模化镜像预热能力

阿里巴巴云原生

Serverless 容器 云原生 k8s 调度

python编译器中出现了绿色波浪线,光标放上去出现的提示是什么意思?

Emotion

为了跳槽刷完1000道Java面试真题,没想到老板直接给我升职了

Java 程序员 架构 面试

定义结构体访问结构成员的三种方法

Emotion

实习就参与“服务过亿用户的项目”,是什么体验?

阿里巴巴云原生

开发者 云原生 调度 应用服务中间件 Go 语言

活动 | Apache Pulsar Meetup 欢迎报名

有道技术团队

活动

Go Storage存储包封装

非晓为骁

storage Go 语言

Flink 执行引擎:流批一体的融合之路

Apache Flink

flink

C 语言性能优化:循环条件i<=n与i!=0的性能差异

1

有道技术岗大揭秘!这么幸福的生活,真的是熬夜掉发Top1的职业吗?

有道技术团队

招聘

一周信创舆情观察(3.15~3.21)

统小信uos

跟我一起认识Little’s Law_文化 & 方法_xinnong_InfoQ精选文章