目录
1:把统计用户的使用频率等这些数据放到一个集中的存储,比如redis,这样无论用户的请求落在了哪台服务器,都以集中存储的数据为准。(Redis)
单位时间内,允许部分操作。 1小时,只允许10个用户操作。
优点:最简单
缺点:可能出现流量突刺
eg:前59分钟,第59分钟来了十个操作。第一小时01分钟又来了十个操作,就可能导致流量突刺,相当于2分钟实现了20个操作。
单位时间内,允许部分操作,但是这个时间是滑动的 需要指定滑动单位
滑动单位: 1min
开始前:
0s 1h 2h
一分钟:
1min 1h1min
优点;能够解决上面流量突刺的问题,第59分钟,限流窗口59min到1h59min,这个时间段内接受10次请求,只要在这个窗口内,更多的操作就会被拒绝。
缺点:实现相对复杂。滑动单位越小,限效果越好。
以固定的速率请求,当请求桶满后,拒绝请求。
每秒处理10个请求,桶的容量是10,每0.1秒处理1次请求(固定的),如果1秒内,来了10个都可以处理完,但如果一秒内来了11个请求,最后那个请求就会被拒绝。
优点:能够一定程度上应对流量突刺,能够以固定的速率处理请求,安全性高
缺点:速度是固定的,没有办法处理一批请求,只能一个一个来
管理员先生成一批令牌,每秒生成10个令牌,当用户操作前,先去拿到令牌,有令牌的人可以先执行,都能够同时执行。
优点:能够并发处理同时的请求,并发性高
缺点:时间单位选取的问题。
以上漏桶限流和令牌桶限流最常用。
- <dependency>
- <groupId>org.redissongroupId>
- <artifactId>redissonartifactId>
- <version>3.17.5version>
- dependency>
- @Configuration
- @ConfigurationProperties(prefix = "spring.redis")
-
- public class RedissonConfig {
- private Integer database;
- private String host;
- private String port;
- @Bean
- public RedissonClient getRedissonClient(){
- //配置Redis的配置类
- Config config=new Config();
- config.useSingleServer()
- .setDatabase(database)
- .setAddress("redis://"+host+":"+port);
- RedissonClient redisson= Redisson.create(config);
- return redisson;
-
- }
- }
- @Service
- public class RedisLimiterManage {
- @Autowired
- private RedissonClient redissonClient;
- //key:区分不同的限流器:不同的用户id
- public void doRateLimit(String key){
-
- RRateLimiter rateLimiter=redissonClient.getRateLimiter(key);
- //将所有用户的访问次数放在同一个限流器上,1秒允许两次
- rateLimiter.trySetRate(RateType.OVERALL,2,1, RateIntervalUnit.SECONDS);
- //每当一个用户来了之后,请求一个令牌
- boolean result = rateLimiter.tryAcquire(1);
- if(!result){
- throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"请求过于频繁");
- }
- }
- }
当我们使用分布式限流Redis的时候,只需要让这个RedisLimiterManage调用doRateLimit方法,就可以进行分布式限流的操作。
- @Autowired
- private RedisLimiterManage redisLimiterManage;
- //引入依赖
-
- //进行限流判断
- redisLimiterManage.doRateLimit("genChartByAi_"+user.getId());
- //每个用户的限流器