微服务架构下的分布式限流方案全解析

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 微服务架构下的分布式限流方案全解析

1.微服务限流


随着微服务的流行,服务和服务之间的稳定性变得越来越重要。缓存、降级和限流是保护微服务系统运行稳定性的三大利器。


缓存的目的是提升系统访问速度和增大系统能处理的容量,而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开,而有些场景并不能用缓存和降级来解决,比如稀缺资源、数据库的写操作、频繁的复杂查询,因此需有一种手段来限制这些场景的请求量,即限流。


比如当我们设计了一个函数,准备上线,这时候这个函数会消耗一些资源,处理上限是1秒服务3000个QPS,但如果实际情况遇到高于3000的QPS该如何解决呢?


所以限流的目的应当是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率就可以拒绝服务、等待、降级。


学习如何去实现一个分布式限流框架,首先,我们需要去了解最基本的两种限流算法。


2.限流算法


2.1漏桶算法


漏桶算法思路很简单,水(也就是请求)先进入到漏桶里,漏桶以一定的速度出水,当水流入速度过大会直接溢出,然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。示意图(来源网络)如下:


image.png


2.2令牌桶算法


令牌桶算法和漏桶算法效果一样但方向相反的算法,更加容易理解。随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入令牌(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了。新请求来临时,会各自拿走一个令牌,如果没有令牌可拿了就阻塞或者拒绝服务。示意图(来源网络)如下:


image.png



2.3算法选择


漏桶算法与令牌桶算法的区别在于,漏桶算法能够强行限制数据的传输速率,令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发情况。令牌桶还有一个好处是可以方便的改变速度。一旦需要提高速率,则按需提高放入桶中的令牌的速率。所以,限流框架的核心算法还是以令牌桶算法为主。


3.本地限流


已知上面讲述的令牌桶算法的原理,如何通过代码实现?

本地限流的实现可以用Long长整型作为令牌桶,为了达到无锁,建议使用Long的原子类型AtomicLong,使用AtomicLong的好处就是可以非常方便的对其进行CAS加操作与CAS减操作(也就是令牌桶令牌的放入与拿取),以避免线程的上下文切换的开销,核心CAS算法如下:


private boolean tryAcquireFailed() {
   long l = bucket.longValue();
   while (l > 0) {
      if (bucket.compareAndSet(l, l - 1)) {
          return true;
      }
      l = bucket.longValue();
   }
   return false;
}


根据上述了解的令牌桶算法可以得知,令牌桶需要一个ScheduledThread不断的放入令牌,这部分的代码如下:


ScheduledThreadExecutor.scheduleAtFixedRate(() -> 
    bucket.set(rule.getLimit()), rule.getInitialDelay(), rule.getPeriod(), rule.getUnit()
);


4.分布式限流概述


分布式限流需要解决什么问题呢?我想至少有下面几个:


1.动态规则:比如限流的QPS我们希望可以动态修改,限流的功能可以随时开启、关闭,限流的规则可以跟随业务进行动态变更等。


2.集群限流:比如对Spring Cloud微服务架构中的某服务下的所有实例进行统一限流,以控制后续访问数据库的流量。


3.熔断降级:比如在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。


可选的其它几个功能,诸如实时监控数据、网关流控、热点参数限流、系统自适应限流、黑白名单控制、注解支持等,这些功能其实可以非常方便的进行扩展。


5.分布式限流方案


分布式限流的思想我列举下面三个方案:


1.Redis令牌桶


这种方案是最简单的一种集群限流思想。在本地限流中,我们使用Long的原子类作令牌桶,当实例数量超过1,我们就考虑将Redis用作公共内存区域,进行读写。涉及到的并发控制,也可以使用Redis实现分布式锁。


方案的缺点显而易见,每取一次令牌都会进行一次网络开销,而网络开销起码是毫秒级,所以这种方案支持的并发量是非常有限的。


2.QPS统一分配


这种方案的思想是将集群限流最大程度的本地化。


举个例子,我们有两台服务器实例,对应的是同一个应用程序(Application.name相同),程序中设置的QPS为100,将应用程序与同一个控制台程序进行连接,控制台端依据应用的实例数量将QPS进行均分,动态设置每个实例的QPS为50,若是遇到两个服务器的配置并不相同,在负载均衡层的就已经根据服务器的优劣对流量进行分配,例如一台分配70%流量,另一台分配30%的流量。面对这种情况,控制台也可以对其实行加权分配QPS的策略。


客观来说,这是一种集群限流的实现方案,但依旧存在不小的问题。该模式的分配比例是建立在大数据流量下的趋势进行分配,实际情况中可能并不是严格的五五分或三七分,误差不可控,极容易出现用户连续访问某一台服务器遇到请求驳回而另一台服务器此刻空闲流量充足的尴尬情况。


3.发票服务器


这种方案的思想是建立在Redis令牌桶方案的基础之上的。如何解决每次取令牌都伴随一次网络开销,该方案的解决方法是建立一层控制端,利用该控制端与Redis令牌桶进行交互,只有当客户端的剩余令牌数不足时,客户端才向该控制层取令牌并且每次取一批。


这种思想类似于Java集合框架的数组扩容,设置一个阈值,只有当超过该临界值时,才会触发异步调用。其余存取令牌的操作与本地限流无二。虽然该方案依旧存在误差,但误差最大也就一批次令牌数而已。


6.开源项目


上面说了三种分布式限流方案的实现思路,这里推荐一个基于发票服务器思想实现的分布式限流项目SnowJean(https://github.com/yueshutong/SnowJena)。


笔者通过该项目源码观察到该限流项目在解决分布式限流上的有很多巧妙的点,比如,SnowJean内部使用观察者模式实现动态规则配置,使用工厂模式实现限流器的构造,使用建造者模式构建限流规则。


在解决如何对客户端实例的健康状况进行检查时,利用的是Redis的过期时间与客户端发送的心跳包(发送心跳时再进行延期)。比较不错的一点是,该项目提供基于前端Echarts图表的QPS视图展示,如下图。



image.png


相关文章
|
15小时前
|
监控 负载均衡 持续交付
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第5天】在数字化转型的浪潮中,微服务架构以其灵活性、可扩展性和容错性成为企业追求的技术典范。本文深入探讨了微服务的核心组件、设计原则和实施策略,旨在为后端开发者提供构建和维护高效微服务系统的实用指南。通过分析微服务的最佳实践和常见陷阱,我们揭示了如何优化系统性能、保证服务的高可用性以及如何处理分布式系统中的复杂性。
|
18小时前
|
缓存 NoSQL Java
构建高性能微服务架构:Java后端的实践之路
【5月更文挑战第5天】在当今快速迭代和高并发需求的软件开发领域,微服务架构因其灵活性、可扩展性而受到青睐。本文将深入探讨如何在Java后端环境中构建一个高性能的微服务系统,涵盖关键的设计原则、常用的框架选择以及性能优化技巧。我们将重点讨论如何通过合理的服务划分、高效的数据存储策略、智能的缓存机制以及有效的负载均衡技术来提升整体系统的响应速度和处理能力。
|
19小时前
|
监控 持续交付 数据库
构建高效可靠的微服务架构:策略与实践
【5月更文挑战第5天】 在当今快速发展的软件开发领域,微服务架构已成为构建可扩展、灵活且容错的系统的首选模式。本文将探讨如何通过一系列经过验证的策略和最佳实践来构建一个高效且可靠的微服务系统。我们将深入分析微服务设计的核心原则,包括服务的细粒度划分、通信机制、数据一致性以及容错处理,并讨论如何利用现代技术栈来实现这些目标。文章将提供一套综合指南,旨在帮助开发者和架构师在保证系统性能的同时,确保系统的稳健性。
11 4
|
20小时前
|
负载均衡 Java 数据库
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第5天】在现代软件开发中,微服务架构已经成为一种流行的设计模式。它通过将大型应用程序分解为一组小型、松散耦合的服务来提高可维护性、可扩展性和敏捷性。本文将探讨如何构建高效的微服务架构,包括选择合适的技术栈、设计良好的服务接口、确保数据一致性以及实现高可用性和负载均衡。
|
1天前
|
Kubernetes 监控 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【5月更文挑战第4天】在现代软件开发中,微服务架构已成为实现可扩展、灵活且独立部署服务的流行解决方案。本文将探讨如何利用Docker容器化技术和Kubernetes容器编排平台来构建一个高效的微服务系统。我们将分析Docker和Kubernetes的核心优势,并指导读者如何通过这些工具优化微服务部署、管理和扩展过程。文章还将涉及监控和日志管理策略,以确保系统的健壮性和可靠性。
|
1天前
|
监控 Java 持续交付
构建高效微服务架构:后端开发者的终极指南
【5月更文挑战第4天】在当今快速迭代和竞争激烈的软件市场中,微服务架构已成为企业追求敏捷性、可扩展性和技术多样性的关键策略。本文深入探讨了如何构建和维护高效的微服务系统,从基本概念到高级实践,为后端开发者提供一套综合指南,以支持他们在这一变革性架构风格中扮演关键角色。
|
1天前
|
负载均衡 API 数据库
构建高效微服务架构的五大关键技术
【5月更文挑战第4天】 随着云计算和容器化技术的成熟,微服务架构已成为软件开发的主流模式。本文将详细探讨实现高效微服务架构的五个关键技术点:服务拆分策略、API网关设计、服务发现与注册、熔断机制以及分布式事务管理。这些技术点是确保微服务系统可扩展性、灵活性及稳定性的基石,对于后端开发者而言,掌握它们至关重要。文章将提供具体的实施建议和最佳实践,帮助读者构建和维护高性能的微服务系统。
|
2天前
|
JavaScript Java 持续交付
构建高效微服务架构:后端开发的新范式
【5月更文挑战第3天】 在现代软件开发的浪潮中,微服务架构以其灵活性、可扩展性和技术多样性而受到重视。本文深入探讨了如何构建一个高效的微服务系统,包括关键的设计原则、技术选型、以及实现细节。我们将通过分析微服务的核心概念,提供一套实用的步骤和最佳实践,以指导开发者构建出既健壮又易于维护的分布式系统。文章将重点讨论如何在保证系统性能和稳定性的前提下,实现服务的解耦与独立部署,从而推动后端开发工作流的优化和创新。
|
2天前
|
安全 数据管理 持续交付
构建高效微服务架构的五大核心策略
【5月更文挑战第3天】在当前软件开发领域,微服务架构已成为一种流行的设计模式,它通过将应用程序拆分成一组小型、松耦合的服务来提高系统的可维护性和扩展性。本文将详细探讨构建高效微服务架构的五大核心策略,包括服务划分原则、通信机制设计、数据管理、安全性考虑以及持续集成与部署。这些策略不仅有助于确保系统的高可用性和灵活性,同时也支持快速迭代和部署,是实现现代云原生应用的基石。
|
3天前
|
Kubernetes API 开发者
构建高效微服务架构:后端开发的新范式
【5月更文挑战第2天】 随着现代软件开发的演进,传统的单体应用已难以满足快速变化的业务需求和敏捷开发的挑战。本文探讨了如何通过构建高效的微服务架构来提升后端开发的灵活性、可维护性和扩展性。我们将深入分析微服务的核心组件,包括服务拆分、容器化、API网关和持续集成/持续部署(CI/CD)等关键技术,并讨论它们如何共同作用以支持复杂的业务场景和云原生应用的需求。
13 1

推荐镜像

更多