容量规划是系统运维和架构设计中非常重要的一环,但是也是很多团队容易忽略,或者做不好的一环容量规划做得好能保证系统稳定运行合理利用资源节省成本容量规划做得不好要么资源不足系统扛不住流量出故障影响用户体验和业务要么资源过剩浪费钱增加成本降低资源利用率。

最近我们团队在做系统容量规划踩了不少坑也积累了一些实战经验本文总结了容量规划中常见的坑以及我们的实战经验和,方法包括如何评估容量如何监控容量如何做容量测试如何应对流量突增等等希望能帮大家做好容量规划避免踩坑。

一、什么是容量规划

先简单说说什么是容量规划容量规划(Capacity Planning)就是根据业务的需求和流量的预测合理地规划系统需要的资源(比如服务器数量CPU内存带宽数据库连接数等等)保证系统在各种流量情况下都能稳定运行,同时尽量提高资源利用率降低成本。

容量规划不是一次性的工作而是一个持续的过程需要不断地监控分析调整,因为业务在发展流量在变化系统在迭代,所以容量也需要不断地调整和优化不能做一次就一劳永逸。

容量规划的目标是在成本和稳定性之间,找到一个平衡既不能为了省钱把容量规划得太小导致系统扛不住流量出故障也不能为了稳定把容量规划得太大导致资源浪费成本过高这个平衡需要根据业务的特点和对稳定性的要求来把握。

二、踩过的坑

先说说我们在容量规划中踩过的坑这些坑有些让我们交了不少学费希望大家能引以为戒避免再踩。

坑1:只看平均流量不看峰值流量

这是我们最早踩的一个坑一开始做容量规划的时候,我们只看平均流量,比如平均QPS是多少平均响应时间是多少,然后根据平均流量来规划容量结果一到流量峰值(比如大促活动,或者晚上高峰时段)系统就扛不住了响应变慢甚至超时报错出故障。

后来我们才意识到容量规划不能只看平均流量更要看峰值流量,因为系统能不能扛住关键看峰值的时候,能不能扛住平均流量再低也没用,只要峰值扛不住就会出故障影响用户体验,所以容量规划应该以峰值流量为基准来规划而不是平均流量。

而且峰值流量也分很多种有日常峰值(比如每天晚上的高峰)有活动峰值(比如大促活动的流量)有突发峰值(比如某个热点事件导致的流量突增)这些都要考虑到不能只看一种峰值我们后来是按日常峰值来规划基础容量按活动峰值来规划弹性扩容的容量按突发峰值来做限流降级的预案这样比较合理。

坑2:只看CPU和内存不看其他资源

第二个坑是只看CPU和内存的使用率来判断容量觉得CPU和内存没满就,还有容量结果有一次我们的系统CPU和内存使用率都不高(大概50%左右)但是系统还是出问题了响应变慢请求超时排查了很久才发现是数据库连接池满了应用的线程都在等数据库连接导致请求堆积响应变慢。

后来我们才意识到容量规划不能只看CPU和内存还要看其他资源,比如数据库连接数线程池大小文件描述符数量网络带宽磁盘IO等等这些资源都可能成为瓶颈,即使CPU和内存,还有余量其他资源满了系统也会出问题。

所以我们后来做容量规划的时候,会全面地监控和评估各种资源的使用率包括CPU内存磁盘IO网络带宽数据库连接数线程池队列长度等等找到真正的瓶颈资源,然后针对性地规划容量而不是只看CPU和内存。

坑3:不做容量测试凭感觉规划

第三个坑是不做容量测试凭感觉来规划容量一开始我们做容量规划都是凭经验和感觉觉得大概需要多少台服务器就申请多少台结果要么申请少了不够用临时加机器手忙脚乱要么申请多了浪费钱资源利用率很低。

后来我们才开始做容量测试用压测工具(比如JMeterwrk等等)对系统进行压力测试测出系统的极限QPS和响应时间,然后根据压测结果来规划容量这样就比较准确了不再凭感觉了。

而且容量测试也能帮我们发现系统的性能瓶颈和问题在压测的过程中我们发现了很多性能问题,比如慢SQL不合理的代码配置不当等等优化了这些问题之后,系统的性能提升了很多需要的服务器数量也减少了节省了成本,所以容量测试,不仅能帮我们准确规划容量还能帮我们发现和解决性能问题非常有价值。

坑4:不考虑流量增长容量规划一成不变

第四个坑是不考虑流量增长容量规划做一次就一成不变一开始我们做了一次容量规划之后,就没怎么管了觉得已经规划好了结果过了几个月业务发展了流量增长了原来的容量不够用了系统开始出问题响应变慢甚至故障我们才赶紧临时加机器扩容手忙脚乱差点出大问题。

后来我们才意识到容量规划是一个持续的过程不是一次性的工作业务在发展流量在增长系统在迭代,所以容量也需要不断地调整和优化我们后来建立了容量规划的定期复盘机制每个月都会回顾一下容量使用情况流量增长情况,然后调整容量规划提前做好扩容准备不再临时抱佛脚。

而且我们还会根据业务的发展计划提前预测流量的增长,比如下个季度有什么大的活动业务量预计增长多少,然后提前做好容量准备扩容,或者优化性能确保系统能扛住增长的流量不再被动应对。

坑5:只关注应用服务器不关注依赖服务

第五个坑是只关注应用服务器的容量不关注依赖服务的容量一开始我们做容量规划只看应用服务器的CPU内存QPS等等觉得应用服务器够了就没问题结果有一次大促活动应用服务器,还有余量,但是依赖的数据库和缓存(Redis)扛不住了数据库CPU满了Redis内存满了导致整个系统响应变慢出故障我们排查了很久才发现是依赖服务的容量不够。

后来我们才意识到容量规划不能只看应用服务器还要看所有依赖的服务和组件,比如数据库缓存消息队列第三方服务等等这些依赖服务的容量也很重要,只要有一个依赖服务扛不住整个系统都会出问题这就是木桶效应系统的整体容量取决于最短的那块木板。

所以我们后来做容量规划的时候,会把整个调用链上的所有服务和组件都纳入容量规划的范围全面评估每个环节的容量确保没有短板整个系统的容量都能满足需求不再只看应用服务器。

三、容量规划的方法和步骤

踩了这么多坑之后,我们总结了一套比较完善的容量规划方法和步骤下面分享给大家。

步骤1:明确业务需求和流量特征

容量规划的第一步是明确业务需求和流量特征要搞清楚系统的业务场景是什么用户的使用模式是什么流量的特征是什么,比如:

  • 系统是做什么的(电商社交工具等等)
  • 主要的用户群体是谁他们的使用习惯是什么
  • 流量的时间分布是什么(有没有明显的高峰时段高峰是几点到几点)
  • 流量的增长趋势是什么(每月增长多少预计未来半年增长多少)
  • 有没有周期性的活动,或者大促(比如双十一618等等流量会增长多少)
  • 有没有可能的突发流量(比如热点事件营销活动等等)

明确了这些业务需求和流量特征之后,才能有针对性地做容量规划,否则就是无的放矢规划出来的容量肯定不准。

步骤2:全面监控系统资源和性能指标

第二步是全面监控系统的资源和性能指标这是容量规划的基础,只有有了准确的监控数据才能做出准确的容量规划我们监控的指标包括:

  • 系统资源指标:CPU使用率内存使用率磁盘IO(读写速度IOPS)网络带宽(入站出站)文件描述符使用数等等。
  • 应用性能指标:QPS(每秒请求数)TPS(每秒事务数)响应时间(平均P50P95P99)错误率线程池使用率队列长度等等。
  • 依赖服务指标:数据库(CPU内存连接数慢查询数QPS响应时间)缓存(CPU内存命中率QPS响应时间)消息队列(堆积数消费速度生产速度)第三方服务(响应时间错误率QPS)等等。

我们用Prometheus+ Grafana来做监控和可视化把所有指标都收集起来展示在仪表盘上能实时看到系统的运行状态和资源使用情况,而且还能看历史数据分析流量的变化趋势和资源的使用规律为容量规划提供数据支撑。

步骤3:做容量测试测出系统极限

第三步是做容量测试测出系统的极限性能和容量这是容量规划中非常关键的一步不能少我们用压测工具(比如JMeterwrk等等)对系统进行压力测试逐步增加并发数和,QPS观察系统的响应时间错误率资源使用率的变化找到系统的极限QPS和瓶颈所在。

容量测试的时候,要注意以下几点:

  • 测试环境要和生产环境一致:尽量用和生产环境一样的配置来做压测这样测出来的结果才准确有参考价值,如果测试环境和生产环境差太多测出来的结果就不准没用。
  • 要模拟真实的业务场景:压测的请求要模拟真实的业务场景包括各种接口的比例参数等等不能只压一个接口,或者用简单的请求来压,否则测出来的结果和真实情况差很多。
  • 要逐步增加压力找到拐点:不要一下子就加到最大压力要逐步增加并发数和QPS观察系统的变化找到性能拐点也就是响应时间开始急剧上升,或者错误率开始增加的那个点那个点就是系统的极限容量。
  • 要监控所有资源和指标:压测的过程中要全面监控系统的所有资源和性能指标包括应用服务器数据库缓存等等这样才能找到系统的瓶颈在哪里是CPU不够还是内存不够还是数据库扛不住等等,然后针对性地优化。

通过容量测试我们能准确地知道系统的极限QPS是多少瓶颈在哪里,然后根据这些数据来规划容量就比较准确了。

步骤4:根据峰值流量和冗余系数规划容量

第四步是根据峰值流量和冗余系数来规划容量有了容量测试的结果(单台服务器能扛多少QPS)和,峰值流量的数据(系统峰值QPS是多少)就可以计算需要多少台服务器了。

计算公式大概是这样的: 需要的服务器数量 = 峰值QPS × 冗余系数 / 单台服务器极限QPS

这里有几个关键点:

  • 用峰值QPS不是平均QPS:前面说过了容量规划要以峰值流量为基准,所以用峰值QPS来计算而不是平均QPS。
  • 要乘冗余系数:冗余系数是为了应对突发流量和服务器故障预留的余量一般建议冗余系数取1.5-2也就是规划的容量是峰值流量的1.5-2倍这样,即使有突发流量,或者某台服务器故障了系统也能扛住不会出问题冗余系数具体取多少要根据业务对稳定性的要求和成本的考虑来决定对稳定性要求高的业务冗余系数可以取大一些对成本敏感的业务可以取小一些。
  • 要考虑依赖服务的容量:除了应用服务器还要考虑数据库缓存等依赖服务的容量确保整个调用链的容量都能满足需求没有短板。

举个例子假设系统峰值QPS是10000单台服务器极限QPS是2000冗余系数取1.5那么需要的服务器数量 = 10000 × 1.5 / 2000 = 7.5向上取整就是8台服务器这样规划出来的容量就比较合理了。

步骤5:建立弹性伸缩机制应对流量变化

第五步是建立弹性伸缩机制应对流量的变化,即使容量规划得再准确也不可能完全预测流量的变化总会有突发流量,或者流量增长超出预期的情况,所以需要建立弹性伸缩机制能根据流量的变化自动扩容,或者缩容这样既能应对流量增长保证系统稳定又能在流量低的时候,缩容节省成本。

我们用Kubernetes(K8s)来做容器编排和弹性伸缩K8s有Horizontal Pod Autoscaler(HPA)功能可以根据CPU使用率,或者自定义指标(比如QPS响应时间)自动调整Pod的数量流量高的时候,自动扩容增加Pod流量低的时候,自动缩容减少Pod非常方便也很智能。

另外对于一些已知的大促活动,或者流量高峰我们也会提前手动扩容预留足够的容量确保活动期间系统稳定活动结束后再缩容恢复正常容量这样结合自动弹性伸缩和手动扩容就能很好地应对各种流量变化了。

步骤6:定期复盘和调整容量规划

第六步是定期复盘和调整容量规划容量规划不是一次性的工作是持续的过程,所以需要定期复盘回顾容量使用情况流量变化情况,然后调整容量规划我们是每个月做一次容量复盘主要看以下几个方面:

  • 这个月的流量情况(峰值QPS平均QPS增长情况)
  • 资源使用情况(CPU内存等等的使用率有没有瓶颈)
  • 容量规划的准确性(之前,规划的容量够不够有没有浪费,或者不足)
  • 下个月的业务计划和流量预测(有没有活动预计增长多少)

根据复盘的结果调整下个月的容量规划该扩容的扩容该缩容的缩容该优化的优化确保容量始终能满足业务需求,同时尽量提高资源利用率降低成本。

四、应对流量突增的预案

除了日常的容量规划我们还制定了应对流量突增的预案确保在突发大流量的情况下系统也能稳定运行不会崩溃主要有以下几个措施。

1. 限流

限流是应对流量突增的最基本的措施当流量超过系统的承载能力时通过限流拒绝多余的请求保证系统不被打垮我们用Sentinel来做限流给每个接口都设置了合理的QPS阈值超过阈值的请求直接拒绝,或者排队保证系统的稳定。

限流的阈值要根据容量测试的结果来设置一般设置为系统极限QPS的80%左右留一些余量不要设置得太极限,否则容易出问题。

2. 降级

降级是在系统压力大的时候,关闭一些非核心功能,或者返回兜底数据保证核心功能可用,比如电商系统大促的时候,可以暂时关闭商品推荐用户评价等非核心功能保证下单支付等核心功能正常运行我们也给系统做了降级开关能随时开启,或者关闭某些功能应对大流量场景。

降级的策略要提前规划好哪些功能是核心的必须保证哪些功能是非核心的可以降级降级的时候,返回什么兜底数据等等都要提前想清楚做好准备不能临时抱佛脚。

3. 熔断

熔断是当某个依赖服务出问题的时候,自动熔断对该服务的调用直接返回降级结果避免故障蔓延导致整个系统崩溃我们用Sentinel和Resilience4j来做熔断给每个依赖服务的调用都加了熔断配置当某个服务的错误率,或者响应时间超过阈值时自动熔断返回降级结果保护整个系统。

熔断能有效防止雪崩效应一个服务出问题不会影响整个系统其他服务还能正常运行只是,相关功能降级而已大大提升了系统的稳定性。

4. 快速扩容

除了限流降级熔断这些保护措施我们,还有快速扩容的能力当流量突增的时候,能快速增加服务器数量提升系统的承载能力我们用K8s的弹性伸缩能在几分钟内完成扩容非常快速,另外我们也预留了一些备用资源紧急情况下能快速启用应对突发大流量。

五、写在最后

以上就是我们团队在容量规划方面的踩坑总结和实战经验包括什么是容量规划踩过的坑容量规划的方法和步骤以及,应对流量突增的预案希望能帮大家做好容量规划避免踩坑。

容量规划是系统运维和架构设计中非常重要的一环直接关系到系统的稳定性和成本做得好能保证系统稳定运行合理利用资源节省成本做得不好要么系统出故障影响业务要么资源浪费增加成本,所以一定要重视容量规划认真做好。

容量规划不是一次性的工作是持续的过程需要不断地监控分析调整优化不要做一次就一劳永逸要建立定期复盘的机制持续优化容量规划让容量始终能匹配业务的需求,同时尽量提高资源利用率降低成本。

另外容量规划也不是只是运维的事情需要开发测试产品等各个团队一起配合开发要写出高性能的代码测试要做好性能测试产品要提供准确的业务需求和流量预测,只有各个团队一起努力才能做好容量规划保证系统稳定运行。

最后用一句话结束这篇文章:"容量规划是系统稳定性的基石也是成本优化的关键认真做好容量规划持续监控和调整才能在保证系统稳定的,同时最大化资源利用率降低成本。"

愿大家的系统都能稳定高效运行从容应对各种流量挑战。