【Java限流算法详解及实现】

news2024/11/17 5:28:18

Java限流算法详解及实现

在高并发场景下,限流是保护系统的重要手段。限流算法可以帮助我们在流量过大时进行合理的控制,避免系统崩溃。本文将详细介绍几种常见的限流算法及其在Java中的实现。

Java限流算法详解及实现

  • Java限流算法详解及实现
    • 一、令牌桶算法(Token Bucket)
      • 理论介绍
      • 实现步骤
      • 代码实现
    • 二、漏桶算法(Leaky Bucket)
      • 理论介绍
      • 实现步骤
      • 代码实现
    • 三、计数器算法(Counter)
      • 理论介绍
      • 实现步骤
      • 代码实现
    • 四、滑动窗口算法(Sliding Window)
      • 理论介绍
      • 实现步骤
      • 代码实现
    • 结论

一、令牌桶算法(Token Bucket)

理论介绍

令牌桶算法是一个常用于网络流量整形和流量控制的算法。它的工作原理是系统以固定的速率生成令牌,并将其放入令牌桶中。当请求到来时,需要从桶中取出一定数量的令牌才能继续处理请求。如果桶中没有足够的令牌,则请求会被拒绝或等待。

实现步骤

  1. 初始化一个令牌桶,设置桶的容量和令牌生成速率。
  2. 定时向令牌桶中添加令牌,但不能超过桶的最大容量。
  3. 当请求到来时,检查桶中是否有足够的令牌:
    • 如果有足够的令牌,则允许请求,并从桶中取出相应数量的令牌。
    • 如果没有足够的令牌,则拒绝请求或让请求等待。

代码实现

import java.util.concurrent.atomic.AtomicLong;

public class TokenBucket {
    private final long capacity;
    private final long refillRate;
    private AtomicLong tokens;
    private long lastRefillTimestamp;

    public TokenBucket(long capacity, long refillRate) {
        this.capacity = capacity;
        this.refillRate = refillRate;
        this.tokens = new AtomicLong(capacity);
        this.lastRefillTimestamp = System.nanoTime();
    }

    public synchronized boolean tryConsume(long numTokens) {
        refill();
        if (tokens.get() >= numTokens) {
            tokens.addAndGet(-numTokens);
            return true;
        }
        return false;
    }

    private void refill() {
        long now = System.nanoTime();
        long tokensToAdd = (now - lastRefillTimestamp) * refillRate / 1_000_000_000;
        if (tokensToAdd > 0) {
            tokens.getAndAdd(Math.min(tokensToAdd, capacity - tokens.get()));
            lastRefillTimestamp = now;
        }
    }
}

令牌桶

二、漏桶算法(Leaky Bucket)

理论介绍

漏桶算法也是一种常用的流量整形和流量控制算法。它的工作原理是系统将请求放入一个漏桶中,桶以固定的速率漏水(处理请求)。当桶满时,新的请求将被丢弃。

实现步骤

  1. 初始化一个漏桶,设置桶的容量和漏水速率。
  2. 定时以固定速率从漏桶中漏水(处理请求)。
  3. 当请求到来时,检查漏桶是否已满:
    • 如果未满,则将请求放入桶中。
    • 如果已满,则拒绝请求。

代码实现

import java.util.concurrent.LinkedBlockingQueue;

public class LeakyBucket {
    private final int capacity;
    private final long leakRate;
    private final LinkedBlockingQueue<Long> bucket;
    private long lastLeakTimestamp;

    public LeakyBucket(int capacity, long leakRate) {
        this.capacity = capacity;
        this.leakRate = leakRate;
        this.bucket = new LinkedBlockingQueue<>(capacity);
        this.lastLeakTimestamp = System.nanoTime();
    }

    public synchronized boolean tryConsume() {
        leak();
        if (bucket.remainingCapacity() > 0) {
            bucket.offer(System.nanoTime());
            return true;
        }
        return false;
    }

    private void leak() {
        long now = System.nanoTime();
        long numLeaks = (now - lastLeakTimestamp) * leakRate / 1_000_000_000;
        for (long i = 0; i < numLeaks && !bucket.isEmpty(); i++) {
            bucket.poll();
        }
        lastLeakTimestamp = now;
    }
}

漏桶

三、计数器算法(Counter)

理论介绍

计数器算法是最简单的限流算法。它在一个固定时间窗口内计数请求数量,如果请求数量超过限制,则拒绝请求。

实现步骤

  1. 设置一个时间窗口和请求上限。
  2. 在时间窗口内计数请求数量。
  3. 当请求数量超过上限时,拒绝请求。
  4. 在新时间窗口开始时重置计数器。

代码实现

import java.util.concurrent.atomic.AtomicInteger;

public class CounterLimiter {
    private final int limit;
    private final long interval;
    private AtomicInteger counter;
    private long startTime;

    public CounterLimiter(int limit, long interval) {
        this.limit = limit;
        this.interval = interval;
        this.counter = new AtomicInteger(0);
        this.startTime = System.nanoTime();
    }

    public synchronized boolean tryConsume() {
        long now = System.nanoTime();
        if (now - startTime > interval) {
            counter.set(0);
            startTime = now;
        }
        if (counter.incrementAndGet() <= limit) {
            return true;
        }
        return false;
    }
}

计数器算法

四、滑动窗口算法(Sliding Window)

理论介绍

滑动窗口算法改进了计数器算法,通过使用多个小窗口来统计请求数量,从而更加准确地反映瞬时流量。

实现步骤

  1. 将时间窗口分成多个小窗口。
  2. 在每个小窗口内计数请求数量。
  3. 滑动窗口在新请求到来时更新,计算总请求数量。
  4. 如果总请求数量超过限制,则拒绝请求。

代码实现

import java.util.LinkedList;
import java.util.Queue;

public class SlidingWindowLimiter {
    private final int limit;
    private final long windowSize;
    private final Queue<Long> timestamps;

    public SlidingWindowLimiter(int limit, long windowSize) {
        this.limit = limit;
        this.windowSize = windowSize;
        this.timestamps = new LinkedList<>();
    }

    public synchronized boolean tryConsume() {
        long now = System.nanoTime();
        long boundary = now - windowSize;
        while (!timestamps.isEmpty() && timestamps.peek() < boundary) {
            timestamps.poll();
        }
        if (timestamps.size() < limit) {
            timestamps.offer(now);
            return true;
        }
        return false;
    }
}

滑动窗口算法

结论

限流算法在高并发系统中至关重要。通过合理地选择和实现限流算法,我们可以有效地保护系统免受流量突增的冲击。希望本文对大家理解和实现限流算法有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1700440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 深入系统源码探讨 Activity、Window 和 View 的关系与实践

文章目录 1、概括2、Android Window 设计2.1、Window 类2.2、PhoneWindow2.3、WindowManager2.4、ViewRootImpl2.5、DecorView 3、Android Activity 设计3.1、Activity的基本概念3.2.、Activity的生命周期3.3、Activity的内部结构 4、Android View 设计4.1、View的基本概念4.2、…

构建智慧城市公共服务系统的功能架构设计

随着城市化进程的加速&#xff0c;城市公共服务系统在保障居民生活品质、提升城市管理水平方面扮演着愈发重要的角色。构建智慧城市公共服务系统的功能架构设计至关重要&#xff0c;它不仅需要充分考虑居民需求与城市管理的实际情况&#xff0c;还需要整合先进的科技手段&#…

vue3快速入门(局部使用)

目录 前置知识JavaScript-导入导出 入门操作 变量渲染页面 局部使用vue的实现步骤 vue指令 v-for v-bind v-if v-show v-on v-model 生命周期 前置知识JavaScript-导入导出 正常情况在html导入js文件是全部导入&#xff0c;这样会导致性能上的损失 。 JS提供的…

Docker之xfs文件系统下安装报错解决方案

一、需求说明 centos系统下安装docker最新版的时候&#xff0c;安装成功&#xff0c;启动的时候报错。报错信息“failed to start daemon: error initializing graphdriver: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorr…

5.26机器人基础-DH参数 正解

1.建立DH坐标系 1.确定Zi轴&#xff08;关节轴&#xff09; 2.确定基础坐标系 3.确定Xi方向&#xff08;垂直于zi和zi1的平面&#xff09; 4.完全确定各个坐标系 例子&#xff1a; 坐标系的布局是由个人决定的&#xff0c;可以有不同的选择 标准坐标系布局&#xff1a; …

NDIS协议驱动(一)

Microsoft Windows 操作系统使用基于 1978 年国际标准化组织 (ISO) 开发的七层网络模型的网络体系结构。 ISO 开放系统互连 (OSI) 参考模型将网络描述为“一系列协议层&#xff0c;具有分配给每个层的一组特定函数。 每个层都向更高层提供特定的服务&#xff0c;同时阻止这些层…

vscode:如何解决”检测到include错误,请更新includePath“

vscode:如何解决”检测到include错误&#xff0c;请更新includePath“ 前言解决办法1 获取includePath路径2 将includePath路径添加到指定文件3 保存 前言 配置vscode是出现如下错误&#xff1a; 解决办法 1 获取includePath路径 通过cmd打开终端&#xff0c;输入如下指令&a…

有个小伙把 MyBatis 替换成 MyBatis-Plus,上线后就被开了!!

MyBatis-Plus 替换 MyBatis 首先&#xff0c;我们准备了一张名为 tbl_order 的表&#xff0c;并初始化了其中的两条数据。 DROP TABLE IF EXISTS tbl_order; CREATE TABLE tbl_order (id bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 自增主键,order_no varchar(50)…

云易办springboot+vue后端

springbootvue云易办后端项目完成 一.创建项目 创建父项目&#xff1a;yeb&#xff0c; 使用spring Initializr&#xff0c;完成创建之后删除无用文件夹&#xff0c;作为父项目 添加packaging <packaging>pom</packaging>二.创建子模块&#xff1a;yeb-server …

这或许是国产游戏出海的最佳时机

《刺客信条&#xff1a;影》过于政治正确的选角激怒了全球玩家&#xff0c;而社交媒体上有玩家讨论育碧是否应该因为刻意加入DEI&#xff08;多元化&#xff09;而延期《刺客信条&#xff1a;影》时&#xff0c;没想到这得到了X拥有人埃隆马斯克的回复。马斯克表示“DEI&#x…

内网穿透实现公网访问自己搭建的Ollma架构的AI服务器

内网穿透实现公网访问自己搭建的Ollma架构的AI服务器 [2024年5月9号我发布一个博文关于搭建本地AI服务器的博文][https://blog.csdn.net/weixin_41905135/article/details/138588043?spm1001.2014.3001.5501]&#xff0c;今天我们内网穿透实现从公网访问我的本地AI服务器&…

【深度学习】最强算法之:人工神经网络(ANN)

人工神经网络ANN 1、引言2、人工神经网络(ANN)2.1 定义2.1.1 定义2.1.2 应用场景 2.2 核心原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c;看新闻没&#xff1f; 小鱼&#xff1a;新闻天天看&#xff0c;啥事大惊小怪的。 小屌…

C++干货 --类和对象(二)

前言&#xff1a; 上文中&#xff0c;我们介绍了类这一重要知识点&#xff0c;包括为什么要有类、类的使用方法、封装、以及对象实例化。详情可以去看我的文章&#xff1a;写文章-CSDN创作中心C干货 --类和对象(一)-CSDN博客写文章-CSDN创作中心 这篇文章&#xff0c;我们简单…

全球点赞最高的人颜廷利:真正的人生目标是什么

在那个充满生机的2024年春天&#xff0c;记者有幸对中国第一起名大师的老师颜廷利教授进行了深入的访谈。带着对其人生哲学的强烈好奇&#xff0c;记者紧张而期待地提出了问题&#xff1a;“颜教授&#xff0c;您在漫长的人生旅途中最追求的是什么&#xff1f;” 宁夏银川、山东…

【模拟面试问答】深入解析力扣163题:缺失的区间(线性扫描与双指针法详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

文盘Rust -- 生命周期问题引发的 static hashmap 锁

100编程书屋_孔夫子旧书网 2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了。项目地址:https://github.com/jiashiwen/interactcli-rs。 春节以前看到axum已经0.4.x了,于是想看看能不能用rust做个服务端的框架。 春节…

C++的哈希 哈希表 哈希桶

目录 Unordered系列关联式容器 什么是哈希 哈希表 闭散列 载荷因子α 扩容 查找 删除 字符串哈希算法 最终代码 开散列 插入 查找 删除 最终代码 完整代码 Unordered系列关联式容器 C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0…

浅谈Docker容器的网络通信原理

文章目录 1、回顾容器概念2、容器网络3、容器与主机之间的网络连通4、交换机的虚拟实现---虚拟网桥&#xff08;Bridge&#xff09;5、Docker 守护进程daemon管理容器网络 1、回顾容器概念 我们知道容器允许我们在同一台宿主机&#xff08;电脑&#xff09;上运行多个服务&…

【蓝桥杯省赛真题44】python计算N+N的值 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析

目录 python计算NN的值 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python计算NN的值 第十四届蓝桥杯青少年组python省赛真题 一、题目要求…

VMware安装Ubuntu系统(超详细)

一.Ubuntu官网下载镜像 Ubuntu官网&#xff1a;Enterprise Open Source and Linux | Ubuntu 二.安装Ubuntu系统 选择文件->创建虚拟机新建虚拟机&#xff08;ControlN&#xff09;&#xff0c;这里直接选择典型即可 选择稍后安装系统 选择linux Ubuntu 64位 填写虚拟机名称…