博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
限流降级
阅读量:6074 次
发布时间:2019-06-20

本文共 3278 字,大约阅读时间需要 10 分钟。

从实际生活中的场景来理解限流:一个人能够挑100斤的担子,如果给他的肩膀上放150

斤的重物,他可能直接就趴下了,运输能力变成了0,所以我们必须保障给他肩上加的重物
不超过100斤。

 

限流也是同样的道理,通过限流让系统工作在最高吞吐量的水位上,防止系统被击垮。

四个限流器: 

 

单机QPS - RateLimiter -- guava

单机并发 - Semaphore -- memory

多机QPS - redis key -- redis

多机并发 - RPermitExpirableSemaphore -- redission

 

单机QPS - RateLimiter -- guava

 

 通过guava的ratelimiter,实现了令牌桶算法,它不是记录上次的请求时间,而是保存下次请求到来的时间

阻塞方法 tryAccuire()

非阻塞方法 tryAccuire()带超时时间,表示允许等待该超时时间

 

 

单机并发 - Semaphore -- memory

操作系统的信号量是个很重要的概念,Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。

阻塞方法 acquire() 

非阻塞方法  tryAcquire()

 

多机QPS - redis key -- redis

redis key incr方法 

计数器是 Redis 的原子性自增操作可实现的最直观的模式了,它的想法相当简单:每当某个操作发生时,向 Redis 发送一个  命令。

比如在一个 web 应用程序中,如果想知道用户在一年中每天的点击量,那么只要将用户 ID 以及相关的日期信息作为键,并在每次用户点击页面时,执行一次自增操作即可。

1. 通过lua脚本实现原子性

local currentcurrent = redis.call("incr",KEYS[1])if tonumber(current) == 1 then    redis.call("expire",KEYS[1],1)end

2. 思路是每秒进来的请求都是同一个key,无需设置超时时间,会有些许的精度丢失

protected static long getCurrentSecond() {        return System.currentTimeMillis() / 1000;    }--Long currentSecond = getCurrentSecond();            String key = config.getId() + currentSecond;            long currentLimit = jedis.incr(key);            if (currentLimit == 1) {                jedis.expire(key, (int) (long) config.getExpireTime());            }            if (currentLimit > config.getLimit()) {                return false;            } else {                return true;            }

3.思路3 使用redis的列表 + redis事务

FUNCTION LIMIT_API_CALL(ip)current = LLEN(ip)IF current > 10 THEN    ERROR "too many requests per second"ELSE    IF EXISTS(ip) == FALSE        MULTI            RPUSH(ip,ip)            EXPIRE(ip,1)        EXEC    ELSE        RPUSHX(ip,ip)    END    PERFORM_API_CALL()END

 

 

多机并发 - RPermitExpirableSemaphore -- redission

Redisson的可过期性信号量(PermitExpirableSemaphore)实在RSemaphore对象的基础上,为每个信号增加了一个过期时间。每个信号可以通过独立的ID来辨识,释放时只能通过提交这个ID才能释放。

 

 

 

两个算法

 

1、令牌桶算法 :

(1)每秒会有r个令牌放入桶中,或者说,每过1/r秒桶中增加一个令牌。
(2)桶中最多存放b个令牌,如果桶满了,新放入的令牌会被丢弃。
(3)当一个n字节的数据包到达时,消耗n个令牌,请求通过。
(4)如果桶中可用令牌小于n,请求被拒绝

实现 Guava  RateLimiter

2、漏桶算法:

水(请求)先进入漏桶里,漏桶以一定的速度出水,当水流入速度过大时会直接溢出

 

http://ifeve.com/guava-ratelimiter/

 

//平滑限流         if (!needRateSmooth) {            return rateLimiter.tryAcquire(); //直接返回false        } else {            return rateLimiter.tryAcquire(1, TimeUnit.SECONDS); //在1秒内等待        }

 

if (needRateSmooth) {                    long currentTimeMicros = getCurrentMicroSecond();                    long expectedTimeMicros = getNextExecutableMicros(config, currentLimit);                    if (currentTimeMicros <= expectedTimeMicros) {                        long needToParkMicros = expectedTimeMicros - currentTimeMicros;                        if (needToParkMicros > 100) {                            LockSupport.parkNanos(TimeUnit.MICROSECONDS.toNanos(needToParkMicros));                        } else if (needToParkMicros > 15) {                            while (getCurrentMicroSecond() < expectedTimeMicros) {                                Thread.yield();                            }                        } else {                            while (getCurrentMicroSecond() < expectedTimeMicros) ;                        }                    }                }

 

转载于:https://www.cnblogs.com/number7/p/9670822.html

你可能感兴趣的文章
php数据库类
查看>>
阿里巴巴Java开发手册
查看>>
【精】H5移动端webapp开发(快装app)项目案例
查看>>
1.1 学习之初 1.2 约定 1.3 认识Linux 1.4 安装虚拟机 1.5 安装centos7
查看>>
一张图读懂“云栖大会·南京峰会”重磅发布产品
查看>>
hi3519/hi3516AV200交叉编译opencv的精简版本
查看>>
区块链100讲:如何使用开发环境命令行注册EOS靓号及变更EOS账号的active key和其他...
查看>>
区块链100讲:以太坊智能合约solidity如何节省GAS费?
查看>>
解决python3中解压zip文件是文件名乱码的问题
查看>>
lucene 评分要素解析
查看>>
为什么学习大数据,大数据专家写给大数据分析学习者的10个理由
查看>>
学习Python时最容易遇到的12种错误希望可以让你避开这些坑!
查看>>
VIM 使用
查看>>
模板设计模式
查看>>
如何优雅的编程——C语言界面的一点小建议
查看>>
Visual Paradigm 教程[企业架构]:如何使用TOGAF ADM软件(一)
查看>>
Java核心-反射和动态代理(JDK Proxy和Cglib)
查看>>
深度解析vue组件之间通信【8种方式】实例
查看>>
Python SMTP发送邮件
查看>>
【更新】Essential Studio for ASP.NET MVC更新至2018 v4(一)
查看>>