服务限流-令牌桶java实现
此文非常不错,抄自:
https://www.cnblogs.com/googlemeoften/p/6020718.html
其他实现
https://www.cnblogs.com/LBSer/p/4083131.html
a. 按特定的速率向令牌桶投放令牌
b. 根据预设的匹配规则先对报文进行分类,不符合匹配规则的报文不需要经过令牌桶的处理,直接发送;
c. 符合匹配规则的报文,则需要令牌桶进行处理。当桶中有足够的令牌则报文可以被继续发送下去,同时令牌桶中的令牌 量按报文的长度做相应的减少;
d. 当令牌桶中的令牌不足时,报文将不能被发送,只有等到桶中生成了新的令牌,报文才可以发送。这就可以限制报文的流量只能是小于等于令牌生成的速度,达到限制流量的目的。
保留学习
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; /**
* <pre>
* Created by inter12 on 15-3-18.
* </pre>
*/
public class TokenBucket { // 默认桶大小个数 即最大瞬间流量是64M
private static final int DEFAULT_BUCKET_SIZE = 1024 * 1024 * 64; // 一个桶的单位是1字节
private int everyTokenSize = 1; // 瞬间最大流量
private int maxFlowRate; // 平均流量
private int avgFlowRate; // 队列来缓存桶数量:最大的流量峰值就是 = everyTokenSize*DEFAULT_BUCKET_SIZE 64M = 1 * 1024 * 1024
// * 64
private ArrayBlockingQueue<Byte> tokenQueue = new ArrayBlockingQueue<Byte>(DEFAULT_BUCKET_SIZE); private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private volatile boolean isStart = false; private ReentrantLock lock = new ReentrantLock(true); private static final byte A_CHAR = 'a'; public TokenBucket() {
} public TokenBucket(int maxFlowRate, int avgFlowRate) {
this.maxFlowRate = maxFlowRate;
this.avgFlowRate = avgFlowRate;
} public TokenBucket(int everyTokenSize, int maxFlowRate, int avgFlowRate) {
this.everyTokenSize = everyTokenSize;
this.maxFlowRate = maxFlowRate;
this.avgFlowRate = avgFlowRate;
} public void addTokens(Integer tokenNum) {
// 若是桶已经满了,就不再加入新的令牌
for (int i = 0; i < tokenNum; i++) {
tokenQueue.offer(Byte.valueOf(A_CHAR));
}
} public TokenBucket build() {
start();
return this;
} /**
* 获取足够的令牌个数
*
* @return
*/
public boolean getTokens(byte[] dataSize) {
// Preconditions.checkNotNull(dataSize);
// Preconditions.checkArgument(isStart,
// "please invoke start method first !");
int needTokenNum = dataSize.length / everyTokenSize + 1;// 传输内容大小对应的桶个数 final ReentrantLock lock = this.lock;
lock.lock();
try {
boolean result = needTokenNum <= tokenQueue.size(); // 是否存在足够的桶数量
if (!result) {
return false;
} int tokenCount = 0;
for (int i = 0; i < needTokenNum; i++) {
Byte poll = tokenQueue.poll();
if (poll != null) {
tokenCount++;
}
}
return tokenCount == needTokenNum;
} finally {
lock.unlock();
}
} public void start() {
// 初始化桶队列大小
if (maxFlowRate != 0) {
tokenQueue = new ArrayBlockingQueue<Byte>(maxFlowRate);
} // 初始化令牌生产者
TokenProducer tokenProducer = new TokenProducer(avgFlowRate, this);
scheduledExecutorService.scheduleAtFixedRate(tokenProducer, 0, 1, TimeUnit.SECONDS);
isStart = true;
} public void stop() {
isStart = false;
scheduledExecutorService.shutdown();
} public boolean isStarted() {
return isStart;
} class TokenProducer implements Runnable {
private int avgFlowRate;
private TokenBucket tokenBucket;
public TokenProducer(int avgFlowRate, TokenBucket tokenBucket) {
this.avgFlowRate = avgFlowRate;
this.tokenBucket = tokenBucket;
} @Override
public void run() {
tokenBucket.addTokens(avgFlowRate);
}
} public static TokenBucket newBuilder() {
return new TokenBucket();
} public TokenBucket everyTokenSize(int everyTokenSize) {
this.everyTokenSize = everyTokenSize;
return this;
} public TokenBucket maxFlowRate(int maxFlowRate) {
this.maxFlowRate = maxFlowRate;
return this;
} public TokenBucket avgFlowRate(int avgFlowRate) {
this.avgFlowRate = avgFlowRate;
return this;
} private String stringCopy(String data, int copyNum) {
StringBuilder sbuilder = new StringBuilder(data.length() * copyNum);
for (int i = 0; i < copyNum; i++) {
sbuilder.append(data);
}
return sbuilder.toString();
} public static void main(String[] args) throws IOException, InterruptedException {
TokenBucket tokenBucket = TokenBucket.newBuilder().avgFlowRate(512).maxFlowRate(1024).build();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:/ds_test")));
String data = "xxxx";// 四个字节
for (int i = 1; i <= 1000; i++) {
Random random = new Random();
int i1 = random.nextInt(100);
boolean tokens = tokenBucket.getTokens(tokenBucket.stringCopy(data, i1).getBytes());
TimeUnit.MILLISECONDS.sleep(100);
if (tokens) {
bufferedWriter.write("token pass --- index:" + i1);
System.out.println("token pass --- index:" + i1);
} else {
bufferedWriter.write("token rejuect --- index" + i1);
System.out.println("token rejuect --- index" + i1);
}
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedWriter.close();
}
}
服务限流-令牌桶java实现的更多相关文章
- Spring Cloud Alibaba | Sentinel: 服务限流高级篇
目录 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 1. 熔断降级 1.1 降级策略 2. 热点参数限流 2.1 项目依赖 2.2 热点参数规则 3. 系统自适应限 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(七)——一步一步教你如何撸Dapr之服务限流
在一般的互联网应用中限流是一个比较常见的场景,也有很多常见的方式可以实现对应用的限流比如通过令牌桶通过滑动窗口等等方式都可以实现,也可以在整个请求流程中进行限流比如客户端限流就是在客户端通过随机数直接 ...
- Spring Cloud Alibaba | Sentinel: 服务限流基础篇
目录 Spring Cloud Alibaba | Sentinel: 服务限流基础篇 1. 简介 2. 定义资源 2.1 主流框架的默认适配 2.2 抛出异常的方式定义资源 2.3 返回布尔值方式定 ...
- 【4】JMicro微服务-服务限流
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 通过配置SMethod的maxSpeed属性实现服务限流,单位是个/每秒(qps),也就是服务方法每秒允许接收的最大请求个数 ...
- Hystrix-服务降级-服务熔断-服务限流
Hystrix简介 Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致 ...
- Spring Cloud微服务限流之Sentinel+Apollo生产实践
Sentinel概述 在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素.在并发流量比较高的情况下,由于网络调用之间存 ...
- Dubbo服务限流
为了防止某个消费者的QPS或是所有消费者的QPS总和突然飙升而导致的重要服务的失效,系统可以对访问流量进行控制,这种对集群的保护措施称为服务限流. Dubbo中能够实现服务限流的方式较多,可以划分为两 ...
- 服务限流 -- 自定义注解基于RateLimiter实现接口限流
1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...
- 微服务架构 | 5.2 基于 Sentinel 的服务限流及熔断
目录 前言 1. Sentinel 基础知识 1.1 Sentinel 的特性 1.2 Sentinel 的组成 1.3 Sentinel 控制台上的 9 个功能 1.4 Sentinel 工作原理 ...
随机推荐
- 廖雪峰Java4反射与泛型-2注解-3处理注解
1.处理注解 注解本身对对代码逻辑没有任何影响 SOURCE类型的注解在编译期就被丢掉了 CLASS类型的注解仅保存在class文件中 RUNTIME类型的注解在运行期可以被读取 如何使用注解由工具决 ...
- H5移动端开发vue+vux
项目src中用到的npm包有(从编译打包到最终部署仍不能移除)1:vue 渐进式 JavaScript 框架 http://cn.vuejs.org/v2/guide/2: ...
- FTP的应用
创建共享文件,并删除 cd /var/ftp/---------------------(切换到ftp目录下) mkdir aaaaa-------------------(创建aaaaa目录) ll ...
- [UE4]用Blenspace混合空间动画代替AimOffset动画偏移
- Sublime下MarkDown插件实现编辑和实时预览并转换成HTML格式
最近在使用markdown做笔记,编辑器Sublime Text3用起来很轻巧,现在让他支持markdown的语法并且可以实时预览. 安装准备——安装Package Control Package C ...
- Ext.NET Combobox实现数据源静态配置
背景 项目中使用增值税税率, 需求原本是统一的指定税率, 譬如3% 5% 等固定的. 随着业务增加, 发现不同业务有不同的税率, 一会加一个, 一下要改很多个界面. 就想着放到统一的地方. 技术背景 ...
- http note
http 多媒体传输协议 HyperText Transfer Protocol 超文本传输协议 https Hyper Text Transfer Protocol over Secure Sock ...
- spring boot 整合pagehelper分页插件
Spring Boot 整合pagehelper分页插件 测试环境: spring boot 版本 2.0.0.M7 mybatis starter 版本 1.3.1 jdk 1.8 ------ ...
- android 实现一个简单纯文本的ListView
思维线路: 1.创建一个ListViewActivity,LinearLayout布局里写了一个ListView布局 2.创建一个TextView布局给ArrayAdapter适配器使用 3.将Tex ...
- [UGUI]修改顶点
参考链接: https://blog.csdn.net/jk823394954/article/details/53870779 说明:unity版本5.3,新建一个Image,挂上以下的脚本 一.图 ...