限流
Contents
💠
-
- 2.1. Nginx
- 2.2. Guava
- 2.3. Redis
- 2.4. Hystrix
- 2.5. concurrency-limits
-
- 3.1. Redis 实现
- 3.2. Oracle Coherence
💠 2024-09-20 11:10:09
限流
目的
- 保护系统稳定性:过多的并发请求可能导致服务器内存耗尽、CPU 使用率饱和,从而引发系统响应慢、无法正常服务的问题。
- 防止资源滥用:确保有限的服务资源被合理公平地分配给所有用户,防止个别用户或恶意程序过度消耗资源。
- 优化用户体验:对于网站和应用程序而言,如果任由高并发导致响应速度变慢,会影响所有用户的正常使用体验。
- 保障安全:在网络层面,限流有助于防范 DoS/DDoS 攻击,降低系统遭受恶意攻击的风险。
- 运维成本控制:合理的限流措施可以帮助企业减少不必要的硬件投入,节省运营成本。
算法
令牌桶,漏桶,固定窗口,滑动窗口 都是对流量整形,削峰填谷,适用于常见REST接口。
如果是任务调度类场景,单个任务执行时间很长(分钟级),则不适用,可以考虑分布式Semaphore的实现,限制整个集群上下游的并行任务数。
令牌桶
固定速率生成令牌放入桶中,并支持预取,通过是否获得令牌来实现限流
- 允许当前请求获取超量资源(大于并发限制),下一次请求需要等待超额的时间
漏桶
不支持突发流量, 通过限制流出速率,丢弃突发的流入流量来实现限流
固定窗口
通过限制固定时间窗口(例如自然时间1分钟 10:00 到 10:01 )内请求数,超出部分丢弃,实现限流。
滑动窗口
通过限制滑动时间窗口(例如过去1分钟)内请求数,超出部分丢弃,实现限流。
组件方案
Nginx
Guava
RateLimiter 令牌桶实现
- 支持平滑发放令牌(例如限制每秒5并发,每个令牌的获取间隔大概在200ms左右)
Redis
简易:zset 使用时间戳值来做滑动窗口,如果服务器间时间不同步,会在边界情况下超出设定的最大阈值。
Hystrix
concurrency-limits
concurrency-limits 类似于 TCP拥塞控制算法
分布式Semaphore
作用类似于 JDK中的Semaphore,但是资源限制是分布式的,而不是单机,实现可以依赖Redis或MySQL等中间存储。
Redis 实现
- 使用 Redission 中的 RSemaphore
- Lua脚本实现,加一(获取资源),判断是否超阈值超过则撤销加一,减一(释放资源)
自旋等待
- 命令:
EVAL "local cnt = redis.call('incr', KEYS[1]); if (tonumber(cnt) > tonumber(ARGV[1]) ) then redis.call('decr', KEYS[1]); return 0; else return 1; end " 1 lockA 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
public static final String Judge = "local cnt = redis.call('incr', KEYS[1]);" + " if (tonumber(cnt) > tonumber(ARGV[1]) ) then redis.call('decr', KEYS[1]); return 0;" + " else return 1; end"; public boolean acquire() { // 指定 lua 脚本,并且指定返回值类型 DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>(Judge, Integer.class); // 参数一:redisScript,参数二:key列表,参数三:arg(可多个) Object lockB = redisTemplate.execute(redisScript, Collections.singletonList("lockB"), 3); if (Objects.isNull(lockB)) { return false; } return Integer.parseInt(lockB.toString()) > 0; } public String release() { Long val = redisTemplate.opsForValue().decrement("lockB"); return val + ""; }
- 命令:
分布式限流——Redis版分布式信号量原理
负面参考:实现复杂有缺陷
Oracle Coherence
Author Kuangcp
LastMod 2022-08-03