注意:特此声明:本文章首发文章在掘金:https://juejin.cn/spost/7329722122657890330,未经允许,请勿进行侵权私自转载。
他强任他强,清风拂山岗。他横任他横,明月照大江。 —九阳真经心法**
文章导航
背景介绍
尽管经过了上一篇文章 《【亿级数据专题】「分布式消息引擎」 盘点本年度我们探索服务的低延迟可用性机制方案实现》有了低延迟的优化保障,消息引擎仍需精心规划其容量。为了提供无与伦比的流畅体验,消息引擎必须实施有效的容量管理策略。
那么,如何在汹涌的流量洪峰面前保持从容不迫?这就需要运用降级、限流和熔断这三大法宝。
三大法宝
正如古语所言,“他强任他强,清风拂山岗;他横任他横,明月照大江。
上面的这句话这正是降级、限流和熔断三大法宝的精髓所在。通过合理的运用,我们便能在流量洪峰面前保持从容不迫,为应用提供稳定、高效的消息服务。
在这三大法宝的运用中,降级尤为关键。在面对突发的流量冲击时,可以通过牺牲一些边缘服务或组件来确保核心服务的稳定运行,从而避免整个系统被击垮。这就像在围棋中丢卒保车,以局部的牺牲换取全局的胜利。
服务“吃不下了”
从架构稳定性的角度来看,即使在资源有限的情况下,所提供的单位时间服务能力也是有限的。一旦超出这个承受能力,可能会导致整个服务的停顿、应用的崩溃,进而将风险传递给服务调用方,甚至可能导致整个系统的服务能力丧失,引发连锁反应。
就像下图中的大胖子一样,他吃了太多的食物,已经达到了极限,最终导致了消化不良。
限流(排队理论)
根据排队理论,随着请求量的不断增加,具有延迟的服务其平均响应时间也会迅速上升。为了确保服务的SLA(服务级别协议),必须对单位时间的请求量进行控制。这正是限流变得愈发重要的原因,在学术界,限流也被称为Traffic Shaping。
漏桶和令牌桶
这个概念最早起源于网络通讯领域,其中典型的算法包括漏桶(leaky bucket)算法和令牌桶(token bucket)算法。通过合理运用这些算法,可以有效控制单位时间的请求量,从而确保服务的稳定性和可用性。
漏桶算法
漏桶算法的核心思想是,有一个模拟的“桶”,它具有特定的容量,并持续地以恒定速率“漏水”。这个漏水的速率可以看作是系统能够处理请求的极限能力。同时,上方源源不断地有“水滴”(代表请求)流入桶中,如同下图:
如果流入桶中的水滴速度过快,超过了漏水的速率,那么桶中的水就会逐渐积累,直至溢出。这种情况就意味着请求过载,系统无法及时处理所有的请求。
算法原理
漏桶算法用于控制单位时间内的请求量,确保系统不会因过多的请求而过载。通过合理地调整漏水的速率,可以有效地管理系统的负载,确保服务的稳定性和可用性。
算法漏洞
虽然漏桶算法在处理请求过载问题上具有一定的作用,但它也存在明显的局限性和不足之处,主要分为以下三个方向:
- 灵活性不足:漏桶算法的速率固定,对于变化的处理需求不够灵活。如果实际请求量超过预设速率,系统无法相应地提高处理能力,可能会导致请求丢失或者服务延迟。
- 漏桶算法缺乏动态调整的能力。在面对负载变化时,它无法根据实时情况自动调整处理速率。
- 难以应对突发请求:漏桶算法通过限制请求速率来防止过载,但对于突发请求的处理可能并不理想。
- 导致短暂时间内的速度无法控制。
- 无法充分利用系统资源:由于漏桶算法的限制性,系统可能无法充分利用可用资源来处理更多的请求。
- 当系统资源有剩余时,漏桶算法无法自动提高处理能力。
由于漏桶算法存在明显的局限性和不足,我们决定引入令牌桶算法。令牌桶算法在处理请求过载问题上更加灵活和有效,能够更好地满足系统需求和提高用户体验。
令牌桶算法(生产者和消费组模式)
令牌桶算法的核心思想是,设置一个令牌桶,令牌以恒定速率添加到桶中。桶内令牌的数量存在上限,每个请求需要获取一个令牌才能被处理。当桶内没有令牌可供获取时,意味着系统已经过载,属于一个典型的生产者和消费组模式。
相比漏桶,令牌桶算法在处理网络流量和请求过载问题时具有更高的灵活性和适应性。
- 处理突发请求:令牌桶算法能够更好地处理突发请求。由于令牌的生成速率可以根据实际情况进行调整,因此能够更好地应对突发请求,避免因突发流量过大而导致系统过载。
- 动态流量控制:令牌桶算法能够根据实时流量情况动态调整令牌的生成速率,实现动态流量控制。这使得系统能够更好地适应流量变化,并充分利用系统资源。
- 可扩展性:令牌桶算法具有较强的可扩展性,可以轻松地应用于大规模分布式系统。通过将流量分配到多个桶中,可以实现流量分流和负载均衡,从而提高系统的可扩展性和可靠性。
- 优先级处理:令牌桶算法可以与优先级队列结合使用,实现优先级处理。通过为不同优先级的请求分配不同的令牌生成速率,可以更好地满足高优先级请求的需求,提高系统的服务质量。
在生产项目中,可以考虑结合其他算法或策略,如动态调整令牌生成速率、引入优先级队列等,以提高系统的响应能力和服务质量。
处理网络流量和请求过载的问题上,无论是漏桶、令牌桶还是它们的变种算法,本质上都是一种速度控制和限流机制。在工程领域,有许多类似的工具和技术,如Guava库中的RateLimiter,Netty框架中的TrafficShaping等,都采用了类似的原理。
并发控制限流
除了速度控制限流,还有一种并发控制限流模式,例如操作系统中的信号量机制以及Java Development Kit (JDK) 中的Semaphore。这些工具和算法的目标都是为了保护系统资源,防止过载,并确保系统的稳定性和可靠性。
在选择合适的限流算法或工具时,需要根据实际应用场景和需求进行权衡。每种算法都有其优点和局限性,适用于不同的场景。深入了解各种算法的原理、特性和适用范围,并根据具体情况进行选择,是实现高效、稳定系统的重要步骤。
成功案例
异步解耦、削峰填谷是消息引擎的核心能力,这正是RocketMQ的设计初衷。
在RPC、应用网关、容器等场景中,流控成为不可或缺的一环,而速度控制更是首选。尽管如此,针对特定场景进行必要的流控仍需细致考量。
- RocketMQ并没有内置如Guava、Netty等现成的流控组件。它采用了一种独特的策略,借鉴了排队理论来处理慢请求。
- RocketMQ通过滑动窗口机制来进行容错处理。通过逐步缩小窗口的方式,降低从服务端拉取的频率和消息大小,从而减轻对服务端的压力。
在处理高频交易和数据复制等关键场景时,RocketMQ选择了快速失败策略作为其核心机制。此策略的主要目的是预防因应用服务连锁反应导致的资源迅速耗尽,进而可能触发的应用雪崩风险。通过这一策略,RocketMQ不仅成功地降低了服务端的负载压力,还为端到端传输提供了坚实的低延迟保障,从而确保了整体系统运行的稳定性和可靠性。
正是基于这样的背景与需求,我们自然过渡到了下一个重要议题:服务降级。
熔断和降级
熔断和降级是应对系统过载的两种常用策略,它们紧密相连,常常一起使用。
降级是一种策略性措施,旨在确保系统的稳定性和可靠性。它通常采用关闭或下线某些非核心服务的方式来减轻系统负载,从而避免整个系统的过载和崩溃。这种策略遵循了二八原则,即少数关键服务得到优先保障,而其他非核心服务则可以暂时牺牲。
熔断是一种保护机制,当系统负载过高时,会自动熔断高负载的组件,避免整个系统崩溃。
降级的Qos指标
在选择降级目标时,主要依据服务QoS的定义。服务QoS定义了服务的可用性、性能、可靠性等方面的要求,是衡量服务质量的重要指标。
通过分析服务QoS,可以确定哪些服务是核心服务,哪些服务是非核心服务,从而有针对性地进行降级操作。
降级处理主要来自于两个方面:用户数据的收集和引擎组件的服务QoS设定。
- 用户数据的收集:可以帮助我们了解系统的实时运行状态和性能表现,从而及时发现潜在的问题和瓶颈。
- 引擎组件的服务:QoS设定则是基于对各个组件的重要性和影响力的评估,确定哪些组件可以承受一定的降级操作。
熔断器机制
当谈到熔断时,我们不禁会想起经典电力系统中的保险丝。在电路中,当负载过大或发生故障时,电流会不断升高。为了避免电流过高可能对电路中的重要器件造成损坏,甚至引发火灾,保险丝会在电流异常升高到一定程度时自动熔断,切断电流,从而保护电路的安全运行。
在分布式系统中,初始状态下系统各组件运行正常,没有出现任何问题。然而,当面临高并发场景时,系统中的某个关键依赖组件可能会因为过载或故障而阻塞。如果这个阻塞状态没有得到及时处理,很可能会引发连锁反应,导致其他组件也相继出现故障,最终形成雪崩效应,系统整体崩溃。
很多时候,刚开始可能只是系统出现了局部、小规模的故障,但由于种种原因,故障影响的范围逐渐扩大,最终导致全局性的后果。而这种过载保护机制,就是我们常说的熔断器(Circuit Breaker)。
为了解决这一问题,Netflix 公司开源了他们的熔断解决方案 Hystrix。Hystrix 作为一个容错管理工具,能够在分布式系统中有效地实施熔断,防止因远程服务调用失败而导致的级联故障。通过熔断机制,系统可以在面临过载或故障时快速响应,降低对其他服务或组件的影响,从而保障系统的稳定性和可靠性。
为了避免这种情况的发生,我们可以引入Hystrix的熔断机制。Hystrix作为一种容错管理工具,能够在系统过载或故障时快速响应,通过熔断机制将系统隔离,避免对其他组件造成影响。当某个关键依赖组件出现问题时,Hystrix会立即切断与其的连接,使应用快速失败,从而避免因连锁反应而导致的最坏情况发生。
较为成熟的熔断技术
通过引入熔断机制,我们可以有效地控制系统的流量,及时发现并处理问题,确保系统的稳定性和可靠性。
Sentinel是阿里巴巴开源的断路器实现,旨在隔离访问远程系统、服务和第三方库的访问点,防止级联故障,从而提高系统的可用性和容错性。它通过添加延迟容忍和容错逻辑来控制这些分布式服务之间的交互。
Hystrix是Netflix开源的延迟和容错库,旨在隔离对远程系统、服务和第三方库的访问,以防止级联故障。通过添加延迟容忍和容错逻辑,Hystrix可以帮助控制这些分布式服务之间的交互,并提高系统的总体弹性。
Resilience4j是一个轻量级的容错库,专门为Java 8和函数式编程设计。它提供了高阶函数(decorators)来增强任何功能接口、lambda表达式或方法引用,包括断路器、速率限制器、重试或隔板。这使得在任何函数接口、lambda表达式或方法引用上都可以堆叠多个装饰器。
Sentinel、Hystrix和Resilience4j都是用于处理分布式系统中的流量控制、熔断和降级等问题的工具,下面是三种熔断技术的对比介绍: