java限流


@Component
public class LimiterUtil {
@Resource
private RedisTemplate<String, String> redisTemplate;

/**
 * 固定窗口限流算法
 *
 * @return true 限流  false 放行
 */
public boolean fixedWindow(String key, int count) {
    long countCache = redisTemplate.opsForValue().increment(key);
    return countCache > count;
}

/**
 * intervalTime 时间内 最多只能访问5次
 *
 * @param key          缓存key
 * @param currentTime  当前时间  new Date().getTime();
 * @param intervalTime 有效期
 * @param count        限流次数
 * @return true 限流 false 放行
 */
public boolean slidingWindow(String key, Long currentTime, Long intervalTime, int count) {
    //发送次数+1
    redisTemplate.opsForZSet().add(key, UUID.randomUUID().toString(), currentTime);
    // intervalTime是限流的时间
    int countCache = Objects.requireNonNull(redisTemplate.opsForZSet().rangeByScore(key, currentTime - intervalTime, currentTime)).size();
    return countCache > count; 
}
}

/**
*发送短信单位时间内次数限制采用的是slidingWindow()方法的参数。
*/
public
CommonResult<Boolean> sendCode(String phone, String codeCachePre, Integer msgType) { if (StringUtil.isEmpty(phone)) { return CommonResult.failed(ResultCode.VALIDATE_FAILED); } ParamValidate.isNull(phone, "phone参数为空"); //同一个手机号码 发送次数限流 //同一个手机号每秒 最多只能发5次 boolean limit = limiterUtil.slidingWindow(RedisConstantPre.MESSAGE_LIMIT_KEY_PRE + phone, (new Date()).getTime(), 60000L, 5); if (limit) { return CommonResult.failed(ResultCode.SEND_MESSAGE_LIMIT); } CommonResult<MessageTemplateDto> commonResult = messageTemplateFeignClient.queryByMessageType(msgType); if (commonResult.getCode() != ResultCode.SUCCESS.getCode()) { log.error("短信模板不存在,tye={}", msgType); return CommonResult.failed(ResultCode.VALIDATE_FAILED); } MessageTemplateDto messageTemplateDto = commonResult.getData(); //生成随机验证码 String code = RandomUtil.randomNumbers(6); log.info("登录发送验证码:{}", code); //发送验证码 String content = messageTemplateDto.getContent(); //验证码占位符 String newContent = content.replace(messageTemplateDto.getContentParam(), code); //调用MQ 异步发送短信验证码 phoneMessageProducer.sendPhoneMessage(phone, newContent); //存到redis中 设置有效期 60秒 //60秒后需要重现发送 redisConfig.set(codeCachePre + phone, code, 60); return CommonResult.success(Boolean.TRUE); }

 

posted on 2023-06-19 08:26  五官一体即忢  阅读(26)  评论(0编辑  收藏  举报

导航