架构与思维:熔断限流的一些使用场景

架构,思维,熔断,限流,一些,使用,场景 · 浏览次数 : 2011

小编点评

## 服务的能力终归是有限的,如何友好的使用限流来进行落地? 本文介绍了如何使用限流来应对服务的能力终归问题,包括两种场景: **1.1 突发高峰照成的服务雪崩** * 突发流量超过服务能力的峰值时,服务无法处理请求,导致雪崩。 * 解决方案: * 使用 **计数限流算法** 或 **固定窗口限流** 等技术,在峰值期间记录请求数量,当时间间隔到期之后,清理计数器,重新计算请求数量。 * 使用 **滑动窗口限流** 等技术,在窗口内记录请求时间点,并在窗口结束时计算平均请求数量,如果超过阈值,则拒绝请求。 **1.2 超出预期值的流量洪峰** * 超出预期的流量时,服务可能无法处理请求,导致雪崩。 * 解决方案: * 使用 **兜底的限流** 或 **熔断** 等技术,在流量洪峰前设置一个保护机制,如延迟或拒绝请求。 * 使用 **缓存** 等技术,缓存部分流量,减少对数据库的压力。 **2. 解决方案** **2.1 应用层面解决方案** * 使用 **限流算法** 或 **熔断** 等技术,在流量过高时限制服务实例数量,降低请求处理效率。 * 使用 **缓存** 等技术,缓存部分流量,减少对数据库的压力。 **2.2 存储层面解决方案** * 使用 **分布式锁** 或 **请求按照队列执行** 等技术,避免所有请求都并发访问数据库,降低数据库负载。 * 使用 **缓存预热** 等技术,在缓存中存储部分数据,避免数据库频繁查询。

正文

1 前言

在《微服务系列》中,我们讲过很多限流,熔断相关的知识。
老生长谈的一个话题,服务的能力终归是有限的,无论是内存、CPU、线程数都是,如果遇到突如其来的峰量请求,我们怎么友好的使用限流来进行落地,避免整个服务集群的雪崩。

峰量请求主要有两种场景:

1.1 突发高峰照成的服务雪崩

如果你的服务突然遇到持续性的、高频率的、不符合预期的突发流量。你需要检查一下服务是否有被错误调用、恶意攻击,或者下游程序逻辑问题。
这种超出预期的调用经常会造成你的服务响应延迟,请求堆积,甚至服务雪崩。而雪崩会随着调用链向上传递,导致整个服务链的崩溃,对我们的系统造成很大的隐患。
image

1.2 超出预期值的流量洪峰

如果你的商城或者平台搞活动(类似双11、618),但你又无法有效评估出这个峰值的具象值和持续时间,那么你的服务依然有被打垮的风险。
除非你能做到服务集群弹性伸缩(动态扩缩容)的能力,这个我在后面的云原生系列中会详细说。
image
如上图,正常量值为1500 QPS,预估模型的量值是2600的QPS,后面发现,来了几波活动,量值增加到 10000,远超过我们服务器的负载。服务一过载,系统就开始出现各种问题,延迟、故障、请求堆积,甚至雪崩。

2 解决方案

2.1 云原生和弹性伸缩

如果你的服务基架构与足够强大,你的服务上云足够的彻底,那么弹性伸缩是最好的办法。类似淘宝、京东、百度APP,都是类似的做法。
kubernetes会根据流量的变化,CPU、内存的曲线过程实时计算需要的服务实例数,然后进行动态扩容,低峰期再还回去。这个要求你的服务上云足够彻底,并且有足够的资源来达成资源扩容的目标。
★关于这块内容笔者后续会有专门的系列来讲解,以及如何在大厂实现落地的过程,这边不展开。

2.2 兜底的限流、熔断

最基本的保障就是能够在服务做一层保护,避免因为过载而造成服务雪崩,导致整个系统不可用.
对超过预期或者承载能力的流量进行限流是比较好的一种办法。所以你在双11、618、抢购、竞拍 等的选择的时候会经常看到这样的词汇:

  • 服务正在努力加载中,请稍候!
  • 服务/网络错误,请重试!
  • 哎呀,服务繁忙,请稍后再试!
    image

2.1 应用层面解决方案

2.1.1 常见的限流算法

  • 计数限流算法

计数算法是指再一定的时间间隔里,记录请求次数,当时间间隔到期之后,就把计数清零,重新计算。
image

  • 固定窗口限流算法(采样时间窗)

相对于上一个 计数限流,多了个时间窗口的概念,计数器每过一个时间窗口就重置,重新开始计算。
image

  • 滑动窗口限流(记录每个请求到达的时间点)

滑动窗口限流解决固定窗口临界值的问题,可以保证在任意时间窗口内都不会超过阈值。
image

  • 漏桶算法(漏斗池算法)

类似沙漏思维,大家都用过,沙子是匀速流出得。对于漏桶来说,由于它的出水口的速度是恒定的,也就是消化处理请求的速度是恒定的,所以它可以保证服务以恒定的速率来处理请求,
image

  • 令牌桶算法(定速流入)

令牌桶和漏桶的原理类似,只不过漏桶是定速流出,令牌桶是定速流入(即往桶里塞入令牌),每个请求进来,分配一个令牌,只有拿到了令牌才能进入服务器处理,拿不到令牌的就被拒绝了。
因为令牌桶的大小也是有限制的,所以一旦令牌桶满,后续生成的令牌就会被丢弃,拿不到令牌的服务请求就被拒绝了,达到限流的目的。执行原理如下:
image

2.1.2 相关实现的框架

  • Spring Cloud 的 Hystrix
  • Sentinel 熔断降级能力
  • Google Guava 的 Ratter Limitter

2.1.3 达到限流条件的时候的做法

fallback:返回固定的对象或者执行固定的方法

// 返回固定的对象
{
"timestamp": 1649756501928,
"status": 429,
"message": "Too Many Requests",
}

// 执行固定的处理方法
function  fallBack(Context ctx) {
   // Todo 默认的处理逻辑
}

2.1.4 Web/Mobile/PC/3d

接收到固定的消息结构或者固定的处理结果之后,以友好的方式提示给用户。

  • 提示服务正在努力加载中,请稍候!
  • 服务/网络错误,请重试!
  • 哎呀,服务繁忙,请稍后再试!

2.2 存储层面解决方案

Redis热点数据同时并发请求处理,1000W+请求同时投向后端,如果缓存未建立,直接投向数据库,可能会造成击穿,怎么破?一般有如下解决方法,优劣各异:

  • 分布式锁:只允许一个请求线程去访问DB,其他请求被阻塞,这样就避免了很多请求投放到DB上。但是这样吞吐量降低。

  • 请求按照队列执行:按照队列顺序执行,避免全部投向数据库。这样还是吞吐量降低。

  • 缓存预热:进入数据库的缓存数量会比较少,保证有一部分的数据先做出来。

  • 空/默认 初始值:第一个请求进去的时候,创建空初始值或者默认初始值的缓存,并进入数据库查询。查询之后,更新缓存,保证后续的拿到正确的值。而在查询的这个过程中(可能几ms到几十ms),拿到的是默认值或空置,前端做一下友好的提示。这是一种降级的策略,保证仅有1个或者前n个进入数据库。

  • 本地缓存:改造web应用服务,在获取到redis缓存后,在web服务本地把热点的数据进行缓存,因为热点的商品不会很多,所以保存在本地缓存中,是没有问题的。这样请求数据时,如果web本地有缓存数据,就直接返回了。本地缓存和服务进程缓存混用的情况。缓存更新会增加额外的负担。
    这里面,空初始值和和分布式锁的结合使用是目前很多大厂的处理方式,如下:
    image

  • 第一个请求进去的时候,创建空初始值或者默认初始值的缓存

  • 后续进来的同类请求会短暂获取到 默认值的缓存信息

  • 当第一个请求从数据库查询到结果,立即更新缓存,保证后续的同类请求拿到的是正确的值

  • 而第一个请求调用数据库的过程中(可能几ms到几十ms),其他同类请求拿到的是默认值或空值,前端做一下友好的提示

  • 这是一种典型的降级策略,保证仅有1个或者前n个进入数据库

3 总结

无论是应用层级还是存储层级,无非是跟前端约定一个规则,返回默认参数或者默认回到方法,让前端以用户友好体验的方式进行降级,保证服务端不至于崩溃。

与架构与思维:熔断限流的一些使用场景相似的内容:

架构与思维:熔断限流的一些使用场景

1 前言 在《微服务系列》中,我们讲过很多限流,熔断相关的知识。 老生长谈的一个话题,服务的能力终归是有限的,无论是内存、CPU、线程数都是,如果遇到突如其来的峰量请求,我们怎么友好的使用限流来进行落地,避免整个服务集群的雪崩。 峰量请求主要有两种场景: 1.1 突发高峰照成的服务雪崩 如果你的服务

架构与思维:秒杀和竞拍的业务架构,永不过时的话题

1 互联网架构越来越复杂? 为啥感觉互联网架构越来越复杂了,早期我们的系统,可能也就那么少部分人使用,大都是一些后台管理系统。 所以不用考虑很多东西,比如: 流量少,无需考虑并发问题 数据少,不用考虑什么索引优化、分库分表 访问不集中,不用考虑缓存、过载保护 如果数据不重要,不用考虑安全策略,甚至不

架构与思维:微服务架构的思想本质

我们为什么需要微服务架构,它一定是为了解决我们某些问题才出现了。这篇文章我们讨论下微服务架构模式所解决的问题,带来的挑战,以及他的核心思想本质。 1 早期的服务架构 上图是一个典型的服务分层架构: Client: 调用方是browser web或者App 应用层: 实现计算层的业务逻辑,从上游数据层

架构与思维:了解Http 和 Https的区别(图文详解)

1 介绍 随着 HTTPS 的不断普及和使用成本的下降,现阶段大部分的系统都已经开始用上 HTTPS 协议。 HTTPS 与 HTTP 相比, 主打的就是安全概念,相关的知识如 SSL 、非对称加密、 CA证书、数据完整性保护 等,我们多多少少也都有听过。 本文重点从原理上讲解 HTTPS 的安全性

架构与思维:4大主流分布式算法介绍(图文并茂、算法拆解)

0 导读 之前的文章中,我们介绍过分布式事务的基础知识,也了解了分布式场景下常见一致性问题和解决方案,对分布式锁和CAS模式有一定的了解,有兴趣的同学可以通过下面链接到作者的两篇相关文章。 五种分布式事务解决方案(图文总结) 高并发下的数据一致性保障(图文全面总结) 1 介绍 本文聚焦高并发场景下分

架构与思维:再聊缓存击穿,面试是一场博弈

1 介绍 在之前的一篇文章《一次缓存雪崩的灾难复盘》中,我们比较清晰的描述了缓存雪崩、穿透、击穿的各自特征和解决方案,想详细了解的可以移步。 最近在配合HR筛选候选人,作为大厂的业务方向负责人,招人主要也是我们自己团队在用,而缓存是必不可少的面试选项之一。下面我们就来聊一聊在特定业务场景下缓存击穿和

实时数仓构建:Flink+OLAP查询的一些实践与思考

以Flink为主的计算引擎配合OLAP查询分析引擎组合进而构建实时数仓**,其技术方案的选择是我们在技术选型过程中最常见的问题之一。也是很多公司和业务支持过程中会实实在在遇到的问题。 很多人一提起实时数仓,就直接大谈特谈Hudi,Flink的流批一体等,但实际上,**实时数仓包括任何架构体系的构建如...

快速理解DDD领域驱动设计架构思想-基础篇

本文与大家一起学习并介绍领域驱动设计(Domain Drive Design) 简称DDD,以及为什么我们需要领域驱动设计,它有哪些优缺点,尽量用一些通俗易懂文字来描述讲解领域驱动设计

[转帖]浅谈系统稳定性与高可用保障的几种思路

https://segmentfault.com/u/dewujishu 一、前言 高并发、高可用、高性能被称为互联网三高架构,这三者都是工程师和架构师在系统架构设计中必须考虑的因素之一。今天我们就来聊一聊三H中的高可用,也是我们常说的系统稳定性。 本篇文章只聊思路,没有太多的深入细节。阅读全文大概

凭证管理揭秘:Cookie-Session 与 JWT 方案的对决

在软件架构中,关于凭证如何存储和传递,一直有两种不同的解决思路,两种不同的解决方式,实际上反映了两种不同的架构思路