限流与令牌桶

news2024/11/28 0:48:55

一、概述

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

原理

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 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 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个请求会获得新令牌…

在这里插入图片描述

在这里插入图片描述

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

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

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

相关文章

跟着《代码随想录刷题》(六)—— 二叉树

6.1 二叉树的前、中、后序遍历 144.、二叉树的前序遍历&#xff08;中左右&#xff09; LeetCode&#xff1a;114、二叉树的前序遍历 &#xff08;1&#xff09;递归法 class Solution { public:void traversal(TreeNode* cur, vector<int>& vec) {if (cur N…

eslint + prettier如何搭配使用

简介 eslintprettier写代码爽到飞起&#xff0c;既规范了代码的格式&#xff0c;同时也让你的代码美观易读。本文介绍如何在项目中使用eslint搭配prettier来规范你的代码 1.eslint 和 prettier区别 先来回答一个问题&#xff0c;eslint和prettier这二者有啥区别&#xff0c;es…

【后端面经-数据库】MySQL的事务隔离级别简介

【后端面经-数据库】MySQL的事务隔离级别简介 0. 事务的概念1. 三类问题2. 事务隔离级别3. 操作指令4. 总结5. 参考博文 0. 事务的概念 事务指的是一连串的集中操作指令&#xff0c;一个事务的执行必须执行完所有的动作才能算作执行结束。事务具有四个特点&#xff0c;简记作A…

表示学习(Representation Learning) Part2--Auto-Encoders、VAEs、GANs

文章目录 Compression:Auto-EncodersCapture parameter distribution (variance): Variational Auto-Encoders原理介绍数学推导生成数据diffusion modelsPros&Cons Train using a second network: GANs 来自Manolis Kellis教授&#xff08;MIT计算生物学主任&#xff09;的…

spark_idea

spark_idea 3、打jar包运行2、code1、pom_xml0、创建数据、模型、预测表0、Windows配置scala环境 3、打jar包运行 ./bin/spark-submit \--class spark02 \--master spark://hadoop102:7077 \--deploy-mode client \/home/gpb/scala_spark2.jar打jar包、存储到虚拟机中 编写执行…

什么是布隆过滤器?如何解决高并发缓存穿透问题?

日常开发中&#xff0c;大家经常使用缓存&#xff0c;但是你知道大型的互联网公司面对高并发流量&#xff0c;要注意缓存穿透问题吗!!! 本文会介绍布隆过滤器&#xff0c;空间换时间&#xff0c;以较低的内存空间、高效解决这个问题。 本篇文章的目录&#xff1a; 1、性能不…

IMX6ULL裸机篇之SPI实验-ICM20608代码实现

一. SPI 实验 SPI实验&#xff1a;学习如何使用 I.MX6U 的 SPI 接口来驱动 ICM-20608&#xff0c;读取 ICM-20608 的六轴数据。 本文学习 SPI通信实验中&#xff0c;涉及从设备的 SPI代码编写。 之前学习了 SPI 主控芯片代码的编写&#xff0c;如下所示&#xff1a; IMX6ULL…

【ROS】RViz使用详解

1、安装 1.1 ROS1-RVIZ RVIZ的ROS1各个ubuntu版本中的安装命令 ubuntu14.04&#xff1a; sudo apt install ros-indigo-rvizubuntu16.04&#xff1a; sudo apt install ros-kinetic-rvizubuntu18.04&#xff1a; sudo apt install ros-melodic-rvizubuntu20.04&#xff1a…

Java厘米级高精准定位系统源码(支持UWB、蓝牙、WIFI定位)

高精准定位系统支持10厘米工业级高精准定位&#xff0c;同时支持UWB&#xff0c;蓝牙&#xff0c;WIFI定位。 ♦高精准定位系统首页为数据统计页面&#xff0c;统计的信息可以分为数量统计、区域告警人数统计、工牌使用量的统计、区域报警率统计以及告警消息的展示。 系统首页…

Pytest教程__常用执行参数详解(3)

前面讲了测试用例的执行方式&#xff0c;也认识了 -v -s 这些参数&#xff0c;那么还有没有其它参数呢&#xff1f;答案肯定是有的&#xff0c;我们可以通过 pytest -h来查看所有可用参数。 从图中可以看出&#xff0c;pytest的参数有很多&#xff0c;但并不是每一个参数都需要…

fiddler高级工具栏中的statistics数据分析工具

Fiddler statistics 板块会统计一个请求开始发出到最终接收并转发的数据&#xff0c;统计和响应的一些信息&#xff1a; 可以使用statistics分页&#xff0c;完成简单的性能测试&#xff0c;查看其接口的响应时间 如图展示&#xff1a; 如图详细解释下每一项的含义&#xff…

grep(General Regular Expression Parser)命令

基本用法 本篇介绍非常有用的命令是grep&#xff0c;这个不寻常的名字代表的是通用正则表达式解析器&#xff08;General Regular Expression Parser&#xff0c;简写为grep&#xff09;。你使用find命令在系统中搜索文件&#xff0c;而使用grep命令在文件中搜索字符串。事实上…

磁盘坏道:sd 2:0:0:0: [sda] Sense Key : Medium Error [current] [descriptor]

现网问题 从log来看磁盘可能存在问题&#xff0c;进一步实锤。 问题定位 通过badblocks扫描磁盘&#xff0c;发现sda磁盘有磁道损坏&#xff0c;建议更换磁盘。 badblocks命令详解 Linux badblocks命令用于检查磁盘装置中损坏的区块,执行指令时须指定所要检查的磁盘装置&…

postman高级使用

概念&#xff1a;让程序代替人判断测试用例执行的结果是否符合预期的一个过程 特点&#xff1a; postman断言使用js编写&#xff0c;断言写在postman的tests中 tests脚本在发送请求之后执行&#xff0c;会把断言的结果最终在testresult中进行展示 常用的postman提供的断言片…

在Django项目中的各个应用中分别编写路由配置文件urls.py

目录 01-通过命令建立三个应用02-配置路由 /index/、/app1/index/、/app2/index/02-1-配置路由 /index/ 并将各个应用的urls.py文件包含进主路由目录中02-02-配置路由/app1/index/02-03-配置路由/app2/index/ 03-编写各个应用的视图views.py 文件04-注册模板文件所在目录05 创建…

CVPR23 | 可编辑3D场景布局的文本引导多对象合成NeRF

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2303.13843 0.背景&#xff1a; 最近&#xff0c;文本到图像生成通过将视觉-语言预训练模型与扩散模型相结合&#xff0c;取得了巨大的成功。这些突破也使得强大…

python: read excel and export excel

""" PythonAppReadExcel.py edit&#xff1a; geovindu,Geovin Du,涂聚文 date 2023-06-13 保险 """ # This is a sample Python script. # python.exe -m pip install --upgrade pip # Press ShiftF10 to execute it or replace it with your c…

orbslam 地图点观测距离范围 mfMinDistance,mfMaxDistance 的理解

目的是在不同帧不同距离的范围内观测到同一个地图点 直观理解&#xff0c;由于相机成像小孔成像近大远小 相机在距离特征点i 1米时图像金字塔第0层的 31x31图像区域&#xff0c; 类似于相机在距离 特征点i 最远约米时的图像金字塔第7层的31x31图像区域。 相机在距离特征点i 1…

桥接模式(十)

不管怎么样&#xff0c;都要继续充满着希望 上一章简单介绍了适配器模式(九), 如果没有看过, 请观看上一章 一. 桥接模式 引用 菜鸟教程里面的 桥接模式介绍: https://www.runoob.com/design-pattern/bridge-pattern.html 桥接&#xff08;Bridge&#xff09;是用于把抽象化…

GitHub 2800颗星,支持GPT/Transformer,字节跳动这个开源项目是怎么来的?

AI 绘画、机器翻译、多轮对话……对于各类 AI 相关的功能来说&#xff0c;总有一个痛点&#xff0c;困扰着所有训模型的算法工程师们&#xff1a; 想要效果更好&#xff0c;那么 AI 模型一般都很大&#xff0c;耗费的算力更多不说&#xff0c;运行起来还更费时间&#xff1b; 如…