限流与令牌桶

这篇具有很好参考价值的文章主要介绍了限流与令牌桶。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

令牌桶是一种常用的流量控制技术。令牌桶本身没有丢弃和优先级策略。

原理

1.令牌以一定的速率放入桶中。

2.每个令牌允许源发送一定数量的比特。

3.发送一个包,流量调节器就要从桶中删除与包大小相等的令牌数。

4.如果没有足够的令牌发送包,这个包就会等待直到有足够的令牌(在整形器的情况下)或者包被丢弃,也有可能被标记更低的DSCP(在策略者的情况下)。

5.桶有特定的容量,如果桶已经满了,新加入的令牌就会被丢弃。因此,在任何时候,源发送到网络上的最大突发数据量与桶的大小成比例。令牌桶允许突发,但是不能超过限制。

二、原理图

限流与令牌桶

三、令牌桶工具类

简单模拟;
只有生成令牌方法为静态的;

  • TreeSet 桶
package com.tuwer.util;

import java.time.Instant;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * <p>令牌桶</p>
 *
 * @author 土味儿
 * @version 1.0
 * @Date 2023/6/14
 */
public class TokenBucket {
    /**
     * 速率(每秒)
     */
    private int rate;
    /**
     * 令牌桶
     */
    private TreeSet<String> bucket;

    public TokenBucket(int rate) {
        this.rate = Math.max(rate, 1);
        this.bucket = new TreeSet<>();
        this.put();
    }

    /**
     * 获取令牌
     *
     * @return
     */
    public boolean getToken() {
        // 从桶中弹出第一个令牌;如果弹出成功为true
        return Objects.nonNull(this.bucket.pollFirst());
    }

    /**
     * 补充令牌
     * 使桶内令牌保持与速率一致
     */
    private void put() {
        // 开启新线程
        Executors.newSingleThreadExecutor().execute(() -> {
            int num;
            // 匀速补充令牌
            while (true) {
                // 需要补充的令牌数量
                num = this.rate - this.bucket.size();
                this.bucket.addAll(createToken(num));

                // 休眼1秒
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 生成num个令牌
     *
     * @param num
     * @return
     */
    private static Set<String> createToken(int num) {
        Set<String> res = new HashSet<>();
        if (num < 1) {
            return res;
        }

        // 当前时间戳
        long second = Instant.now().getEpochSecond();
        for (int i = 1; i < num + 1; i++) {
            res.add(second + "-" + i);
        }
        return res;
    }
}
  • List 桶
package com.tuwer.util;

import java.time.Instant;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * <p>令牌桶</p>
 *
 * @author 土味儿
 * @version 1.0
 * @Date 2023/6/14
 */
public class TokenBucketOfList {
    /**
     * 速率(每秒)
     */
    private int rate;
    /**
     * 令牌桶
     */
    private List<String> bucket;

    public TokenBucketOfList(int rate) {
        this.rate = Math.max(rate, 1);
        this.bucket = new ArrayList<>(this.rate);
        this.put();
    }

    /**
     * 获取令牌
     *
     * @return
     */
    public boolean getToken() {
        if(bucket.isEmpty()){
            return false;
        }
        // 从桶中弹出第一个令牌
        bucket.remove(0);
        return true;
    }

    /**
     * 补充令牌
     * 使桶内令牌保持与速率一致
     */
    private void put() {
        // 开启新线程
        Executors.newSingleThreadExecutor().execute(() -> {
            int num;
            // 匀速补充令牌
            while (true) {
                // 需要补充的令牌数量
                num = this.rate - this.bucket.size();
                this.bucket.addAll(createToken(num));

                // 休眼1秒
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 生成num个令牌
     *
     * @param num
     * @return
     */
    private static Set<String> createToken(int num) {
        Set<String> res = new HashSet<>();
        if (num < 1) {
            return res;
        }

        // 当前时间戳
        long second = Instant.now().getEpochSecond();
        for (int i = 1; i < num + 1; i++) {
            res.add(second + "-" + i);
        }
        return res;
    }
}

四、模拟API接口

1、服务1

每秒可以处理5个请求

package com.tuwer.service;

import com.tuwer.util.TokenBucket;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>服务类</p>
 *
 * @author 土味儿
 * @version 1.0
 * @Date 2023/6/14
 */
public class MyService1 {
    private static TokenBucket tokenBucket = new TokenBucket(5);

    public List<String> userList(){
        if(tokenBucket.getToken()){
            List<String> list = new ArrayList<>();
            list.add("张三");
            list.add("李四");
            list.add("王五");
            list.add("赵六");
            System.out.println(list);
            return list;
        }else{
            System.out.println("\nMyService1 服务忙,请稍候再试!\n");
            return null;
        }
    }
}

2、服务2

每秒可以处理3个请求

package com.tuwer.service;

import com.tuwer.util.TokenBucket;
import com.tuwer.util.TokenBucketOfList;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>服务类</p>
 *
 * @author 土味儿
 * @version 1.0
 * @Date 2023/6/14
 */
public class MyService2 {
    private static TokenBucket tokenBucket = new TokenBucket(3);

    public List<String> userList(){
        if(tokenBucket.getToken()){
            List<String> list = new ArrayList<>();
            list.add("AAA");
            list.add("BBB");
            list.add("CCC");
            System.out.println(list);
            return list;
        }else{
            System.out.println("\nMyService2 服务忙,请稍候再试!\n");
            return null;
        }
    }
}

五、测试

向两个服务分别发送30个请求,每个请求间隔150毫秒

public class MyTest {
    public static void main(String[] args) {
        MyService1 myService1 = new MyService1();
        MyService2 myService2 = new MyService2();
        int num = 30;
        for (int i = 0; i < num; i++) {
            try {
                TimeUnit.MILLISECONDS.sleep(150);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            myService1.userList();
            myService2.userList();
        }
    }
}
  • 服务1:每秒可以处理5个请求;每隔150毫秒到来1个请求,1秒内会有6个请求,第6个请求超出处理能力,会拒绝。每秒钟会向令牌桶中补充令牌(至5个为止),第7个请求会获得新令牌…

限流与令牌桶

限流与令牌桶

  • 服务2:每秒可以处理3个请求;每隔150毫秒到来1个请求,1秒内会有6个请求,第4个请求开始超出处理能力,会拒绝。每秒钟会向令牌桶中补充令牌(至3个为止),第7个请求会获得新令牌…

限流与令牌桶

限流与令牌桶文章来源地址https://www.toymoban.com/news/detail-482812.html

  • 服务类中用new的方式生成令牌桶工具类,使各个令牌桶互不影响

到了这里,关于限流与令牌桶的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Springboot 中使用 Redisson+AOP+自定义注解 实现访问限流与黑名单拦截

    🏷️ 个人主页 :牵着猫散步的鼠鼠  🏷️ 系列专栏 :Java全栈-专栏 🏷️ 个人学习笔记,若有缺误,欢迎评论区指正   前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站AI学习网站。 目录 前言 1.导入Redisson 引入依

    2024年02月21日
    浏览(55)
  • 限流算法(计数器、滑动时间窗口、漏斗、令牌)原理以及代码实现

    本文会对这4个限流算法进行详细说明,并输出实现限流算法的代码示例。 代码是按照自己的理解写的,很简单的实现了功能,还请大佬们多多交流找bug。 下面还有投票,帮忙投个票👍 什么是限流?限流 限流 就是限制流量。在高并发、高流量的场景中我们需要把限流做好,

    2023年04月17日
    浏览(46)
  • 限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)

    限流是面试中的常见的面试题(尤其是大厂面试、高P面试) 注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请到文末《技术自由圈》公号获取 为什么要限流 简单来说: 限流在很多场景中用来限制并发和请求量,比如说秒杀抢购,保护自身系统和下游系统

    2023年04月17日
    浏览(43)
  • java进行系统的限流实现--Guava RateLimiter、简单计数、滑窗计数、信号量、令牌桶

    本文主要介绍了几种限流方法:Guava RateLimiter、简单计数、滑窗计数、信号量、令牌桶,漏桶算法和nginx限流等等 1、引入guava集成的工具 pom.xml 文件 demo代码实现 2.令牌桶算法 3、滑窗计数器 4、信号量

    2024年02月09日
    浏览(41)
  • 常用限流算法指南

            限流是一种防止系统被过度请求压垮的算法。简单来说,限流就是对系统中的请求进行数量控制,确保系统可以正常处理每个请求而不会因为流量过大而宕机。         举一个常见的例子:假设你家附近有一家三甲医院,其中某科室医生有限,每天只能够接待

    2024年02月01日
    浏览(23)
  • 一种解决常用存储设备无法被电脑识别的方法

           通用串行总线(Universal Serial Bus,简称USB),是连接电脑与设备的一种序列总线标准,也是一种输入输出(I/O)连接端口的技术规范,广泛应用于个人电脑和移动设备等信息通信产品,并扩展至摄影器材、数字电视、游戏机等其他领域[1]。         通用串行总线控

    2024年01月24日
    浏览(55)
  • Git概述及常用命令

    目录 一、前言 二、Git代码托管服务 1. 三、Git常用命令 git config --list 获取Git仓库 1.在本地初始化Git仓库 2.从远程仓库克隆  Git工作区中的文件状态 本地仓库常用操作  远程仓库操作 分支操作  查看分支​​​​​ 标签操作  四、结言         什么是Git?         Git是一

    2024年02月04日
    浏览(25)
  • 【Collection集合】概述、使用以及常用方法

    1.Collection集合的概述 它是单列集合的顶级接口,它表示一组对象,这些对象也称为Collection的元素 JDK不提供此接口的任何直接实现,它提供更具体地子接口(如set和list)实现 2.创建Collection集合的对象 多态的方式 具体的实现类ArrayList,在java.util包下需要导包 向集合里添加元

    2024年02月08日
    浏览(41)
  • 主码流与子码流

            主码流与子码流是为了解决在网络情况不好时为了满足远程预览的流畅性降低码率,而不影响本地录像提出的双码流技术,即一路视频进入NVR后,NVR可以编码提供两种码流,主码流和子码流,主码流分辨率高于子码流,主码流用来录像,子码流用来网传。     这

    2023年04月08日
    浏览(26)
  • 硬件基础——过流与短路保护

    1、保护定义 顾名思义,负载电流超过最大输出电流,就是过流了。 2、保护缘由 ① 对于LDO供电电路,如果过流了,可能电压下降或烧毁LDO ② 对于BUCK或BOOST供电电路,如果过流了,输出功率达不到,电压会下拉 3、保护电路 Note:对于负载过流,尽量在设计阶段解决,确保输

    2024年01月16日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包