在做系统架构的时候,我们经常会遇到一个问题:是应该先做好容量规划,保证系统有足够的能力应对流量,还是应该先设计好API网关,通过限流、熔断、降级等手段来保护系统?
这个问题,在技术团队里经常引起争论。一派人认为,容量规划是根本,系统能扛住流量,就不需要那么多花里胡哨的防护手段,加机器就行了。另一派人认为,再大的容量也扛不住突发流量和恶意攻击,API网关的限流、熔断、降级才是系统的护身符,必须先做好。
这两个观点,都有道理,但是都有片面性。实际上,容量规划和API网关设计,不是非此即彼的选择,而是相辅相成的。一个健壮的系统,既需要合理的容量规划,也需要完善的API网关防护。
今天,我想聊聊我对这个问题的思考和实践经验,包括容量规划和API网关各自的作用、它们的关系、怎么结合使用、以及一些常见的误区和最佳实践。
一、先搞清楚:容量规划和API网关,各自解决什么问题
在讨论"选哪个"之前,我们先要搞清楚,容量规划和API网关,各自解决什么问题。它们看起来都是为了系统的稳定性和高可用,但是侧重点完全不同。
1. 容量规划解决什么问题
容量规划,解决的是"系统能不能扛住正常流量"的问题。
它的核心思路是:根据业务的流量预测,计算出系统需要多少资源(CPU、内存、带宽、存储等),然后提前准备好这些资源,确保系统在正常的流量下,能够稳定运行,响应时间在可接受的范围内。
容量规划,主要关注以下几个方面:
- 流量预测:根据历史数据和业务增长,预测未来的流量(QPS、并发数、数据量等)。
- 性能基准:通过压测,知道单台服务器能扛多少QPS,响应时间是多少。
- 资源计算:根据流量预测和性能基准,计算需要多少台服务器、多少带宽、多少存储。
- 冗余设计:在计算的基础上,留一定的冗余(比如2-3倍),应对突发流量和机器故障。
- 弹性伸缩:设计自动扩缩容机制,流量大的时候自动加机器,流量小的时候自动减机器,节省成本。
容量规划做得好,系统在正常流量下,就能稳定运行,不会因为资源不足而响应变慢或者崩溃。
2. API网关解决什么问题
API网关,解决的是"系统在异常情况下怎么保护自己"的问题。
它的核心思路是:在系统的入口处,加一个网关层,对所有进来的请求进行统一的管控,包括路由、鉴权、限流、熔断、降级、监控等。当系统遇到异常情况(突发流量、下游服务故障、恶意攻击等)的时候,API网关能起到保护作用,防止系统被打垮。
API网关,主要提供以下能力:
- 路由转发:把请求转发到对应的后端服务。
- 鉴权认证:统一处理身份认证和权限校验。
- 限流:限制请求的速率,防止流量过大打垮系统。
- 熔断:当下游服务故障的时候,快速失败,不调用故障服务,防止雪崩。
- 降级:在系统压力大或者服务故障的时候,返回兜底数据,保证核心功能可用。
- 监控日志:统一收集请求的日志和监控数据,方便排查问题。
- 协议转换:在不同协议之间转换(比如HTTP转gRPC)。
API网关做得好,系统在遇到异常情况的时候,就能自我保护,不会被打垮,不会发生雪崩。
3. 两者的本质区别
从上面的分析可以看出,容量规划和API网关的本质区别是:
- 容量规划是"加法":通过增加资源,让系统能扛住更多的流量。它假设流量是可预测的,系统是正常的。
- API网关是"减法":通过限制和保护,让系统在流量过大或者服务故障的时候,不会被打垮。它假设流量是不可预测的,系统可能会出问题。
一个是"让系统更强",一个是"让系统更稳"。一个是"进攻",一个是"防守"。
二、为什么不能只选一个
搞清楚了两者的区别,我们就明白了,为什么不能只选一个。
1. 只做容量规划,不做API网关,会怎么样?
如果只做容量规划,不做API网关,那么系统在正常流量下,可能没问题。但是一旦遇到异常情况,就很危险:
- 突发流量:容量规划是基于预测的,但是预测不可能100%准确。如果遇到突发流量(比如热点事件、大促、营销活动),实际流量远超预测,系统就会被打垮。
- 恶意攻击:如果遇到DDoS攻击、爬虫、恶意刷接口等,流量可能是正常流量的几十倍甚至上百倍。再大的容量,也扛不住这种攻击。
- 下游故障:即使自己的系统容量足够,但是如果下游服务出了问题(响应变慢、挂了),请求会堆积在你的系统里,耗尽你的资源,导致你的系统也挂掉。这就是服务雪崩。
- 资源浪费:为了应对极端情况,你需要预留大量的冗余资源。但是这些资源,大部分时间都是闲置的,造成很大的浪费。
所以,只做容量规划,不做API网关,系统是脆弱的,经不起任何异常情况的冲击。
2. 只做API网关,不做容量规划,会怎么样?
如果只做API网关,不做容量规划,那么系统在异常情况下,可能有一定的保护能力,但是在正常流量下,就可能出问题:
- 正常流量都扛不住:如果容量不够,即使是正常的流量,系统也会响应变慢,甚至崩溃。API网关的限流,只能限制超过阈值的流量,但是如果连正常流量都超过了系统的处理能力,那限流就会把大量正常请求挡掉,用户体验很差。
- 限流阈值难设置:API网关的限流,需要设置一个合理的阈值。这个阈值,应该基于系统的实际容量来设置。如果没有做容量规划,不知道系统到底能扛多少QPS,那限流阈值就只能拍脑袋设置,要么设高了起不到保护作用,要么设低了影响正常用户。
- 成本不可控:没有容量规划,就不知道需要多少资源,要么资源不够导致系统不稳定,要么资源太多造成浪费。成本不可控,对于业务来说是很大的问题。
- 无法弹性伸缩:弹性伸缩需要基于容量规划来设计,知道什么时候该加机器,加多少机器。没有容量规划,弹性伸缩就没有依据,要么加得不够,要么加得太多。
所以,只做API网关,不做容量规划,系统在正常情况下就可能不稳定,而且成本不可控。
3. 结论:两者都需要,缺一不可
从上面的分析可以得出结论:容量规划和API网关,两者都需要,缺一不可。
- 容量规划,保证系统在正常流量下,能稳定运行,成本可控。
- API网关,保证系统在异常情况下,能自我保护,不会被打垮。
一个健壮的系统,既需要合理的容量规划,也需要完善的API网关防护。它们是相辅相成的,而不是互相替代的。
三、怎么结合使用:一个实践框架
明白了两者都需要之后,接下来的问题是:怎么结合使用?有没有一个实践框架?
根据我的经验,容量规划和API网关的结合,可以按照以下这个框架来做:
第一步:做容量规划,确定系统的基准容量
首先,要做容量规划,确定系统的基准容量。
- 压测:对系统进行压力测试,知道单台服务器能扛多少QPS,响应时间是多少,资源使用率是多少。
- 预测流量:根据历史数据和业务增长,预测未来一段时间的流量(峰值QPS、平均QPS、并发数等)。
- 计算资源:根据压测结果和流量预测,计算需要多少台服务器、多少带宽、多少存储。
- 留冗余:在计算的基础上,留2-3倍的冗余,应对正常的突发流量和机器故障。
- 确定基准容量:最终确定系统的基准容量,也就是系统在稳定运行的情况下,能扛多少QPS。
这个基准容量,是后续API网关限流阈值设置的依据。
第二步:设计API网关,设置合理的防护策略
有了基准容量之后,就可以设计API网关,设置合理的防护策略了。
- 限流阈值:根据基准容量,设置限流阈值。一般来说,限流阈值设置为基准容量的70%-80%比较合适。留20%-30%的余量,应对突发的小流量波动。比如,基准容量是1000 QPS,那限流阈值可以设置为700-800 QPS。
- 分级限流:不要所有接口都用同一个限流阈值。核心接口(比如下单、支付)可以设置高一点的阈值,保证核心功能可用;非核心接口(比如评论、推荐)可以设置低一点的阈值,在流量大的时候优先牺牲非核心功能。
- 熔断策略:对下游服务的调用,设置熔断策略。当某个下游服务的错误率超过阈值(比如50%),或者响应时间超过阈值(比如1秒),就触发熔断,快速失败,不调用故障服务,防止雪崩。
- 降级策略:设计降级方案。当系统压力大,或者某个服务故障的时候,哪些功能可以降级,怎么降级,返回什么兜底数据,都要提前设计好。比如,商品详情页的推荐功能,可以降级为返回热门商品;评论功能,可以降级为暂时关闭。
- 鉴权和安全:在API网关上统一做鉴权和安全防护,比如身份认证、权限校验、防SQL注入、防XSS、防DDoS等。
第三步:建立监控和告警,及时发现问题
容量规划和API网关都做好了之后,还要建立完善的监控和告警,及时发现问题。
- 系统监控:监控服务器的CPU、内存、带宽、磁盘等资源使用率。
- 业务监控:监控接口的QPS、响应时间、错误率等业务指标。
- 网关监控:监控API网关的限流次数、熔断次数、降级次数等。当这些指标异常升高的时候,说明系统遇到了问题,需要及时处理。
- 告警:设置合理的告警阈值,当指标超过阈值的时候,及时告警,通知相关人员处理。
第四步:定期复盘和优化,持续改进
最后,要定期复盘和优化,持续改进。
- 容量复盘:定期(比如每个季度)复盘容量规划,根据实际流量和业务增长,调整容量规划,更新基准容量。
- 网关策略优化:根据实际运行情况,优化API网关的限流阈值、熔断策略、降级策略等。
- 故障复盘:每次发生故障或者限流、熔断触发的时候,都要做复盘,分析原因,总结经验,优化系统。
- 压测验证:定期做压测,验证系统的实际容量和防护策略是否有效。
四、常见的误区
在实践中,我发现很多团队在容量规划和API网关方面,存在一些常见的误区。这里列举几个,供大家参考:
误区1:容量规划就是加机器
很多人以为,容量规划就是加机器,流量大了就加机器,流量小了就减机器。其实不是这样的。
容量规划,不仅仅是加机器,还包括性能优化、架构优化、缓存设计、异步化等很多方面。有时候,通过优化代码、加缓存、做异步,就能把系统的容量提升几倍,比单纯加机器划算多了。
而且,加机器也不是无限的。当系统达到一定规模之后,加机器的边际效益会递减,甚至会因为分布式系统的复杂性,带来新的问题。所以,容量规划要综合考虑,不能只靠加机器。
误区2:API网关是万能的,有了网关就不用做容量规划了
有些人以为,有了API网关,有了限流熔断降级,系统就安全了,不用做容量规划了。这是错误的。
API网关的限流,只能保护系统不被超过阈值的流量打垮。但是,如果系统本身的容量就不够,连正常流量都扛不住,那限流就会把大量正常请求挡掉,用户体验很差。
而且,API网关本身也有性能瓶颈。如果网关的容量不够,它自己就会先被打垮,更别说保护后端系统了。所以,API网关本身也需要做容量规划。
误区3:限流阈值设得越高越好
有些人觉得,限流阈值设得高一点,能让更多请求通过,用户体验更好。所以,把限流阈值设得很高,甚至接近系统的极限容量。
这是很危险的。因为,系统的极限容量,是在理想情况下测出来的。实际运行中,可能会有各种因素影响性能(比如垃圾回收、网络波动、下游服务变慢等),实际容量可能比极限容量低。如果限流阈值设得太高,就起不到保护作用,系统还是可能被打垮。
而且,限流阈值设得太高,系统在高负载下运行,响应时间会变长,用户体验反而更差。不如把阈值设得合理一点,让系统在比较轻松的负载下运行,响应时间更短,用户体验更好。超过阈值的请求,虽然被限流了,但是至少不会把整个系统拖垮。
一般来说,限流阈值设置为基准容量的70%-80%比较合适。
误区4:熔断和降级是一回事
很多人把熔断和降级混为一谈,以为它们是一回事。其实不是。
熔断,是针对下游服务调用的。当下游服务故障的时候,快速失败,不调用故障服务,防止雪崩。熔断的触发,是自动的,基于错误率或者响应时间。
降级,是针对业务功能的。在系统压力大或者服务故障的时候,主动关闭一些非核心功能,或者返回兜底数据,保证核心功能可用。降级的触发,可以是自动的(基于系统负载),也可以是手动的(运维人员手动开关)。
熔断和降级,经常配合使用,但是它们的关注点不同。熔断关注的是"不要调用故障服务",降级关注的是"牺牲非核心功能,保证核心功能"。
误区5:容量规划和API网关,做一次就完事了
有些人以为,容量规划和API网关,做一次就完事了,以后不用管了。这是错误的。
业务是在不断发展的,流量是在不断变化的,系统是在不断迭代的。今天的容量规划,可能半年之后就不适用了。今天的API网关策略,可能下个月就需要调整了。
所以,容量规划和API网关,都需要持续地维护和优化。要定期复盘,根据实际情况调整,才能保证系统始终稳定可靠。
五、写在最后
容量规划和API网关,是系统架构中两个非常重要的方面。它们不是非此即彼的选择,而是相辅相成的。
容量规划,是系统的基础,保证系统在正常流量下能稳定运行,成本可控。API网关,是系统的防护,保证系统在异常情况下能自我保护,不会被打垮。
一个健壮的系统,既需要合理的容量规划,也需要完善的API网关防护。只做其中一个,系统都是脆弱的。只有把两者结合起来,才能构建出真正稳定、可靠、高可用的系统。
当然,具体怎么做,要根据团队的实际情况来。如果团队比较小,业务还在早期,可以先做基础的容量规划,加一个简单的API网关(比如用Nginx做限流),保证系统基本稳定。等业务发展起来了,团队壮大了,再逐步完善容量规划和API网关的能力。
不要一开始就追求大而全,做很复杂的容量规划和很完善的API网关,那样成本太高,也没有必要。循序渐进,根据业务的发展,逐步完善,才是比较务实的做法。
最后,用一句话来总结这篇文章:"容量规划让系统能扛住正常流量,API网关让系统能抵御异常冲击。两者相辅相成,缺一不可。合理规划,精心防护,持续优化,才能构建出真正稳定可靠的系统。"
希望这篇文章,能给正在做系统架构的你,一些参考和启发。如果你有不同的观点或者更好的实践经验,欢迎在评论区留言,我们一起交流。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录