转载请标注出处
背景
当运营需要进行一次拉新投放,或者准备做一场秒杀活动时,都有可能会拉高系统的并发,从而对系统的可用性发起挑战;这时就有可能会被问到这些问题:当前的机器能扛住吗,如果需要扩容,需要扩容多少台机器呢?
如果我们能对流量的并发情况提前了解到,并扩容系统以支持到预设的并发量,就能从容许多。
在本文中,我们假设运营要做一个日均 100w 新用户,持续 10 天的拉新投放,去估算系统需要面对的高峰 QPS 大概是多少(只算业务接口的 QPS,不计算存储组件的 QPS )。
指标含义
定义
QPS
Query Per Second,每秒处理的请求个数,等同于 RPS(Requests Per Second)。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> Q P S = 总请求数(不区分该接口是读还是写) / 时间段(以秒为单位) QPS = 总请求数(不区分该接口是读还是写) / 时间段(以秒为单位) </math>QPS=总请求数(不区分该接口是读还是写)/时间段(以秒为单位)
QPS 定义是没有一个明确的标准的,有的说是 "查询数量/秒",有的说是 "接口数量/秒(不区分读写)";在我看来,这两个其实都能接受,重要的是要能说明清楚这个指标的含义到底是什么,让别人能理解到就可以了。
这里我们把 QPS 定义为 "接口数量/秒(不区分读写)",不区分接口是写入还是查询。
TPS
Transactions Per Second,每秒处理的事务数,这里的 "事务" 是自定义的,定义成什么就是什么含义。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> Q P S = 总事务数(自定义的事务) / 时间段(以秒为单位) QPS = 总事务数(自定义的事务) / 时间段(以秒为单位) </math>QPS=总事务数(自定义的事务)/时间段(以秒为单位)
QPS vs TPS
因为事务是自定义的,所以 QPS 与 TPS 的关系也是会变化的。
如果一个事务是由多个接口请求完成的,那么 1 TPS = n * QPS,例如一些功能中,可能有 UI 端多次主动轮询后台查找最新数据的情况,
此时若功能定义为一个事务(无论最终是成功还是失败),则单次该事务就会对应多个接口请求。
如果一个接口请求中包含多个事务,那么 1 QPS = n * TPS,例如一般的业务增加接口中,会有查询 DB,然后再写入的逻辑,若此时事务定义为 "和 DB 交互",每交互一次就算完成一次事务,则单次接口请求会对应多个事务。
RT(response time)
Response Time,接口响应时间,单位毫秒。
执行一个请求从开始到最后收到响应数据所花费的总体时间,即从客户端发起请求到收到服务器响应结果的时间。
建议是 TP95 或以上。响应时间不同业务特性的具体要求是不同的,一般读不超过 200ms,写不超过 500ms。
QPS 细分
目前的业务系统一般都是计算和存储分离的,计算组件和存储组件都会使用不同的组件,所以主要分为 "业务接口的 QPS"、"数据组件的
QPS" 两种,他们之间的数值可能不是相等的。
这里讨论的主要是业务系统,非大数据系统,实时计算的大数据部分和业务系统是不一样的。
业务接口的 QPS
接口级别的 QPS,受影响最大的有计算节点的 CPU、MEM、IO 等。
CPU 密集型的应用,计算节点的 CPU 使用率就会因为接口 QPS 的升高而快速增长。
IO 密集型的,比如写日志的计算节点,则 IO 就可能会受到影响。
数据组件的 QPS
内存型的存储组件,如 Redis 就会影响多一些。
综合型存储组件,如 MySQL,则 CPU、MEM 等都可能会受到影响。
估算业务接口的 QPS
说明
估算的过程主要分为两步:
- 估算人数
- 估算具体的 QPS
在这个估算的过程中,如果有历史数据可以参考,比如系统已经上线了一段时间,或者前面刚做过一场类似的活动,或者有其他项目类似场景的业务,则可以参考一下其数据表现,不同类型的业务有不同的特性,有参考数据,可以让估算更准确一些。
假设其他的或者以前的历史数据这次的情况不一样,预估的流量少了,可以参见下文的处理措施。
估算人数
首先看目标功能会有多少人数参与,比如电商中的支付功能,有 100w 的新用户,那大概会有多少人付款呢,不太可能是 100w 人都会付款吧。这里假设目标功能就是会有 100w 访问,然后继续进行计算。
确认业务的流量形态
首先要确定下业务的流量形态,流量是平缓分布的,还是高低峰明显的情况。
平均数的倍数
如果流量分布是平缓的,有一种 "平均数的倍数" 的计算方式,形式是先算出目前时间段内的平均人数,然后在取这个平均值的若干倍作为估算值。这种方式适合流量形态大体是均衡分布的业务。如果业务的流量形态不是均匀的,而是高低峰明显,则不适合这种方式。
过程如下:
第一步,算出平均值
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 平均值 = 一天的总人数 / 4 w 秒 平均值 = 一天的总人数 / 4w 秒 </math>平均值=一天的总人数/4w秒
4w 秒:一天共24小时60分钟60秒=8w秒,一般假设所有请求都发生在白天,所以一般来说一天只按照4w秒评估。
第二步,然后再取平均值的若干倍 (一般是 3-5倍)
比例计算
一天总共有 100w 的人数,那高峰期会有多少呢?这个其实也没有一个固定的标准,不同的业务场景有不同的算法。业内常用的有 "八二" 、"七三" 算法等。
比如 "秒杀" 场景,可能就不太适合 "八二" 的方式了,它的高峰大都在开始的几分钟内。
八二 或者叫 二八,就是假设 80% 的人会在 20% 的时间请求接口,然后算出这个 20% 时间内的平均 QPS 来当作高峰 QPS。
七三 或者叫 三七,是同理的。
这里使用八二原则来计算,则高峰时人数则为:(100w 人 * 80%)/ (24h * 20%)= 80w 人 / 4.8h = 16.7w/h = 46.3 人/s
估算 QPS
得知高峰期的人数后,还需要估算一下一个人平均会同时请求几个接口。例如,有些场景一个页面打开,需要请求 6 个以上的接口,这些接口的请求时间都比较接近,可以认为他们是并发请求的。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 高峰 Q P S = 人数 ∗ 平均每人接口数量 高峰 QPS = 人数 * 平均每人接口数量 </math>高峰QPS=人数∗平均每人接口数量
加上当前的量级
估算出来的量级需要加上当前系统里正在运行的量级,其和就是拉新期间系统会面临的全部并发量了。
估算错误了怎么办
要拉新 100w,其实也是运营同学的预估,也不一定那么准确。一般情况下技术同学是不太清楚具体的投放标准和费用的,所以大部分情况下还是要相信运营的预估量级;如果感觉不合适可以和其沟通来确认一下相对更合理的预估范围。
估算多了
这种情况也是挺常见的,想要拉新 100w,结果是有 70w 的新增,运营后边可能要调整投放策略;但对系统来说是能扛住的,只是多扩容了一些资源,是能接受的;毕竟这几天扩容的机器费用一般都不会太多,且可以活动结束后进行缩容,相比系统宕机,业务受损来说,根本不算什么。
估算少了
拉新情况出乎意料的好,导致流量远超我们的估算,此时的应用主要有以下几种:
1. 丢弃掉无法承接的流量
使用 "限流" 功能,把系统无法处理的流量都抛弃掉,当然可以给用户一个比较友好的提醒,从而让用户过一会儿再进行重试,尽量避免用户流失。
这个方式是有损业务的,毕竟运营用钱买来的用户,可能因为系统的不能承受导致有可能会流失;所以尽量避免这种情况出现。
2. 腾出空间
搭配 "降级、熔断" 功能,尽可能的容纳更多的主要流量。
降级可以把一些非主要的功能关闭掉,给主要功能提供更多的机器资源。
熔断可以让一些响应经常出错的接口服务等,更快的给出结果,从而让主要功能的接口更快的返回,降低系统整体的并发量;流量大的时候,接口响应越慢,系统内同时要处理的接口数量就会更多。
3. 临时扩容
还可以看下 "计算服务器、数据存储服务器" 可以进行临时扩容。
计算服务器因为是无状态的,一般都是可以快速进行扩容,不太会是卡点。
数据服务器若不是分布式的,临时扩容的操作空间并不大,即使做了分库分表,但因为此时流量较大,也不能很方便的再次进行一次分库分表;此时可以看是否可以做冷热数据的分离,降低数据表的容量,从而容纳更多的数据写入。
但这个要看业务的增速情况,如果增速很快,就需要配合限流措施先把流量控制住,然后再进行临时的扩容,扩容完成后再改大限流的阈值。可以搭配告警,避免一直需要人工的盯着监控面板。
而在控制流量的期间,也是是业务受损的,所以最好就多估算一些,多加一些机器,简单便捷。
4. 异步处理
当前的数据是否可以先缓存下来,稍后再进行处理;如果可以的话,可以临时上个代码,把数据存储到其它的地方。
5. 多估算一些
为了避免出现业务受损的情况,可以把估算出来的数值的 2 - 3 倍,当作目标高峰 QPS 来进行处理。
压测
得到了高峰 QPS 后,下一步就是要把当前机器是否能够承载,以及若需要扩容,需要扩容多少的情况计算出来了,这个步骤大都是通过压测得到的,不同的代码形式,编写逻辑,不同规格的机器,带宽等,都可能会导致支撑同样的 QPS 需要的机器是不同的,所以进行实际压测得到的结果是最接近目前 QPS 的。
脚本
需要尽量的模拟出用户的真实行为,越接近则压测的结果就越准确。
短板
根据木桶效应,找到当前系统中最短的一块板,最短的部分就是系统整体的最高 QPS。
当 QPS 上不去,或者先增加,然后不断下降的时候,即出现性能拐点的时候,往往就是出现了短板瓶颈了,需要去排查系统,找到这个短板。
一般服务都有性能临界点。当超过临界点时,吞吐量非线性下降,响应时间指数级增加,成功率降低。
一旦达到性能拐点,有可能会出现雪崩现象,造成极其严重的事故。 观察超过性能拐点后,系统是否会出现假死、崩溃等高风险事件。
系统稳定性
保持最高吞吐量(目标响应时间下的最高吞吐量),持续运行 7*24 小时。然后收集 CPU,内存,硬盘/网络 IO,等指标,查看系统是否稳定,比如,CPU 是平稳的,内存使用也是平稳的。那么这个值就是系统的性能。