概述
容量治理的三个重要手段:扩容、限流与降级,这三个手段分别基于不同的视角来实施,在容量保障中发挥着不同的作用和价值。
容量保障是需要考虑成本的。
扩容的实践要点
认知
- 扩容通俗的理解就是在集群中不断加入新的服务器资源的过程,一般也称伸缩性,主要用于应对流量增长的能力
- 对待扩容应该秉承谨慎的态度,鼓励将快速扩容作为应急手段,但作为容量质量的手段要谨慎,警惕无脑扩容和滥用扩容
- 要建立服务性能优化胜过简单扩容的意识,努力通过性能优化腾出容量,避免不经思考直接扩容
- 扩容的出发点是尽可能提供足够的资源保证服务容量充足
实践
- 在实际研发中,当遇到服务容量不足时,谨记不要第一个念头就是扩容,而更应该去考虑优化服务本身,如:异步处理、读写分离、增加缓存、SQL 调优等
- 扩容不能只关注服务本身的资源占用情况,还应同时关注对底层资源的影响,如数据库资源、中间件资源
- 应对扩容要考虑的通用做法:先梳理出被扩容服务的调用链路,看一看流量经过哪些地方,分析一下这些地方会不会受扩容的影响,再去采用相应的措施
案例
案例一:数据库连接数瓶颈
某服务集群一共有 10 个容器实例,每个实例会建立约 100 个数据库连接,加起来就是约 1000 个连接,假设数据库总共支持的连接数为 1200 个,这是能够支撑现状的。但如果考虑到近期业务增长较快,需要扩容 5 个实例,那么总的数据库连接数大约会达到 1500 个,这就肯定支撑不住了,所以对服务进行扩容时,对数据库也需要同步扩容。
案例二:服务发现的长连接瓶颈
在微服务体系中有一项服务发现机制,每个服务可以通过该机制获取被调用服务的位置。服务发现机制的一种实现方式是,由一个注册中心建立对每个服务实例的长连接,并维护一个服务状态列表,这样一旦服务状态发生变化,注册中心能够第一时间感知到并对服务状态列表进行更新。这些建立的大量长连接可能会产生瓶颈(主要是消耗内存),当我们对服务进行扩容时,实际上就是增加了服务实例,这会产生更多的长连接。因此在这种服务发现模式下进行扩容时,注册中心的容量也需要同步考虑。
限流的实践要点
认知
- 限流是在控制成本的情况下对服务容量的一种保护性措施
- 限流是通过拒绝一部分服务流量来强行控制服务负载的手段,是从控制流量的视角来保证服务容量安全
- 相较于紧急扩容,提前设置合理的限流对系统进行过载保护,是更主动的方式
- 限流策略的选择和业务场景应该是高度挂钩的
- 良好的限流应该是分层的
限流策略
两窗两桶:固定窗口、滑动窗口、漏桶算法、令牌桶算法
三大流量控制:
| 策略 | 说明 |
|---|---|
| 流量整形 | 不管流量到达的速率多么不稳定,在接收流量后都将其均匀输出,即”乱进齐出” |
| 容忍突发流量 | 限流策略允许流量在短时间内突增,且在突增结束后不影响后续流量的正常限流 |
| 平滑限流 | 在限流周期内流量分布均匀,比如限制 10 秒内请求次数不超过 1000,平滑限流应做到每秒不超过 100 次请求 |
实践
限流分层:
- 网关层限流
- 接入层限流
- 应用层限流
- 数据库层限流
在制定每一层的限流策略时,都应该抱着不信任上层限流的思维,这样即使上层限流出现问题,也不会引发全局问题。
核心思路:
- 根据业务特点(是否有突发流量、输出流量、是否需要整形、是否需要平滑限流等),选择合适的限流策略
- 分层次,在不同的位置进行限流,多管齐下全方位完善限流体系
降级的实践要点
认知
降级是从系统功能的角度来实施容量治理,人为或自动地将某些不重要的功能停掉或者简化,以降低服务负载,释放的资源可以去支撑更核心的功能(弃卒保帅)。
降级策略
| 策略 | 示例 |
|---|---|
| 牺牲用户体验 | 不展示个性化推荐、不展示搜索热词、不展示缩略图 |
| 放弃部分功能 | 不允许退货、不允许评论 |
| 降低安全性 | 不调用风控接口、不记录审查日志 |
| 降低准确性 | 排序不带权重、搜索内容不是最新 |
| 降低一致性 | 库存信息不做强一致性校验、允许一定的超卖 |
| 降低数据量 | 评论只显示 100 条、历史订单只能查近三个月 |
实践
- 降级的技术实现一般是通过设置开关,并将开关收口至配置中心的方式集中式管理
- 降级需要平衡好自动触发和人工执行两种做法
案例
需要人工介入的场景:在系统偶发抖动的情况下,到底是降还是不降,需要根据当时的业务情况做综合判断,这时候人工介入更靠谱。此外,还有一些降级会涉及到与第三方的合约,比如对支付宝、微信支付这类功能的降级,需要与对方确认后才能执行。
适合自动触发的场景:请求调用失败次数大于一定的阈值,或是服务接口超时等情况;还有一些旁路服务,比如审查日志记录等,如果压力过大也可以直接触发自动降级。
降级和限流的区别
| 维度 | 降级 | 限流 |
|---|---|---|
| 核心手段 | 依靠牺牲一部分功能或体验保住容量 | 依靠牺牲一部分流量来保护容量 |
| 策略特点 | 策略较多,需要从多角度去简化 | 通用性更强 |
| 实施建议 | 对降级进行分级,实现有层次的降级效果;通过高频演练确保降级的有效性 | 分层限流,不信任上层限流 |