Commit 6a1ba44a authored by shenjiaqing's avatar shenjiaqing

提交代码

parent da3b426e
...@@ -38,7 +38,7 @@ allprojects { ...@@ -38,7 +38,7 @@ allprojects {
} }
group = "cn.com.duiba.boot" group = "cn.com.duiba.boot"
version = "0.0.73-sjq-SNAPSHOT" version = "0.0.74-sjq-SNAPSHOT"
} }
subprojects { subprojects {
......
...@@ -23,6 +23,8 @@ import java.util.concurrent.atomic.AtomicLong; ...@@ -23,6 +23,8 @@ import java.util.concurrent.atomic.AtomicLong;
@Component @Component
public class LimitAspect { public class LimitAspect {
private final static Map<Long, Integer> redisNodeIndex = new ConcurrentHashMap<>();
private final static Logger logger = LoggerFactory.getLogger(LimitAspect.class); private final static Logger logger = LoggerFactory.getLogger(LimitAspect.class);
private final static Map<String, AtomicLong> map = new ConcurrentHashMap<>(); private final static Map<String, AtomicLong> map = new ConcurrentHashMap<>();
...@@ -31,6 +33,23 @@ public class LimitAspect { ...@@ -31,6 +33,23 @@ public class LimitAspect {
static { static {
map.put("rate.limit:com.duiba.tuia.adx.web.service.algo.impl.AdxAlgoServiceImpl-hello-limit", new AtomicLong()); map.put("rate.limit:com.duiba.tuia.adx.web.service.algo.impl.AdxAlgoServiceImpl-hello-limit", new AtomicLong());
redisNodeIndex.put(0L, 14);
redisNodeIndex.put(1L, 18);
redisNodeIndex.put(2L, 296);
redisNodeIndex.put(3L, 346);
redisNodeIndex.put(4L, 29);
redisNodeIndex.put(5L, 21);
redisNodeIndex.put(6L, 32);
redisNodeIndex.put(7L, 122);
redisNodeIndex.put(8L, 69);
redisNodeIndex.put(9L, 65);
redisNodeIndex.put(10L, 76);
redisNodeIndex.put(11L, 197);
redisNodeIndex.put(12L, 50);
redisNodeIndex.put(13L, 58);
redisNodeIndex.put(14L, 223);
redisNodeIndex.put(15L, 47);
} }
@Resource(name = "redis03StringRedisTemplate") @Resource(name = "redis03StringRedisTemplate")
...@@ -68,11 +87,11 @@ public class LimitAspect { ...@@ -68,11 +87,11 @@ public class LimitAspect {
.append(method.getName()).append("-") .append(method.getName()).append("-")
.append(rateLimit.key()); .append(rateLimit.key());
String s = stringBuilder.toString(); String commonRedisKey = stringBuilder.toString();
long index = map.get(s).getAndIncrement() % REDIS_NODE_NUM; long index = map.get(commonRedisKey).getAndIncrement() % REDIS_NODE_NUM;
String redisKey = s + index; String redisKey = commonRedisKey + "{" + redisNodeIndex.get(index) + "}";
logger.info("限流啦, redis key{}", redisKey); logger.info("限流啦, redis key{}", redisKey);
List<String> keys = Collections.singletonList(redisKey); List<String> keys = Collections.singletonList(redisKey);
......
...@@ -7,3 +7,60 @@ else --请求数+1,并设置2秒过期 ...@@ -7,3 +7,60 @@ else --请求数+1,并设置2秒过期
redis.call("expire", KEYS[1], "2") redis.call("expire", KEYS[1], "2")
return current + 1 return current + 1
end end
--
--
-- -- LUA脚本会以单线程执行,不会有并发问题,一个脚本中的执行过程中如果报错,那么已执行的操作不会回滚
-- -- KEYS和ARGV是外部传入进来需要操作的redis数据库中的key,下标从1开始
-- -- 参数结构: KEYS = [限流的key] ARGV = [最大令牌数, 每秒生成的令牌数, 本次请求的毫秒数]
-- local info = redis.pcall('HMGET', KEYS[1], 'last_time', 'stored_token_nums')
-- local last_time = info[1] --最后一次通过限流的时间
-- local stored_token_nums = tonumber(info[2]) -- 剩余的令牌数量
-- local max_token = tonumber(ARGV[1])
-- local token_rate = tonumber(ARGV[2])
-- local current_time = tonumber(ARGV[3])
-- local past_time = 0
-- local rateOfperMills = token_rate/1000 -- 每毫秒生产令牌速率
--
-- if stored_token_nums == nil then
-- -- 第一次请求或者键已经过期
-- stored_token_nums = max_token --令牌恢复至最大数量
-- last_time = current_time --记录请求时间
-- else
-- -- 处于流量中
-- past_time = current_time - last_time --经过了多少时间
--
-- if past_time <= 0 then
-- --高并发下每个服务的时间可能不一致
-- past_time = 0 -- 强制变成0 此处可能会出现少量误差
-- end
-- -- 两次请求期间内应该生成多少个token
-- local generated_nums = math.floor(past_time * rateOfperMills) -- 向下取整,多余的认为还没生成完
-- stored_token_nums = math.min((stored_token_nums + generated_nums), max_token) -- 合并所有的令牌后不能超过设定的最大令牌数
-- end
--
-- local returnVal = 0 -- 返回值
--
-- if stored_token_nums > 0 then
-- returnVal = 1 -- 通过限流
-- stored_token_nums = stored_token_nums - 1 -- 减少令牌
-- -- 必须要在获得令牌后才能重新记录时间。举例: 当每隔2ms请求一次时,只要第一次没有获取到token,那么后续会无法生产token,永远只过去了2ms
-- last_time = last_time + past_time
-- end
--
-- -- 更新缓存
-- redis.call('HMSET', KEYS[1], 'last_time', last_time, 'stored_token_nums', stored_token_nums)
-- -- 设置超时时间
-- -- 令牌桶满额的时间(超时时间)(ms) = 空缺的令牌数 * 生成一枚令牌所需要的毫秒数(1 / 每毫秒生产令牌速率)
-- redis.call('PEXPIRE', KEYS[1], math.ceil((1/rateOfperMills) * (max_token - stored_token_nums)))
--
-- return returnVal
--
-- --实现平滑限流
-- --出自:https://www.jianshu.com/p/89822f8d5c69
-- --https://blog.csdn.net/teavamc/article/details/113359632
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment