每日一博 | 跟我一起认识 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 准备过程介绍
- 基于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!"; } }
- 通过jmeter设置不同的并发数对上面的接口进行压测
3.3.1.2 结果展示与分析
初始阶段响应时间基本稳定,吞吐量随着并发数的增加而增加; 随着并发数增加,系统到达“拐点”,吞吐量开始出现下降的趋势,同时响应时间也开始增大;继续增加并发数,系统负载超负荷,从而进入过饱和区,此时响应时间急剧增大,吞吐量急剧下降。在“拐点”之前和刚进入拐点这段区域,此时可以认为系统为“稳定”的,此时并发数、吞吐量、平均响应时间是符合Little's Law公式的。
3.3.2 mysql服务的实例
3.3.2.1 准备过程介绍
- 准备一个腾讯云mysql服务(5.6版本,配置为2核4G)和一台云服务器(腾讯云内网测试)
- 用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.参考
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
PJON 12.0 发布,Arduino 通讯总线方案
PJON 12.0已经发布,内容如下: 新规范: PJDLv4.0 包含响应初始化器,以避免多主模式下的漏洞 现在,pjdlr v3.0 能够使媒体在交换之间保持忙状态,并包括响应初始化程序,以避免多主模式下的漏洞 Changelog: Osprey 存储库中已经删除了动态寻址功能 SoftwareBitBang 现在实现了 PJDLv4.0,如果在多主模式中使用,它会更安全 OverSampling现在实现了 pjdlr v3.0,它更安全,并且支持多主模式,而不需要对所有设备进行公共配置 LocalFile 策略使用硬盘上的文件,允许多个进程在同一台机器上通信,可以用于进程间通信、仿真、测试应用程序和实时操作系统上的网络 ThrouLoRa 不再支持同步确认和重传 Interactive 路由器同步确认传输 增加对 Android 的支持 增加了对 STM 32-Duino 安装的支持 Linux 口函数声明的可选分离 PJON 数据缓冲区类型为 char PJON 发送函数 payload 参数现在类型为 Const void* SendString 和 ReceiveStrin...
- 下一篇
高手问答 —— K8S 从懵圈到熟练,资深架构师在线解答
近几年,Kubernetes 已从一个新生事物发展为一个影响全球 IT 技术的基础设施平台,也推动了云原生应用、微服务架构、ServiceMesh 等热门技术的普及和落地。现在,Kubernetes 已经成为明星项目,成为开源历史上发展速度超快的项目之一。 与此同时,关注 Kubernetes 的读者量一直在增加,读者抛出 Kubernetes 相关问题的频率也很高,因此本期高手问答以期为大家提供一个与权威专家在线讨论的渠道。 OSCHINA 本期高手问答(10 月 28 日 - 11月 03日)特邀请到《Kubernetes 权威指南》主要作者吴治辉@zzzxgswd 在线答疑,解答各位读者或者 Kubernetes 爱好者的各种技术疑问。 嘉宾简介 吴治辉,HPE 资深架构师,拥有近 20 年软件研发经验,专注于电信软件和云计算方面的软件研发,拥有丰富的大型项目架构设计经验,是业界少有的具备很强 Coding 能力的资深架构师,也是《架构解密:从分布式到微服务》《Kubernetes 权威指南:企业级容器云实战》等书作者。 为了鼓励踊跃提问,@博文视点 会在问答结束后从提问者中抽取...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果