序言
此两种算法是服务降级的一种实现.
常用于限制我们的对外服务的QPS,即控制对外服务在单位时间内所能处理的请求数量.保护我们的服务不会被海量请求给崩盘cuiyaonan2000@163.com
漏桶算法漏桶算法的主要思路为:
- 在nginx层与controller层加一层(即漏桶层),
- 用于接收nginx收到的大批量的请求,接收的请求的速度是没有控制的,但是如果超过了漏桶层的最大容量则直接抛弃该请求.
- 漏桶层将大批量的请求以特定的速度转发给controller层.(当然漏桶层可以放置在需要的任何位置cuiyaonan2000@163.com)
更直观的理解可以参考百度百科的截图如下:
package nan.yao.cui.others.aboutbuckets;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author 崔耀男
* @des: TODO
* @date 2021年6月22日 上午11:10:30
* @package nan.yao.cui.others.aboutbuckets
*/
public class BucketTest {
// 桶的容量
private int capacity = 100;
// 木桶剩余的水滴的量(初始化的时候的空的桶)
private AtomicInteger water = new AtomicInteger(0);
// 水滴的流出的速率,这个可以在 构造方法种设置,比如每秒10个请求.
private int outRate;
// 记录上次成功接收到请求的时间
// 用于计算当前系统时间减去上次请求时间 乘以outrate 所处理的请求数.
private long receivedTime;
// 判断该controller是否能继续接收请求
// true:表示可以处理该请求
// false:表示不能处理该请求,漏桶已经满了
public boolean acquire() {
// 如果是空桶,则直接将
if (water.get() == 0) {
receivedTime = System.currentTimeMillis();
water.addAndGet(1);
return true;
}
// 先计算下上成功接受到当前时间已经流出的记录数
int outNum = ((int) ((System.currentTimeMillis() - receivedTime) / 1000)) * outRate;
int waterLeft = water.get() - outNum;
water.set(Math.max(0, waterLeft));
// 重新更新leakTimeStamp
// outNum是否大于0---cuiyaonan2000@163.com
if (outNum > 0) {
receivedTime = System.currentTimeMillis();
}
// 尝试加水,并且水还未满
if ((water.get()) < capacity) {
water.addAndGet(1);
return true;
} else {
// 水满,拒绝加水
return false;
}
}
public static void main(String[] args) {
System.out.println((((System.currentTimeMillis() - 100) / 1000) * 2));
System.out.println(System.currentTimeMillis() - 100);
System.out.println((System.currentTimeMillis() - 100) / 1000);
}
}
令牌桶算法
令牌桶的算法中心逻辑是:
- 以恒定的速度向令牌桶种添加令牌.当令牌桶满时则放弃向令牌桶中添加令牌
- 请求到达controller层时,需要去令牌桶中获取令牌,如果存在令牌,则继续执行,不存在这放弃这次请求cuiyaonan2000@163.com
更直观的流程图参考百度:
package nan.yao.cui.others.aboutbuckets;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author 崔耀男
* @des: TODO
* @date 2021年6月22日 上午11:14:29
* @package nan.yao.cui.others.aboutbuckets
*/
public class TokenBucketTest {
// 令牌桶的容量----同时表示该controller的同一时间的并发量
private int capacity = 10;
// 令牌桶
private AtomicInteger tokenBucket = new AtomicInteger(0);
// 每秒钟产生的令牌数量
private int tokenNum;
public void doWhile() throws InterruptedException {
// 多少毫秒产生一个令牌
int forNum = 1000 / tokenNum;
while (true) {
tokenBucket.set(0);
while (forNum < 1000) {
Thread.sleep(forNum);
forNum += forNum;
tokenBucket.getAndAdd(1);
}
}
}
public synchronized boolean getToken() {
if (tokenBucket.get()
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?