前言
在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;而降级是当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开;而有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页),因此需有一种手段来限制这些场景的并发/请求量,即限流。
常见的限流算法有:令牌桶、漏桶、计数器
计数器
它是限流算法中最简单最容易的一种算法,比如我们要求某一个接口,1分钟内的请求不能超过10次,我们可以在开始时设置一个计数器,每次请求,该计数器+1;如果该计数器的值大于10并且与第一次请求的时间间隔在1分钟内,那么说明请求过多,如果该请求与第一次请求的时间间隔大于1分钟,并且该计数器的值还在限流范围内,那么重置该计数器。
但这种不太好,会有临界问题
代码实现
service 类
package com.xd.service.impl;
import org.springframework.stereotype.Service;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by Administrator on 2019/10/24.
* 1 计数器方式实现,限流
*/
@Service
public class LimterService {
private static int limtCount = 10;// 限制最大访问的容量
private static AtomicInteger atomicInteger = new AtomicInteger(0); // 每秒钟 实际请求的数量
private static long start = System.currentTimeMillis();// 获取当前系统时间
private static final int interval = 60*1000;// 间隔时间60秒
public boolean acquire() {
long newTime = System.currentTimeMillis();
if (newTime > (start + interval)) {
// 判断是否是一个周期
start = newTime;
atomicInteger.set(0); // 清理为0
return true;
}
atomicInteger.incrementAndGet();// i++;
System.out.println("atomicInteger"+atomicInteger.get());
return atomicInteger.get() <= limtCount;
}
}
controller 类
package com.xd.controller;
import com.google.common.util.concurrent.