分布式高可靠:流量控制


前言

分布式高可靠中的负载均衡的核心在于,将用户请求均匀分配到多个处理服务器处理,以解决单个服务器的单点瓶颈问题。但如果用户请 求数非常多的话,即便实现了负载均衡,服务器能力达到上限,还是无法处理所有的用户请求。

比如,类似双十一、双十二的秒杀场景,用户流量突增时,即使做了负载均衡,仍然会感受到点击抢购时,需要等待较长的时间。这背后的原理是系统控制了用户的请求量。

什么是流量控制?

网络传输中的流量控制,就是让发送方发送数据的速率不要太快,让接收方来得及接收数据,具体的实现方法就是滑动窗口。

滑动窗口:在任意时刻,发送方都维持一个连续的允许发送的数据大小, 称为发送窗口;接收方也会维持一个连续的允许接收的数据大小,称为接收窗口。每次发送方给接收方发送数据后,必须收到接收方返回的确认消息,发送窗口才可向后移动,发送新的数据。

如图所示,发送窗口和接收窗口大小均为 1,发送方发送数据 D1 后,只有接收到来自接收方的确认消息 ACK,发送窗口才可向后移动,即发送方才可以发送后续数据 D2。

在这里插入图片描述

在前面提到的双十一、双十二秒杀场景中,用户流量突增,在这种高并发、大流量的情况下,服务器的处理能力成为电商系统的瓶颈,处理不好就会导致系统崩溃,服务不可用。而分布式系统中的流量控制,就是解决这类问题的一种关键技术。

通俗地说,分布式流量控制就是在分布式系统下,控制每个服务器接收的请求数,以保证服务器来得及处理这些请求,尽可能保证用户请求持续地被处理,而不是让大量的用户请求“阻塞”在服务器中,等待被执行。

分布式系统流量控制策略

消息队列就是实现流量控制的一种方法,通过 一个消息队列来存放用户的消息,然后服务器到消息队列中逐个消费,避免消息过多时服务器处理不过来的情况。

除此之外,分布式系统的流量控制策略还有很多,常用的主要包括两种:漏桶策略和令牌桶策略。

漏桶策略

如下图所示,有一个固定容量的水桶,桶底有一个小洞,水桶可以接收任意速率的水流,但无论水桶里有多少水,水从小洞流出的速率始终不变,桶里的水满了之后,水就会溢出。

在这里插入图片描述

漏桶策略借鉴上述原理,无论用户请求有多少,无论请求速率有多大,“漏桶”都会接收下来,但从漏桶里出来的请求是固定速率的,保证服务器可以处理得游刃有余。当“漏桶”因为容量限制放不下更多的请求时,就会选择丢弃部分请求。这种思路其实就是一种“宽进严出”的策略。

比如,在某段时间内,系统每秒会有 10 个用户发出请求,但这些请求经过漏桶后,每秒始终只流出 2 个请求,服务器每秒最多处理 2 个请求。无论请求速率有多大,都能达到限流的目的,避免服务器在短暂时间内需要处理大量请求,但由于处理能力受限导致系统崩溃,从而保证了系统的高可靠。

优点:做到了流量整形,即无论流量多大,即便是突发的大流量,输出依旧是 一个稳定的流量。

缺点:对于突发流量的情况,因为服务器处理速度与正常流量的处理速度一致,会丢弃比较多的请求。

当突发大流量到来时,服务器最好能够更快地处理用户请求,这也是分布式系统大多数情况下想要达到的效果。漏桶策略适用于间隔性突发流量且流量不用即时处理的场景,可以在流量较小时的“空闲期”,处理大流量时流入漏桶的流量;不适合流量需要即时处理的场景,突发流量时可以放入桶中,但缺乏效率,始终以固定速率进行处理。

漏桶算法已经用于很多框架了,比如阿里开源的流量控制框架 Sentinel 中的匀速排队限流策略,就采用了漏桶算法;分布式追踪系统 Jaeger 中,有一种采集策略是速率限制类型,内部使用的也是漏桶算法等。

令牌桶策略

令牌桶策略指的是桶里放着很多令牌,请求只有拿到令牌才能被服务器处理。

如图所示,有一个固定容量的存放令牌的桶,以固定速率向桶里放入令牌,桶满时会丢弃多出的令牌。每当请求到来时,必须先到桶里取一个令牌才可被服务器处理,只有拿到了令牌的请求才会被服务器处理。可以将令牌理解为门卡,只有拿到了门卡才能顺利进入房间。

在这里插入图片描述

假设,令牌以每秒 3 个的速率放入到令牌桶中,桶的容量为 10。通常情况下, 每秒会有 2 个用户请求,请求到来时就会到桶里取一个令牌,由于请求的速率低于放令牌的速率,因此令牌桶里令牌会逐渐增多,直到达到桶的容量。超过桶容量后,令牌会被丢弃。

当大流量到来时,比如某个时刻来了 10 个请求,此时桶里有 10 个令牌,请求都会被服务器处理;但如果来的请求数不止 10 个,令牌会被取完,多余的请求取不到令牌,也就没办法及时被服务器处理,需要等待令牌。

优点:当有突发大流量时,只要令牌桶里有足够多的令牌,请求就会被迅速执行。通常情况下,令牌桶容量的设置,可以接近服务器处理的极限,可以有效利用服务器的资源。这种策略适用于有突发特性的流量,且流量需要即时处理的场景

在实际使用中,令牌桶算法也很常见。比如,Google 开源工具包 Guava 提供的限流工具类 RateLimiter,就是基于令牌桶算法来完成限流的。

两种策略对比

以上就是漏桶策略和令牌桶策略的核心原理了,接下来我们通过一张表格对比下这两种策略 吧。

Sentinel 流量控制工作原理

Sentinel 的核心是,监控应用的并发线程数或 QPS(请求数 / 每秒)指标,当达到系统设定的阈值时,Sentinel 可以采取一定的策略对流量进行控制,以避免应用被瞬时高流量击垮,从而保证应用高可靠。

在 Sentinel 中,关于流量控制有两种方式:

  • 通过并发线程数进行流量控制,
  • 通过 QPS 指标进行流量控制。

通过并发线程数进行流量控制

过多的线程会消耗非常多的系统资源,包括线程资源消耗、线程调度消耗等。为了解决这个问题,引入了线程池。线程池维护了多个启动着的线程,随时等待着去执行系统分配的任务,系统每次需要处理任务时,可以直接从线程池中取线程,从而避免了创建和销毁线程的时间和资源等消耗。

同一时刻每个线程只能执行一个任务或请求,可以通过并发线程数进行流量控制。

如图所示,假设现在线程池中有 3 个线程,最大并发处理数为 3,现在有 2 个请 求 Q1 和 Q2 到来,由于请求数少于线程数,因此请求可以被并发执行。线程池中启动着的线程 1 和线程 2 会进行相应的处理,而不会创建新线程,线程处理完请求后也不会被销毁,而是回到线程池中继续等待新的请求。但如果现在同时有 4 个请求到来,只有 3 个请求可以被并发处理,而剩下的一个请求要么丢弃,要么等待空闲线程。

在这里插入图片描述

在分布式系统中,每个请求都会由一个线程去进行处理。当请求太多系统处理不过来时,意味着线程池可能已经被耗尽(线程池中无空闲线程),因此当请求过多时,执行请求的并发线程数自然会随之增加,当超过一定的阈值(比如线程池中线程总数)时,需要采取一定的 策略来进行流量控制。

在 Sentinel 中,就采用了直接拒绝的方式,即新来的请求会直接拒绝。

通过 QPS 指标进行流量控制

QPS 是指每秒的请求数,大流量也就意味着 QPS 大。当 QPS 达到阈值时,Sentinel 提供 了三种流量控制策略,分别是直接拒绝、预热(Warm Up)和匀速排队:

  • 直接拒绝:最直接也是最暴力的方式,与并发线程数流量控制采取的方式一致,当 QPS 达到系统设定的阈值时,直接拒绝新来的请求。 这种策略乍一听起来确实不是很好,但对于系统处理能力确切已知的情况(即阈值设定为每秒能接受的最大处理请求数),却非常实用。当请求超出阈值时,可以直接拒绝,因为系统已经没有更多的能力来处理多余的请求了。因此,该策略适用于对系统处理能力确切已知的场景
  • 预热:当系统的 QPS 长期处于一个较低水平时,一旦发生流量骤增,如果直接让系统每秒处理大量的请求,可能会因为服务器处理能力不足,导致系统崩溃。因此 Sentinel 提供了一种“预热”机制,让系统的 QPS 缓慢增加,在一定的时间内逐渐增加到上限。如下图所示,假设通常情况下系统每秒处理 3 个请求,即 QPS=3,当用户请求增加时,系统每秒处理的请求数相应增加,但不会一下子提高很多。比如,每秒增加 1 个处理请求,逐步达到 QPS=10 的处理上限,并不再继续增加,从而避免大流量一下子导致系统故障。
    在这里插入图片描述
    预热这种策略像是一种特殊的令牌桶:放令牌的速率通常保持在一个较低的水平,当流量突增时,放令牌的速率不会一下子提高到最高水平,而是会慢慢增加,直到增加到最大速率则不可再增加。因此,该策略与令牌桶策略的适用场景类似,即适用于具有突发特性的流量,且流量可以即时处理的场景
  • 匀速排队:本质是漏桶策略。它会严格控制系统每秒处理的请求数,请求数很多时,请求之间的间隔也会保持一致。如图所示,当 QPS=5 时,每隔 200ms 才允许服务器处理下一个请求。假设请求队列中有 10 个请求瞬间到达,服务器不会一下子全处理完,而是按照请求的顺序,每 200ms 处理 一个请求,直到处理完所有请求。处理的请求就像是在匀速排队。

在这里插入图片描述
该策略中,系统会设定一个时间间隔 T,假设最大排队时长设置为 6T,上次请求通过的时刻为 t1。当新的请求在 t2 时刻到来的话,则进行判断,首先查看是否还有其他请求在排队。

如果没有请求在排队,分两种情况:

  • 当 t2 - t1 的值大于或等于时间间隔 T,请求可以通过;
  • 当 t2 - t1 的值小于 T 时,需要等待,直到 t2 - t1 的值达到时间间隔 T 时,才可以让请求通过。

如果已经有请求在排队,就需要计算该新请求的预期通过时间。比如,有 3 个请求在排队,则该新请求预期通过时间为 t1+4T,因为需要等到在该请求前面的请求都通过后该请求才可通过,且两个请求通过的时间间隔必须达到 T 才可以。

若排队的请求过多,新来的请求预期等待时间超出最大排队时长,即等待时间超过 6T 时,则直接拒接这个请求。

匀速排队的适用场景与漏桶策略类似,即适用于间隔性突发流量且流量不用即时处理的场景

知识扩展:什么是拥塞控制?它与流量控制的区别是什么?

分布式领域,流量控制:指业务上的流量,即用户请求。

分布式领域,拥塞控制:指网络上传输的数据,即网络上数据传输出现拥塞时应当如何控制。

分布式领域中,这两个概念不是 一回事儿。

但是对于网络上数据的传输而言,流量控制与拥塞控制非常容易混淆。

网络数据传输中,流量控制:指控制发送方和接收方的传输和接收速率在双方都可以接受的范围,通常使用的方法是滑动窗口;

网络数据传输中,拥塞控制:通过检测网络状况,随时疏通网络,避免网络中过多数据堆积,导致无法传输数据,包括慢启动与拥塞避免方法。

总结

在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海陆云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值