流量洪峰下的交通指挥家:详解负载均衡与限流实战

负载均衡:聪明的交通指挥家

如果说水平扩容是为系统增加了更多的"工作车道",那么负载均衡就是站在车道入口处的交通指挥家。它的存在,是为了回答一个根本性问题:当成千上万的请求同时涌来时,如何将它们高效、公平且智能地引导至后端的服务集群,从而避免任何一条"车道"因拥堵而瘫痪?

负载均衡的本质,是将单一的、巨大的访问压力,分解为多个可管理的、微小的压力。负载均衡不仅需要在用户请求和Web服务器之间进行,而且在系统的每个阶段都必须进行。一个中等规模的系统可能在以下三个层面实现负载均衡。

1)用户请求到Web服务器;

2)Web服务器到内部平台层;

3)内部平台层到数据存储层。

负载均衡可以通过硬件或软件来实现。硬件负载均衡器,如F5 BIG-IP等专用硬件设备,通常被用于处理高流量的网站和网络,但其价格通常较高。相比之下,软件负载均衡器,如LVS(Linux Virtual Server)和Nginx,不仅价格更为低廉,而且提供了更高的灵活性,可以根据具体需求进行定制和调整,以满足各种不同的业务场景。对于大多数系统,建议从软件负载均衡器开始,只有在明确需要的情况下,才考虑转向硬件负载均衡器。

负载均衡算法

负载均衡器在将请求转发到后端服务器之前会考虑两个因素。首先,它会确保所选择的服务器能够适当地响应请求,然后使用预先配置的算法从一组正常的服务器中选择一个。

负载均衡器应该只将流量转发到"正常"的服务节点。为了监视服务器的运行状况,负载均衡器会定期进行运行状况检查(Health Check),尝试连接到服务器,以确保服务节点正在正常运行。如果某个服务节点未通过运行状况检查,它将自动从服务器池中删除,并且在它再次通过运行状况检查之前,负载均衡器不会将流量转发给它。

在负载均衡中,有各种各样的方法和算法,这些算法可以根据服务器的性能、负载情况、会话保持需求等因素来进行选择。以下是一些常见的负载均衡算法。

1)轮询(Round Robin):这是最简单也最经典的策略。它像发牌一样,按顺序将请求逐一分发给每台服务器。这种方式纯粹、公平,但略显"天真"------它假设所有服务器的处理能力完全相同,且每个请求的耗时也一样,这在现实世界中几乎不可能。

2)最少连接(Least Connections): 这是最常用的动态算法。它会把新请求发送给当前连接数最少的服务器。这好比在超市结账时,总会下意识地选择排队人数最少的那个收银台,因为它大概率最快。

3)加权算法(Weighted Algorithms):当服务器配置高低不一时,加权算法便派上用场。可以为性能更强的服务器分配更高的"权重",让它承担更多的流量,实现"能者多劳",最大化利用硬件投资。

4)会话保持(Session Persistence / Sticky Sessions):在某些场景下(如网上银行、购物车),需要用户的连续请求始终由同一台服务器处理,以维持会话状态。此时,负载均衡器会根据用户的IP地址或Cookie等信息,实现"粘性会话",确保用户的请求"粘"在固定的服务器上。

限流:给流量装上调节阀

无论系统多么强大,短时间内的流量突增总是令人头疼的问题,因此,对于并发系统来说,一个必不可少的模块就是限流(Rate Limiter)。

限流是一种通过控制请求的频率或数量来保护系统免受过载的技术,确保系统能够在可接受的范围内处理请求,避免过多的请求导致系统资源耗尽、性能下降或崩溃。

常见的限流算法包括固定窗口、滑动窗口、漏桶、令牌桶。

固定窗口

固定窗口(Fixed Window)算法是最简单的限流算法。其原理是在一个固定的时间窗口内(每个时间单位)限制请求的数量。

固定窗口的缺点是无法平滑地处理突发流量。例如,如果阈值为5个请求,时间窗口的时间单位为1秒,在0.8秒到1秒和1秒到1.2秒分别有5个并发请求,尽管它们都没有超过阈值,但当计算0.8秒到1.2秒内的请求时,并发数高达10,已经超过了每个时间单位不超过5个请求的定义。

滑动窗口

因此,可以引入滑动窗口(Sliding Window)算法来解决关键时间窗口转换的问题。滑动窗口是将一个较大的时间窗口分割成几个粒度更细的子窗口。每个子窗口独立计数,并基于子窗口的时间滑动进行限流控制。当滑动窗口具有更多的网格周期时,滑动窗口的滚动将更加平滑,限流统计将更加准确。

假设每单位时间仍然是1秒,滑动窗口算法将其划分为5个小周期,即滑动窗口(每单位时间)被划分为5个小格子。每个格子代表0.2秒。在每个0.2秒内,时间窗口会向右滑动一个格子。然后,每个小周期都有其独立的计数器。如果请求在0.83秒到达,那么在0.8秒到1.0秒格子内的对应计数器将增加1。

假设在1秒内的阈值仍然是5个请求,0.8秒到1.0秒内到达5个请求(例如0.9秒),它们将落入黄色的格子。

在1.0秒的格子之后,又有5个请求到达并落入紫色的格子。如果是固定窗口算法,它将不会被限制。然而,如果是滑动窗口算法,每次经过一个小周期,它就会向右滑动一个格子。在1.0秒的格子之后,它会向右滑动一个格子。当前的每单位时间周期是0.2秒到1.2秒。在这个区域内的请求已经超过了5个的阈值,当前的限流已经被触发。实际上,紫色格子内的所有请求都已被拒绝。

漏桶

漏桶(Leaky Bucket)算法是一种基于输出流速进行流量控制的方法。这个算法的名字来源于它的工作原理,就像一个漏水的桶一样。

在漏桶算法中,可以将数据想象成水滴,而漏桶就是一个有固定容量的桶。请求(水滴)以任何速率进入桶中,而桶(漏桶)以固定的速率将请求(水)释放出去。如果进入的请求(水滴)过多,超过了桶的容量,那么多余的请求(水)就会被丢弃。

漏桶算法适用于需要强制执行固定速率处理的场景,如网络流量控制、API请求限制等。即使输入数据的速率有波动,漏桶算法也可以通过丢弃多余的数据来防止系统过载。

然而,面对突发流量时,漏桶算法仍然以规律的方式处理请求,这并不是希望看到的。当流量突然增加时,希望系统能尽快处理请求,以提高用户体验。

令牌桶

令牌桶(Token Bucket)算法是一种基于输入流量速率进行流量控制的方法。该算法维护一个具有固定容量的令牌桶,并且每秒向令牌桶中放入一定数量的令牌。当请求到来时,如果令牌桶中的令牌数量足够,那么请求将被允许通过,并从令牌桶中消耗一个令牌。否则,请求将被拒绝。

令牌桶算法通常用于保护系统,通过限制调用者的请求速率来防止系统面临突发流量的压力。如果系统的实际处理能力大于配置的流量限制,那么可能会允许一定程度的流量突发,使得实际处理速率高于配置的速率,从而充分利用系统资源。

使用场景

固定窗口:在一个电商网站中,为了防止恶意刷单,希望对每个用户每分钟的下单次数进行限制。通过使用固定窗口算法,例如设置每分钟只能下单5次,以确保订单减少的合理性。

滑动窗口:在一个API服务中,希望平滑地控制请求的频率。通过滑动窗口算法,例如限制每秒最多处理10个请求,且每个请求必须均匀分布在连续的1秒窗口内。

漏桶:在一个消息推送服务中,希望消息的发送速度是恒定的。通过使用漏桶算法,可以控制消息的发送速率,确保发送速度是恒定的,不会超过系统的处理能力。

令牌桶:在一个视频网站中,希望限制用户的平均下载速度,同时又希望能够应对突发的下载需求。通过使用令牌桶算法,可以设置每个用户的下载速度上限,并在令牌桶中存储一定数量的令牌。用户每下载一个视频,需要消耗一个令牌,当令牌桶中的令牌不足时,用户需要等待令牌生成或下载速度受限。

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦!!!

相关推荐
星辰_mya18 小时前
限流、漏斗桶和令牌桶的区别
java·开发语言·面试·架构·高并发
东南门吹雪2 天前
JAVA TCP socket编程框架
java·高并发·socket·tcp·nio
YYYing.4 天前
【C++大型项目之高性能服务器框架 (一) 】一切物语的开始:日志系统&配置系统篇
服务器·高并发·高性能·c/c++·后端框架
梦想的颜色5 天前
Kafka内核解密:架构拓扑、数据流转与生产消费模型的深度剖析
kafka·高并发·多线程·异步·消息组件·生产者与消费者模式
梦想的颜色8 天前
Redis数据类型全解析:从底层原理到生产实战
运维·数据库·redis·缓存·高并发·分布式锁·数据类型
Java爱好狂.10 天前
Java高并发系统架构设计核心技术开源!
java·高并发·并发编程·java面试·java面试题·java程序员·java八股文
我心飞翔@坚持不懈15 天前
高并发高可用电商平台交易架构实战(避坑)指南
高并发·架构设计·高可用·分布式系统·电商架构·架构避坑
better_liang18 天前
每日Java面试场景题知识点之-分布式秒杀系统的设计
java·redis·分布式·消息队列·高并发·秒杀系统·限流降级
梵得儿SHI18 天前
SpringCloud 进阶拓展:性能优化指南(缓存三大问题 + 分库分表入门)
spring cloud·缓存·微服务·性能优化·高并发·分库分表·数据库优化
梵得儿SHI24 天前
Java IO 流进阶:Buffer 与 Channel 核心概念解析及与传统 IO 的本质区别
java·开发语言·高并发·nio·channel·buffer·提升io效率