最近我在做系统容量规划从一开始的兴致勃勃到后来的怀疑人生再到最后的从入门到放弃经历了很多也学到了很多容量规划听起来很简单不就是算一算需要多少台服务器吗,但是真正做起来才发现这里面的水很深坑很多远不是算个数,那么简单。
本文记录了我做容量规划的经历和心路历程从入门到放弃的全过程包括遇到的问题踩过的坑以及,最后的感悟和总结希望能给大家一些启发和娱乐。
一、入门阶段:兴致勃勃觉得很简单
事情是这样开始的我们团队最近在做系统的架构优化和成本优化领导说我们的服务器资源利用率不高有些浪费让我做一个容量规划看看每个服务到底需要多少资源能不能优化一下节省成本我一听觉得这还不简单不就是看看每个服务的CPU内存使用率,然后算一算需要多少台服务器吗,于是兴致勃勃地接下了这个任务开始做容量规划。
第一步:收集监控数据:
我首先,去监控系统(我们用的是Prometheus + Grafana)拉取了每个服务的CPU内存使用率数据看了最近一个月的数据包括平均值峰值P95P99等等拉完数据一看我就有点懵了,因为每个服务的资源使用率差别很大有的服务CPU平均使用率才5%峰值也才20%有的服务CPU平均使用率30%峰值能到80%内存也是有的服务内存使用率很低有的很高,而且不,同时间段的使用率差别也很大白天高晚上低工作日高周末低这一下就把我搞懵了到底该用哪个数据来算容量呢?
我想应该用峰值吧,因为容量规划要保证峰值的时候,系统也能扛住,所以我就用每个服务的CPU内存峰值使用率来算需要多少台服务器算完之后,发现确实有不少服务资源利用率不高可以合并,或者缩容节省一些服务器我挺开心的觉得容量规划也,不过如此很简单嘛。
第二步:做容量测试验证:
但是我又想光看监控数据可能不准,因为监控数据是历史的,而且可能有一些特殊情况影响数据,所以我决定做一下容量测试验证一下每个服务的极限性能和容量我用压测工具(JMeter)对几个核心服务做了压力测试逐步增加并发数看服务的极限QPS和响应时间结果压测结果一出来我就更懵了,因为压测出来的极限QPS和我根据监控数据算出来的容量差别很大有的服务压测出来的极限QPS比我算的高很多有的又低很多,而且压测的场景和真实业务场景也不一样压测的请求比较单一真实业务的请求比较复杂,所以压测结果也不能完全代表真实情况。
这时候我开始觉得容量规划好像没,那么简单了,但是还是觉得问题不大调整一下方法应该就能搞定,于是我继续研究。
二、进阶阶段:发现问题开始怀疑人生
随着做的深入我发现容量规划的问题越来越多越来越复杂我也开始怀疑人生了。
问题1:流量是动态变化的根本没法准确预测:
第一个大问题是流量是动态变化的根本没法准确预测我一开始以为根据历史数据就能预测未来的流量,但是后来发现根本不是,那么回事流量受很多因素影响,比如业务活动节假日热点事件营销推广等等这些因素都很难预测,比如我们上个月做了一个大促活动流量突然涨了3倍,但是这个月没有活动流量又降回去了,而且有时候突然来一个热点事件流量又突然涨上去根本没法预测。
而且不同服务的流量变化规律也不一样有的服务流量比较稳定有的服务流量波动很大有的服务白天流量高晚上低有的服务晚上流量高白天低有,的服务工作日流量高周末低有的服务周末流量高工作日低这么多变化规律根本没法用一个简单的模型来预测更别说准确预测未来的流量了。
我试了很多方法来预测流量,比如用历史平均值用峰值用同比环比用时间序列预测算法(ARIMA等等)但是结果都不准,因为流量的变化太随机了受太多不可控因素影响根本没法准确预测这时候我开始怀疑容量规划到底有没有意义,既然流量都没法准确预测那容量规划不就是瞎猜吗?
问题2:资源使用率和实际容量不是线性关系:
第二个大问题是资源使用率和实际容量不是线性关系我一开始以为CPU使用率50%就说明服务,还有一半的容量还能扛一倍的流量,但是后来发现根本不是这么回事,因为当CPU使用率超过一定阈值(比如70%)之后,服务的响应时间会急剧上升错误率也会增加系统开始不稳定,所以,虽然CPU使用率才70%看起来,还有30%的余量,但是实际上,已经接近极限了不能再增加流量了,否则系统就会出问题。
而且不同服务的资源瓶颈也不一样有的服务是CPU密集型瓶颈在CPU有的服务是IO密集型瓶颈在磁盘IO或者网络IO有的服务瓶颈在数据库连接数,或者线程池大小不是只看CPU和内存使用率就能判断容量的我之前,只看CPU和内存使用率来算容量根本就不准,因为很多服务的瓶颈不在CPU和内存而在其他资源,比如数据库连接池线程池等等这些资源满了,即使CPU和内存,还有余量服务也扛不住了。
这时候我才意识到容量规划要考虑的资源维度太多了CPU内存磁盘IO网络IO数据库连接数线程池队列长度等等每个服务的瓶颈都不一样要逐个分析逐个评估工作量巨大,而且很难准确评估我开始觉得容量规划这事儿真不是人干的。
问题3:服务之间,有依赖容量不能孤立评估:
第三个大问题是服务之间,有依赖容量不能孤立评估我们的系统是微服务架构有几十个服务服务之间,相互调用形成了复杂的调用链一个服务的容量,不仅取决于自己的资源还取决于它依赖的下游服务的容量,比如A服务调用B服务B服务调用C服务,即使A服务自己的资源,还有余量,但是,如果B或者C服务扛不住了A服务也会受影响响应变慢甚至报错,所以评估A服务的容量不能只看A自己的资源还要看整个调用链上所有服务的容量找到最短的那块木板(瓶颈)那才是整个调用链的实际容量。
这就更复杂了几十个服务相互调用调用关系错综复杂要评估每个调用链的容量找到每个链的瓶颈工作量简直是天文数字,而且服务之间,的调用关系还在不断变化新的服务不断加入旧的服务不断修改调用关系也在变化根本没法做一个准确的容量评估,因为等你评估完可能调用关系已经变了评估结果就不准了。
这时候我已经开始怀疑人生了觉得容量规划这事儿根本就没法做准太复杂了变量太多了根本没法控制。
问题4:业务在不断变化容量规划跟不上变化:
第四个大问题是业务在不断变化容量规划跟不上变化我们的业务发展很快新功能不断上线旧功能不断修改流量也在不断变化可能这个月这个服务流量还很小下个月,因为上了新功能,或者做了活动流量突然就涨了几倍也可能这个月这个服务还很重要流量很大下个月业务调整了这个服务就下线了,或者流量变得很小业务变化太快了容量规划根本跟不上变化可能你花了一个月做出来的容量规划结果还没来得及实施业务就变了规划结果就不准了白做了。
而且我们的系统还在不断做架构调整和优化服务的拆分合并迁移等等都在不断进行服务的资源使用情况也在不断变化今天这个服务CPU使用率高明天优化了代码CPU使用率就降下来了今天这个服务需要10台服务器明天做了缓存优化可能5台就够了这么多变化容量规划根本没法跟上只能不断调整不断重新规划,但是这样就陷入了死循环永远在做容量规划,但是永远不准,因为等你规划完情况又变了。
这时候我已经彻底放弃了准确容量规划的想法觉得这根本就是不可能完成的任务变量太多变化太快根本没法做准。
三、放弃阶段:换个思路拥抱变化
在经历了上面的各种问题和打击之后,我终于放弃了做一个准确的容量规划的想法,但是任务还得完成啊领导还在等结果呢,于是我换了个思路,既然没法准确预测和规划那就不要追求准确了拥抱变化用弹性的方式来应对变化这样可能更实际也更有效。
思路1:不追求准确只做粗略估算和预案:
首先,我放弃了追求准确容量规划的想法不再试图准确预测每个服务需要多少资源而是只做一个粗略的估算和预案,比如根据历史数据和经验估算每个服务大概需要多少资源,然后留一定的冗余(比如50%-100%)应对流量波动和突发情况这样,虽然不准确,但是能保证系统稳定也不会太浪费。
而且我还做了各种场景的预案,比如流量涨2倍怎么办涨5倍怎么办涨10倍怎么办每个场景下需要多少资源怎么扩容需要多长时间等等这样,即使流量突然变化也能快速应对不会手忙脚乱,虽然不能准确预测流量,但是有预案就能应对各种情况这比做一个看似准确,但是实际不准的规划有用多了。
思路2:用弹性伸缩代替固定容量规划:
然后我大力推进了弹性伸缩机制用弹性伸缩代替固定容量规划,既然流量是动态变化的没法准确预测那就让系统自己根据流量变化自动调整容量流量高的时候,自动扩容增加资源流量低的时候,自动缩容减少资源这样既能保证系统稳定又能节省成本比固定容量规划灵活多了也有效多了。
我们用Kubernetes的Horizontal Pod Autoscaler(HPA)来做弹性伸缩根据CPU使用率,或者自定义指标(比如QPS响应时间)自动调整Pod的数量流量高的时候,自动扩容流量低的时候,自动缩容非常方便也很智能上线了弹性伸缩之后,我们的资源利用率提升了很多成本也降了不少,而且系统也更稳定了,因为流量涨的时候,会自动扩容不会,因为资源不够出问题这比我之前,费劲做容量规划效果好太多了。
思路3:建立完善的监控和告警及时发现问题:
另外我还建立了完善的监控和告警机制,因为,既然容量没法准确规划那就要能及时发现问题快速应对我们完善了各个维度的监控包括系统资源监控(CPU内存磁盘IO网络IO)应用性能监控(QPS响应时间错误率)业务指标监控(订单量用户量等等)依赖服务监控(数据库缓存消息队列等等)并且设置了合理的告警阈值某个指标异常的时候,及时告警通知我们快速处理。
有了完善的监控和告警我们能及时发现资源瓶颈和性能问题快速扩容,或者优化避免问题扩大影响业务这也弥补了容量规划不准的问题,虽然不能提前准确规划容量,但是能及时发现问题快速应对也能保证系统稳定。
思路4:定期复盘和调整持续优化:
最后我建立了定期复盘和调整的机制,虽然容量没法一次规划准确,但是可以定期复盘根据实际情况调整优化我们每个月都会复盘一下各个服务的资源使用情况流量变化情况看看哪些服务资源不够需要扩容哪些服务资源过剩可以缩容哪些服务有性能问题需要优化,然后及时调整优化这样持续迭代不断优化资源使用效率,虽然不能一次到位,但是持续优化下来效果也很好。
而且我们还会根据业务计划提前做一些准备,比如下个季度有什么大的活动,或者新功能上线预计流量会涨多少提前做一些容量准备和预案,虽然不一定准确,但是有准备总比没准备好到时候也能快速应对。
四、我的感悟和总结
经过这一番折腾从入门到放弃再到换思路拥抱变化我对容量规划有了全新的认识也有了很多感悟。
感悟1:容量规划没有绝对准确,只有相对合理:
第一个感悟是容量规划没有绝对准确,只有相对合理,因为影响容量的因素太多了流量是动态变化的业务是不断发展的系统是不断演进的根本没法做一个绝对准确的容量规划追求绝对准确的容量规划是不现实的只会让自己痛苦也做不好我们应该追求相对合理的容量规划,只要能保证系统稳定资源利用率合理成本可控就够了不用追求绝对准确。
感悟2:弹性和自适应比精准规划更重要:
第二个感悟是弹性和自适应比精准规划更重要在这个快速变化的时代业务和流量都在快速变化精准规划是很难的也是跟不上变化的与其费劲做一个不准的规划不如建立弹性的自适应的系统让系统自己根据变化调整容量这样更灵活也更有效弹性伸缩自动扩缩容这些机制比精准容量规划有用多了能更好地应对变化保证系统稳定也能提升资源利用率降低成本。
感悟3:监控和告警是容量规划的兜底保障:
第三个感悟是监控和告警是容量规划的兜底保障,不管容量规划做得多好都可能有意外情况流量突然暴涨,或者出现性能问题这时候完善的监控和告警就能帮我们及时发现问题快速应对避免问题扩大影响业务,所以监控和告警是必不可少的是容量规划的兜底保障一定要重视做好监控和告警比做一个看似完美的容量规划更重要。
感悟4:容量规划是持续的过程不是一次性的工作:
第四个感悟是容量规划是持续的过程不是一次性的工作很多人以为容量规划是一次性的工作做一次就一劳永逸了,但是实际上,不是这样业务在变化流量在变化系统在演进容量也需要不断调整优化,所以容量规划是一个持续的过程需要定期复盘调整优化持续迭代才能保证容量合理资源利用率高成本可控不要指望做一次容量规划就一劳永逸那是不现实的。
感悟5:不要为了规划而规划要解决实际问题:
第五个感悟是不要为了规划而规划要解决实际问题我一开始就是陷入了为了规划而规划的误区总想做一个完美的准确的容量规划结果越做越复杂越做越不准自己也很痛苦后来才想明白容量规划的目的是解决实际问题保证系统稳定提升资源利用率降低成本,只要能解决这些问题,不管用什么方法都可以不用追求形式上的完美和准确,所以后来我换了思路用弹性伸缩监控告警定期复盘这些方式来解决实际问题效果反而更好也更实际。
五、写在最后
以上就是我做容量规划从入门到放弃的全部经历和感悟从一开始的兴致勃勃觉得很简单到后来的发现问题怀疑人生再到最后的放弃精准规划换思路拥抱变化用弹性和自适应来解决问题这整个过程,虽然有点折腾,但是也让我学到了很多对容量规划有了全新的认识。
容量规划确实是一件很复杂的事情影响因素太多变化太快很难做得绝对准确,但是这并不意味着容量规划没有意义我们只是需要换个思路不要追求绝对准确的规划而是建立弹性的自适应的系统完善的监控和告警以及定期复盘调整的机制用这些方式来应对变化解决实际问题这样可能比做一个看似准确,但是实际不准的规划更有效也更实际。
希望我的经历和感悟能给正在做容量规划的朋友一些启发不要像我一开始那样陷入追求精准规划的误区搞得自己很痛苦也做不好换个思路拥抱变化用弹性和自适应来解决问题可能会豁然开朗效果更好。
最后用一句话结束这篇文章:"容量规划没有最好,只有更合适不要追求绝对准确要追求解决实际问题弹性自适应监控告警持续优化才是应对变化的正确姿势。"
愿大家都能做好容量规划保证系统稳定高效运行从容应对各种变化和挑战。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录