Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >注册中心 Eureka 源码解析 —— 基于令牌桶算法的 RateLimiter

注册中心 Eureka 源码解析 —— 基于令牌桶算法的 RateLimiter

作者头像
芋道源码
发布于 2018-08-17 07:30:12
发布于 2018-08-17 07:30:12
1.4K00
代码可运行
举报
文章被收录于专栏:芋道源码1024芋道源码1024
运行总次数:0
代码可运行

摘要: 原创出处 http://www.iocoder.cn/Eureka/rate-limiter/ 「芋道源码」欢迎转载,保留摘要,谢谢!

本文主要基于 Eureka 1.8.X 版本

  • 1. 概述
  • 2. RateLimiter
  • 2.1 refillToken
  • 2.2 consumeToken
  • 3. RateLimitingFilter
  • 4. InstanceInfoReplicator
  • 666. 彩蛋

1. 概述

本文主要分享 RateLimiter 的代码实现和 RateLimiter 在 Eureka 中的应用

推荐 Spring Cloud 书籍

  • 请支持正版。下载盗版,等于主动编写低级 BUG
  • 程序猿DD —— 《Spring Cloud微服务实战》
  • 周立 —— 《Spring Cloud与Docker微服务架构实战》
  • 两书齐买,京东包邮。

推荐 Spring Cloud 视频

  • Java 微服务实践 - Spring Boot
  • Java 微服务实践 - Spring Cloud
  • Java 微服务实践 - Spring Boot / Spring Cloud

2. RateLimiter

com.netflix.discovery.util.RateLimiter ,基于Token Bucket Algorithm ( 令牌桶算法 )的速率限制器。

FROM 《接口限流实践》 令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。

RateLimiter 目前支持分钟级秒级两种速率限制。构造方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class RateLimiter {

    /**
     * 速率单位转换成毫秒
     */
    private final long rateToMsConversion;

    public RateLimiter(TimeUnit averageRateUnit) {
        switch (averageRateUnit) {
            case SECONDS: // 秒级
                rateToMsConversion = 1000;
                break;
            case MINUTES: // 分钟级
                rateToMsConversion = 60 * 1000;
                break;
            default:
                throw new IllegalArgumentException("TimeUnit of " + averageRateUnit + " is not supported");
        }
    }
}
  • averageRateUnit 参数,速率单位。构造方法里将 averageRateUnit 转换成 rateToMsConversion

调用 #acquire(...) 方法,获取令牌,并返回是否获取成功

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// RateLimiter.java
/**
* 获取令牌( Token )
*
* @param burstSize 令牌桶上限
* @param averageRate 令牌再装平均速率
* @return 是否获取成功
*/
public boolean acquire(int burstSize, long averageRate) {
   return acquire(burstSize, averageRate, System.currentTimeMillis());
}

public boolean acquire(int burstSize, long averageRate, long currentTimeMillis) {
   if (burstSize <= 0 || averageRate <= 0) { // Instead of throwing exception, we just let all the traffic go
       return true;
   }

   // 填充 令牌
   refillToken(burstSize, averageRate, currentTimeMillis);
   // 消费 令牌
   return consumeToken(burstSize);
}
  • burstSize 参数 :令牌桶上限。
  • averageRate 参数 :令牌填充平均速率。
  • 我们举个 ? 来理解这两个参数 + 构造方法里的一个参数:
    • averageRateUnit = SECONDS
    • averageRate = 2000
    • burstSize = 10
    • 可获取 2000 个令牌。例如,每秒允许请求 2000 次。
    • 毫秒可填充 2000 / 1000 = 2消耗的令牌。
    • 毫秒可获取 10 个令牌。例如,每毫秒允许请求上限为 10 次,并且请求消耗掉的令牌,需要逐步填充。这里要注意下,虽然每毫秒允许请求上限为 10 次,这是在没有任何令牌被消耗的情况下,实际每秒允许请求依然是 2000 次。
    • 这就是基于令牌桶算法的限流的特点:让流量平稳,而不是瞬间流量。1000 QPS 相对平均的分摊在这一秒内,而不是第 1 ms 999 请求,后面 999 ms 0 请求
  • 从代码上看,#acquire(...) 分成两部分,我们分别解析,整体如下图:

2.1 refillToken

调用 #refillToken(...) 方法,填充已消耗的令牌。可能很多同学开始和我想的一样,一个后台每毫秒执行填充。为什么不适合这样呢?一方面,实际项目里每个接口都会有相应的 RateLimiter ,导致太多执行频率极高的后台任务;另一方面,获取令牌时才计算,多次令牌填充可以合并成一次,减少冗余和无效的计算。

代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1: /**
  2:  * 速率单位转换成毫秒
  3:  */
  4: private final long rateToMsConversion;
  5: 
  6: /**
  7:  * 消耗令牌数
  8:  */
  9: private final AtomicInteger consumedTokens = new AtomicInteger();
 10: /**
 11:  * 最后填充令牌的时间
 12:  */
 13: private final AtomicLong lastRefillTime = new AtomicLong(0);
 14: 
 15: private void refillToken(int burstSize, long averageRate, long currentTimeMillis) {
 16:     // 获得 最后填充令牌的时间
 17:     long refillTime = lastRefillTime.get();
 18:     // 获得 过去多少毫秒
 19:     long timeDelta = currentTimeMillis - refillTime;
 20: 
 21:     // 计算 可填充最大令牌数量
 22:     long newTokens = timeDelta * averageRate / rateToMsConversion;
 23:     if (newTokens > 0) {
 24:         // 计算 新的填充令牌的时间
 25:         long newRefillTime = refillTime == 0
 26:                 ? currentTimeMillis
 27:                 : refillTime + newTokens * rateToMsConversion / averageRate;
 28:         // CAS 保证有且仅有一个线程进入填充
 29:         if (lastRefillTime.compareAndSet(refillTime, newRefillTime)) {
 30:             while (true) { // 死循环,直到成功
 31:                 // 计算 填充令牌后的已消耗令牌数量
 32:                 int currentLevel = consumedTokens.get();
 33:                 int adjustedLevel = Math.min(currentLevel, burstSize); // In case burstSize decreased
 34:                 int newLevel = (int) Math.max(0, adjustedLevel - newTokens);
 35:                 // CAS 避免和正在消费令牌的线程冲突
 36:                 if (consumedTokens.compareAndSet(currentLevel, newLevel)) {
 37:                     return;
 38:                 }
 39:             }
 40:         }
 41:     }
 42: }
  • 第 17 行 :获取最后填充令牌的时间( refillTime ) 。每次填充令牌,会设置 currentTimeMillisrefillTime
  • 第 19 行 :获得距离最后填充令牌的时间差( timeDelta ),用于计算需要填充的令牌数。
  • 第 22 行 :计算可填充的最大令牌数量( newTokens )。newTokens 可能超过 burstSize ,所以下面会有逻辑调整 newTokens
  • 第 25 至 27 行 :计算新的填充令牌的时间。为什么不能用 `currentTimeMillis` 呢?例如,averageRate = 500 &amp;&amp; averageRateUnit = SECONDS 时, 每 2 毫秒才填充一个令牌,如果设置 currentTimeMillis会导致不足以填充一个令牌的时长被吞了
  • 第 29 行 :通过 CAS 保证有且仅有一个线程进入填充逻辑。
  • 第 30 行 :死循环直到成功
  • 第 32 至 34 行 :计算新的填充令牌后的已消耗的令牌数量。
    • 第 33 行 :`burstSize` 可能调小,例如,系统接入分布式配置中心,可以远程调整该数值。如果此时 `burstSize` 更小,以它作为已消耗的令牌数量。
  • 第 36 行 :通过 CAS 保证避免覆盖设置正在消费令牌的线程。

2.2 consumeToken

#refillToken(...) 方法,填充消耗( 获取 )的令牌。

代码如下 :

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1: private boolean consumeToken(int burstSize) {
  2:     while (true) { // 死循环,直到没有令牌,或者获取令牌成功
  3:         // 没有令牌
  4:         int currentLevel = consumedTokens.get();
  5:         if (currentLevel >= burstSize) {
  6:             return false;
  7:         }
  8:         // CAS 避免和正在消费令牌或者填充令牌的线程冲突
  9:         if (consumedTokens.compareAndSet(currentLevel, currentLevel + 1)) {
 10:             return true;
 11:         }
 12:     }
 13: }
  • 第 2 行 :死循环直到没有令牌或者竞争获取令牌成功
  • 第 4 至 7 行 :没有令牌。
  • 第 9 至 11 行 :通过 CAS 避免和正在消费令牌或者填充令牌的线程冲突。

3. RateLimitingFilter

com.netflix.eureka.RateLimitingFilter ,Eureka-Server 限流过滤器。使用 RateLimiting ,保证 Eureka-Server 稳定性。

#doFilter(...) 方法,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1: @Override
  2: public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  3:     // 获得 Target
  4:     Target target = getTarget(request);
  5: 
  6:     // Other Target ,不做限流
  7:     if (target == Target.Other) {
  8:         chain.doFilter(request, response);
  9:         return;
 10:     }
 11: 
 12:     HttpServletRequest httpRequest = (HttpServletRequest) request;
 13:     // 判断是否被限流
 14:     if (isRateLimited(httpRequest, target)) {
 15:         // TODO[0012]:监控相关,跳过
 16:         incrementStats(target);
 17:         // 如果开启限流,返回 503 状态码
 18:         if (serverConfig.isRateLimiterEnabled()) {
 19:             ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
 20:             return;
 21:         }
 22:     }
 23:     chain.doFilter(request, response);
 24: }
  • 第 4 行 :调用 #getTarget() 方法,获取 Target。RateLimitingFilter 只对符合正在表达式 ^./apps(/[^/])?$ 的接口做限流,其中不包含 Eureka-Server 集群批量同步接口。
    • 点击 链接 查看 Target 枚举类代码。
    • 点击 链接 查看 #getTarget(…) 方法代码。
  • 第 14 行 :调用 #isRateLimited(...) 方法,判断是否被限流。代码如下: 1: private boolean isRateLimited(HttpServletRequest request, Target target) { 2: // 判断是否特权应用 3: if (isPrivileged(request)) { 4: logger.debug("Privileged {} request", target); 5: return false; 6: } 7: // 判断是否被超载( 限流 ) 8: if (isOverloaded(target)) { 9: logger.debug("Overloaded {} request; discarding it", target); 10: return true; 11: } 12: logger.debug("{} request admitted", target); 13: return false; 14: }
    • x
    • x
    • 第 3 至 6 行 :调用 #isPrivileged() 方法,判断是否为特权应用,对特权应用不开启限流逻辑。代码如下: private boolean isPrivileged(HttpServletRequest request) { // 是否对标准客户端开启限流 if (serverConfig.isRateLimiterThrottleStandardClients()) { return false; } // 以请求头( "DiscoveryIdentity-Name" ) 判断是否在标准客户端名集合内 Set<String> privilegedClients = serverConfig.getRateLimiterPrivilegedClients(); String clientName = request.getHeader(AbstractEurekaIdentity.AUTH_NAME_HEADER_KEY); return privilegedClients.contains(clientName) || DEFAULT_PRIVILEGED_CLIENTS.contains(clientName); }
    • 第 8 至 11 行 :调用 #isOverloaded(...) 方法,判断是否超载( 限流 )。代码如下: /** * Includes both full and delta fetches. */ private static final RateLimiter registryFetchRateLimiter = new RateLimiter(TimeUnit.SECONDS); /** * Only full registry fetches. */ private static final RateLimiter registryFullFetchRateLimiter = new RateLimiter(TimeUnit.SECONDS); private boolean isOverloaded(Target target) { int maxInWindow = serverConfig.getRateLimiterBurstSize(); // 10 int fetchWindowSize = serverConfig.getRateLimiterRegistryFetchAverageRate(); // 500 boolean overloaded = !registryFetchRateLimiter.acquire(maxInWindow, fetchWindowSize); if (target == Target.FullFetch) { int fullFetchWindowSize = serverConfig.getRateLimiterFullFetchAverageRate(); // 100 overloaded |= !registryFullFetchRateLimiter.acquire(maxInWindow, fullFetchWindowSize); } return overloaded; }
  • 第 18 至 21 行 :若 eureka.rateLimiter.enabled = true( 默认值 :false ,可配 ),返回 503 状态码。

4. InstanceInfoReplicator

com.netflix.discovery.InstanceInfoReplicator ,Eureka-Client 应用实例复制器。在 《Eureka 源码解析 —— 应用实例注册发现(一)之注册》「2.1 应用实例信息复制器」 有详细解析。

应用实例状态发生变化时,调用 #onDemandUpdate() 方法,向 Eureka-Server 发起注册,同步应用实例信息。InstanceInfoReplicator 使用 RateLimiter ,避免状态频繁发生变化,向 Eureka-Server 频繁同步。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class InstanceInfoReplicator implements Runnable {

    /**
     * RateLimiter
     */
    private final RateLimiter rateLimiter;
    /**
     * 令牌桶上限,默认:2
     */
    private final int burstSize;
    /**
     * 令牌再装平均速率,默认:60 * 2 / 30 = 4
     */
    private final int allowedRatePerMinute;

    InstanceInfoReplicator(DiscoveryClient discoveryClient, InstanceInfo instanceInfo, int replicationIntervalSeconds, int burstSize) {
        // ... 省略其他代码

        this.rateLimiter = new RateLimiter(TimeUnit.MINUTES);
        this.replicationIntervalSeconds = replicationIntervalSeconds;
        this.burstSize = burstSize;

        this.allowedRatePerMinute = 60 * this.burstSize / this.replicationIntervalSeconds;
        logger.info("InstanceInfoReplicator onDemand update allowed rate per min is {}", allowedRatePerMinute);
    }

    public boolean onDemandUpdate() {
        if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) { // 限流
            scheduler.submit(new Runnable() {
                @Override
                public void run() {
                    logger.debug("Executing on-demand update of local InstanceInfo");
                    // 取消任务
                    Future latestPeriodic = scheduledPeriodicRef.get();
                    if (latestPeriodic != null && !latestPeriodic.isDone()) {
                        logger.debug("Canceling the latest scheduled update, it will be rescheduled at the end of on demand update");
                        latestPeriodic.cancel(false);
                    }
                    // 再次调用
                    InstanceInfoReplicator.this.run();
                }
            });
            return true;
        } else {
            logger.warn("Ignoring onDemand update due to rate limiter");
            return false;
        }
    }

}
  • #onDemandUpdate() 方法,调用 RateLimiter#acquire(…) 方法,获取令牌。
    • InstanceInfoReplicator 会固定周期检查本地应用实例是否有没向 Eureka-Server ,若未同步,则发起同步。在 《Eureka 源码解析 —— 应用实例注册发现(一)之注册》「2.1 应用实例信息复制器」 有详细解析。
    • Eureka-Client 向 Eureka-Server 心跳时,Eureka-Server 会对比应用实例的 `lastDirtyTimestamp` ,若 Eureka-Client 的更大,则 Eureka-Server 返回 404 状态码。Eureka-Client 接收到 404 状态码后,发起注册同步。在 Eureka 源码解析 —— 应用实例注册发现(二)之续租》「2.2 HeartbeatThread」 有详细解析。
    • 若获取成功,向 Eureka-Server 发起注册,同步应用实例信息。
    • 若获取失败,向 Eureka-Server 发起注册,同步应用实例信息。这样会不会有问题?答案是不会

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 芋道源码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
注册中心 Eureka 源码解析 —— 应用实例注册发现(一)之注册
点击上方“芋道源码”,选择“置顶公众号” 技术文章第一时间送达! 源码精品专栏 中文详细注释的开源项目 Java 并发源码合集 RocketMQ 源码合集 Sharding-JDBC 源码解析合集 Spring MVC 和 Security 源码合集 MyCAT 源码解析合集 本文主要基于 Eureka 1.8.X 版本 1. 概述 2. Eureka-Client 发起注册 2.1 应用实例信息复制器 2.2 刷新应用实例信息 2.3 发起注册应用实例 3. Eureka-Server 接收注册 3.
芋道源码
2018/06/13
2.6K0
java并发编程实战(6) 乐观锁 CAS
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有独占锁. 我们在系列java并发线程实战(1)线程安全和机制原理,已经提到例子,
黄规速
2022/04/14
1.1K0
java并发编程实战(6) 乐观锁 CAS
注册中心 Eureka 源码解析 —— Eureka-Server 启动(一)之 ServerConfig
本文主要基于 Eureka 1.8.X 版本 1. 概述 2. EurekaServerConfig 2.1 类关系图 2.2 配置属性 2.3 DefaultEurekaServerConfig 本文主要分享 Eureka-Server 启动的过程。 考虑到整个初始化的过程中涉及的代码特别多,拆分成两两篇文章: 【本文】ServerConfig EurekaBootStrap 推荐 Spring Cloud 书籍: 请支持正版。下载盗版,等于主动编写低级 BUG 。 程序猿DD —— 《Spring Cl
芋道源码
2018/03/27
8940
注册中心 Eureka 源码解析 —— Eureka-Server 启动(一)之 ServerConfig
注册中心 Eureka 源码解析 —— Eureka-Server 集群同步
Eureka-Server 可以使用直接配置所有节点的服务地址,或者基于 DNS 配置。推荐阅读:《Spring Cloud构建微服务架构(六)高可用服务注册中心》 。
芋道源码
2018/08/17
1.6K0
注册中心 Eureka 源码解析 —— Eureka-Server 集群同步
eureka 原理_什么是swot分析方法
#总结 eureka内部实际上是分为三个实例的,分别是Client,Server和Instance, Eureka-Client启动,创建Instance实例,封装成对象,推送给server,server接收Instance对象,返回实例集合,并签订租约,client定时发动续租请求到server,server维护各个instance实例,服务之间调用不通过eureka。 #Eureka-Client client启动类实例顺序
全栈程序员站长
2022/09/27
7170
eureka 原理_什么是swot分析方法
注册中心 Eureka 源码解析 —— Eureka-Server 启动(二)之 EurekaBootStrap
本文主要基于 Eureka 1.8.X 版本 1. 概述 2. EurekaBootStrap 2.1 初始化 Eureka-Server 配置环境 2.2 初始化 Eureka-Server 上下文 3. Filter 3.1 StatusFilter 3.2 ServerRequestAuthFilter 3.3 RateLimitingFilter 3.4 GzipEncodingEnforcingFilter 3.5 ServletContainer 666. 彩蛋 1. 概述 本文接《Eureka
芋道源码
2018/04/18
1.9K0
注册中心 Eureka 源码解析 —— Eureka-Server 启动(二)之 EurekaBootStrap
注册中心 Eureka 源码解析 —— 应用实例注册发现 (三)之下线
本文主要分享 Eureka-Client 向 Eureka-Server 下线应用实例的过程。
芋道源码
2018/07/31
5790
注册中心 Eureka 源码解析 —— 应用实例注册发现 (三)之下线
使用Guava RateLimiter限流以及源码解析
首先通过RateLimiter.create(1);创建一个限流器,参数代表每秒生成的令牌数,通过limiter.acquire(i);来以阻塞的方式获取令牌,当然也可以通过tryAcquire(int permits, long timeout, TimeUnit unit)来设置等待超时时间的方式获取令牌,如果超timeout为0,则代表非阻塞,获取不到立即返回。
用户6182664
2020/05/08
1.3K0
使用Guava RateLimiter限流以及源码解析
注册中心 Eureka 源码解析 —— 应用实例注册发现(七)之增量获取
本文主要分享 Eureka-Client 向 Eureka-Server 获取增量注册信息的过程。
芋道源码
2018/07/31
9320
注册中心 Eureka 源码解析 —— 应用实例注册发现(七)之增量获取
注册中心 Eureka 源码解析 —— 应用实例注册发现(六)之全量获取
本文主要分享 Eureka-Client 向 Eureka-Server 获取全量注册信息的过程。
芋道源码
2018/07/31
1.2K0
注册中心 Eureka 源码解析 —— 应用实例注册发现(六)之全量获取
注册中心 Eureka 源码解析 —— Eureka-Client 初始化(三)之 EurekaClient
1. 概述 本文接《Eureka 源码解析 —— Eureka-Client 初始化(二)之 EurekaClientConfig》,主要分享 Eureka-Client 自身初始化的过程的第三部分
芋道源码
2018/03/27
3.2K0
注册中心 Eureka 源码解析 —— Eureka-Client 初始化(三)之 EurekaClient
限流技术总结
在开发高并发系统时,有很多手段来保护系统,如缓存、降级、限流等。缓存可以提升系统的访问速度,降级可以暂时屏蔽掉非核心业务,使得核心业务不受影响。限流的目的是通过对并发访问进行限速,一旦达到一定的速率就可以拒绝服务(定向到错误页或告知资源没有了)、排队等待(如秒杀、评论、下单等)、降级(直接返回兜底数据,如商品库存默认有货)。
lyb-geek
2022/03/10
3460
限流技术总结
Guava RateLimiter详解以及源码分析
首先你需要明白限流的概念,在高并发、高流量的场景中,我们的系统有时候会通过限流的手段来防止自己的系统被外部的流量打挂,是一种自我保护措施。
用户7634691
2021/08/12
1.1K0
注册中心 Eureka 源码解析 —— 应用实例注册发现 (二)之续租
本文主要分享 Eureka-Client 向 Eureka-Server 续租应用实例的过程。
芋道源码
2018/07/31
1.1K0
注册中心 Eureka 源码解析 —— 应用实例注册发现 (二)之续租
限速神器RateLimiter源码解析
Tech 导读 在软件系统中,面对高并发的场景,经常需要通过限流来降低系统压力、保护系统不被压垮;另外在交易处理的场景中,也经常因下游要求或其他原因需控制处理速率。RateLimiter是谷歌开源的一款轻巧限流限速组件,简单实用,设计精妙,本文结合示例对其源码进行了相关分析解读,包括代码层级、处理流程、数据流转、计算逻辑等, 希望能够帮助大家了解和使用。
京东技术
2023/08/22
5200
限速神器RateLimiter源码解析
分布式环境下限流方案的实现redis RateLimiter Guava,Token Bucket, Leaky Bucket
对于web应用的限流,光看标题,似乎过于抽象,难以理解,那我们还是以具体的某一个应用场景来引入这个话题吧。在日常生活中,我们肯定收到过不少不少这样的短信,“双11约吗?,千款….”,“您有幸获得唱读卡,赶快戳链接…”。这种类型的短信是属于推广性质的短信。为什么我要说这个呢?听我慢慢道来。一般而言,对于推广营销类短信,它们针对某一群体(譬如注册会员)进行定点推送,有时这个群体的成员量比较大,甚至可以达到千万级别。因此相应的,发送推广短信的量也会增大。然而,要完成这些短信发送,我们是需要调用服务商的接口来完成的。倘若一次发送的量在200万条,而我们的服务商接口每秒能处理的短信发送量有限,只能达到200条每秒。那么这个时候就会产生问题了,我们如何能控制好程序发送短信时的速度昵?于是限流这个功能就得加上了
用户6182664
2020/05/11
5.8K0
常见限流算法及其实现
在分布式系统中,随着业务量的增长,如何保护核心资源、防止系统过载、保证系统的稳定性成为了一个重要的问题。限流算法作为一种有效的流量控制手段,被广泛应用于各类系统中。本文将详细介绍四种常见的限流算法、两种常用的限流器工具,从原理、源码的角度进行分析。
掂过碌蔗啊
2024/03/05
4790
Java实现令牌桶算法:详细讲解与代码示例
摘要 令牌桶算法是一种常见的限流算法,通过为请求分配令牌来限制请求的进入频率,以此来平滑流量。本文面向初学者,将详细介绍令牌桶算法的设计思路,并给出完整的Java代码示例,帮助大家更好地理解和实现令牌桶限流算法。
默 语
2024/11/22
4551
注册中心 Eureka 源码解析 —— 网络通信
本文主要分享 Eureka 的网络通信部分。在不考虑 Eureka 2.x 的兼容的情况下,Eureka 1.x 主要两部分的网络通信:
芋道源码
2018/08/17
8700
注册中心 Eureka 源码解析 —— 网络通信
如何实现漏桶算法与令牌桶算法
Java中对于生产者消费者模型,或者小米手机营销(1分钟卖多少台手机)等都存在限流的思想在里面。
Bug开发工程师
2019/07/13
1.7K0
推荐阅读
相关推荐
注册中心 Eureka 源码解析 —— 应用实例注册发现(一)之注册
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验