服务限流-令牌桶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 工作原理 ...
随机推荐
- 学习笔记之Microsoft Office 365
云办公确实很方便. Office 365 登录 | Microsoft Office https://www.office.com/ Office 365 - Wikipedia https://en ...
- [转]Android 代码自动提示功能
源地址http://blog.sina.com.cn/s/blog_7dbac12501019mbh.html 或者http://blog.csdn.net/longvslove/article/de ...
- [UE4]关卡蓝图
- ArcGIS for android访问天地图
底图采用Web Mercator投影坐标系 获取元数据信息:http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetCapabili ...
- github----awesome-typescript-projects
https://github.com/brookshi/awesome-typescript-projects
- python类的全面介绍
转载:全面介绍python面向对象的编程——类的基础 转载:类的实例方法.静态方法.类方法的区别
- echarts3更新
dataRange: { realtime: false, itemHeight: 80, splitNumber:6, borderWidth:1, textStyle: { color: '#33 ...
- mysql数据库数据备份与恢复
备份数据: C:\Users\Administrator>mysqldump -uroot --password -v test01 test02 >e:\temp\\a3.sql Ent ...
- jmeter本机内存溢出如何修改?
websocket连接过程中内存溢出,本机配置的内存最大和最小设置的512: 一.后台返回 二.结果树返回: Thread Name: 线程组 1-9Sample Start: 2017-09-11 ...
- 使用tpcc-mysql进行性能测试
tpcc-mysql的github地址:https://github.com/Percona-Lab/tpcc-mysql tpcc-mysql源代码进行编译,服务器上需要安装有mysql git c ...