做「容量预估」可没有true和false

重峦叠嶂
• 阅读 1338
如果第二次看到我的文章,欢迎「文末」扫码订阅我个人的公众号(跨界架构师)哟~ 

每周五11:45 按时送达。当然了,也会时不时加个餐~

我的第「85」篇原创敬上

随着20年来互联网的蓬勃发展,一个软件系统所要面对的访问压力上限被逐渐提高。

虽然如此,但是那些体量达到亿级或者是千万级的产品也只是少数公司的专属。对于整个行业里百万+的程序员群体来说,估计也就只有10%人有机会接触到这些“大系统”。

所以,一提到容量预估,大家可能第一时间想到的是,这是大公司的事,我们这种小系统不用考虑这个问题。

这说法其实不太对。现在这个时代,营销活动满天飞,初创企业更是在绞尽脑汁想着“一炮而红”,所以哪怕不是那些千万级以上的系统也需要考虑容量预估的问题。


对大型系统来说,容量预估是刚需,关乎到系统能不能扛住,或者投入的资源会不会过度浪费,毕竟1%都是好多钱呐。

而对小系统来说,多花个百八十万,多冗余一些资源也没问题。

虽然如此,但是Z哥觉得,能不能做好「容量预估」,背后体现的是一个人解决没有标准答案的问题的能力。

这是很多程序员都缺乏的一个能力。

所以,不管你当前是在大公司还是小公司,只要你希望提高你的架构能力,或者未来想有机会把握住在大公司的工作机会,那么这是一个必须要掌握的基本技能。


日积月累的程序员思维让大家都习惯了事事都有0和1,true和false。然而真正复杂的问题是那些没有标准答案的问题,在这些问题中,没有对和错,只有合适和不合适。

而且,如今大家的生活越来越“在线化”。如果一个系统的负载能力,我们一直不去关注它。那么,当好不容易熬到的“风口”真的吹来的时候,能把握住吗?还是眼睁睁的错过它们。


我想,大多数人对容量预估还是有一些概念的。通过数据推算出对系统承载能力的要求,并且实施满足要求的程序部署。

比如,下个月要做一轮大促。系统要达到一个什么状态才能顺利支撑大促的开展?

大家脑子里至少都会有这样的一个公式:

流量 / 单机性能 = X台机器

但我认为这个理解还可以再深入一些。Z哥的理解是:容量预估的本质是为了获得技术投入与业务发展之间的合理值,追求的是无限接近于“刚刚好”的状态

要达到“刚刚好”的状态,必然意味着不能凭借拍脑袋办事,而要考虑到尽可能多的维度,采集更多维度的数据作为参考。

因为实际的情况,肯定不是像上面公式一样简单的线性关系。而是类似下面这样的对数曲线关系。

做「容量预估」可没有true和false

那么具体该怎么做容量规划呢?

在这之前我们先得搞清楚几个概念。

首先是指标。我们主要关注以下几个指标。

  • UV(Unique Vistor):一段时间内的访客数,同一访客在该时段内的多次访问只计一次。
  • PV(page view):一段时间内的页面浏览次数,同一用户多次打开同一页面也继续累计。
  • 响应时间/系统延迟(Latency):系统处理一个请求/任务的延迟(请求处理时间+数据传输时间)
  • 吞吐量(Throughput):一个单位时间内可以处理的请求数。也就是该单位时间内发起的请求总数/平均响应时间,请求数可以是一次pv、也可以是一次rpc调用等等。
  • TPS(Transaction Per Second):可以理解为,单位时间是“秒”的「吞吐量」。

其次,我们要对会产生性能开销的地方要有认识。这主要分为3个部分。

  • 硬件/操作系统层面的开销。如磁盘I/O、网络I/O,CPU的多线程切换等等。
  • 进程运行的开销。如代码逻辑啊、锁啊等等。
  • 多个进程之间的通信开销。rpc框架、数据库访问框架、redis/memcached访问SDK、MQ访问SDK等等。


然后就可以开始做「容量规划」了。

我一般是按以下5个步骤进行。

第一步,搞清楚业务的状况,先得到业务上的指标

技术工作最怕隔着“部门墙”,蒙着头做,沉浸在自己的“小世界”里。

所以,不管通过什么途径,得先对一些业务指标有客观的认识,PV、UV的数据是必须的。可以找业务方聊,也可以借助百度指数、微信指数等更宏观数据来进行参考和修正。


第二步,围绕这个业务指标,对所涉及的相关技术接口制定性能指标

其实就是要得到一个业务流量与技术的性能指标之间的一个比例关系。

比如,访问一次A页面,涉及到调用a接口2次,b接口1次,c接口3次这样。

做这事儿有一个简单的办法。

先在系统中的每个api接口做好数据采集,目的是为了后续能获得两个数据,响应时间和次数等等。

然后借助一些压测工具,比如loadrunner之类,对当前的业务场景做一轮的全链路压测。模拟的用户数不用很大,因为我们只是为了得到一个比例。

这样,在压测结束后,你就可以将loadrunner中所记录的发起请求的数量,对比api接口采集到的数据,就能得到每个接口与业务流量之间的关系。顺带也能看到在低压力下的错误率、平均响应时间、tp95、tp99等等的情况。


第三步,借助过去的经验对标准进行校准

真实的生产环境是错综复杂的,因为一个api接口往往会被众多地方调用。

那么做校准就是为了让我们的预估更接近真实的生产环境一些。

如果有过去成功支撑的案例数据就最好了。用当时的UV、PV数据、接口与业务量比例对比当前的业务预估的UV、PV、接口与业务量比例进行同比例的调整。

可以得出下面这样的公式:

应满足的TPS = 成功时的TPS  (当前预估业务流量 / 成功时业务流量)  (当前业务接口比例/成功时业务接口比例)。

没有成功案例的话,可以通过分析数据库中任何带有“时间”字段的数据,找到其中已知可承受的最高并发值,以及对应的时间点。(简单粗暴的方式可以groupby“时间字段”)

再反向去找对应这个时间节点的PV、UV。

然后再与这次的业务指标预估进行对比,看下差异比例。

应满足的TPS = 历史最高TPS(不管抗没扛住)  (当前预估业务流量 /  历史最高TPS时业务流量)  (当前业务接口比例 / 历史最高TPS(不管抗没扛住) 时业务接口比例)。


当然了,最坏的情况就是,过去对数据不够重视,完全没有数据可以参考。

那就马上做数据埋点,分析当前系统的运行时数据,得到当前某个时段的业务流量以及对应的TPS。这应该不是难事。

这样也可以推算出一个「应满足的TPS」。

应满足的TPS = 该TPS  (当前预估业务流量 / 某时段业务流量)  当前业务接口比例


最后,得到了一个这样的每个接口的性能指标。

做「容量预估」可没有true和false

接下来要做的第四步,就是确定到底要部署多少服务器,多少程序才能满足这些标准

正如前面所说,得到这个结果不是简单的做除法,因为这不是一个线性关系。

所以,我们需要动手进行验证。

你可以通过分别压测1台、2台、3台、……,不同数量的服务器,得到下面这样的一个曲线。(当然,性能优化工作也是在这个期间进行)

做「容量预估」可没有true和false

如此一来,你就可以根据这个衰减的趋势,得到一个理论上能支撑业务所需的程序数量和服务器数量。


当然了,理论毕竟是理论,为了保险起见,还是要预留一定的弹性空间,这就是第五步。免得算的太“扣”,没给自己留后路。

该“弹”多少合适呢?

Z哥的建议是,同比分析一下过去一段时间内的业务量情况,观察每个波峰的同比增长大小,将同比增长的最大值作为弹性部分的比例。

做「容量预估」可没有true和false

弹性部分可以不用100%提前启用,但要随着备着。

到这里你就完成了整个容量预估工作的5个步骤。

其实最终得到的数据还有一些其他作用。比如,设置程序的线程数量、配置web容器(nginx、tomcat、iis)等等。

因为大多数情况下,参数都会设置的过大,甚至有不少小伙伴会一拍脑袋的设置成max值。

其实这样的风险是非常大的,不但会有资源耗尽的风险,在分布式系统中还会产生级联反应,影响上游系统。


好了,我们来总结一下。

这次呢,Z哥先和你聊了一下容量预估的意义。

然后,分享了我自己做容量预估的思路,通过5步法来实现。

  1. 得到业务的流量指标
  2. 通过调用比例获得相关接口的性能指标
  3. 根据历史数据进行校准
  4. 根据衰减曲线得到预估的节点数量
  5. 预留一些弹性空间


希望对你有所帮助。


推荐阅读:


作者:Zachary

出处:https://zacharyfan.com/archives/835.html

如果你喜欢这篇文章,可以点一下文末的「」。

这样可以给我一点反馈。: )

谢谢你的举手之劳。

▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描下方的二维码~。

如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。

如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。

定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些深度思考

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
DevOpSec DevOpSec
4年前
Linux主机安全配置
1.安全配置规范1.身份鉴别1.账号检查<tableborder"1"cellspacing"0"style"width:426.1pt;"<tbody<tr<tdstyle"width:113.4pt;"<pstyle"marginleft:0pt;"<strong<strong安全配置编号
Wesley13 Wesley13
3年前
Java面试
<divclass"htmledit\_views"id"content\_views"<pid"maintoc"<strong目录</strong</p<pid"Java%E5%9F%BA%E7%A1%80%EF%BC%9Atoc"style"marginleft:40px;"<ahref"Java%E5%
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
8个月打磨,一份送给程序员的「分布式系统」合集
_如果第二次看到我的文章,欢迎「文末」扫码订阅我个人的公众号(跨界架构师)哟~__每周五早8点按时送达到公众号。当然了,也会时不时加个餐~_是的,这份礼物最佳受众是程序员。但是,如果你不是程序员,相信这些能使你更懂程序员,能更好的与他们交流。有些小伙伴们应该知道了,之前的《分布式系统关注点——360°的全方位监控
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
Java 9版本之后Base64Encoder和Base64Decoder无法继续使用解决办法
<divclass"htmledit\_views"id"content\_views"<p在项目开发过程中,因为重装系统,安装了Java10版本,发现sun.misc.Base64Encoder和sun.misc.Base64Decoder无法使用。</p<p<br</p<p<strong原因:</strong</p<p查看
Stella981 Stella981
3年前
Jsoup清除HTML标签(非白名单)
Jsoup默认提供五种白名单: 1):none()    该API会清除所有HTML标签,仅保留文本节点。  2):simpleText()    该API仅会保留b,em,i,strong,u标签,除此之外的所有HTML标签都会被清除。  3):basic()    该API会保留a
Easter79 Easter79
3年前
Tomcat安装、配置、优化及负载均衡详解
<divid"cnblogs\_post\_body"class"blogpostbody"<p<strong原文地址:https://www.cnblogs.com/rocomp/p/4802396.html</strong</p<p<strong一、常见JavaWeb服务器</strong</p<div<strong&
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(