限流的常见算法有以下三种时间窗口算法漏桶算法令牌算法下面来看看充电桩项目中是如何实现的。代码语言javascriptAI代码解释/** * author tianwc 公众号java后端技术全栈、面试专栏 * version 1.0.0 * date 2023年05月27日 09:13 * 博客地址a hrefhttp://woaijava.cc/博客地址/a */ Component public class LimiterUtil { Resource private RedisTemplateString, 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()方法的参数。调用案例service层代码代码语言javascriptAI代码解释public CommonResultBoolean 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); } CommonResultMessageTemplateDto 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); }画个图 更好地理解controller层代码代码语言javascriptAI代码解释/** * 发送登录手机验证码 */ PostMapping(/sendCode) public CommonResultBoolean sendCode4Login(RequestBody SendCodeReqDto sendCodeReqDto) { return sendCodeService.sendCode(sendCodeReqDto.getPhone(), RedisConstantPre.SEND_CODE_LOGIN_PRE, MessageTemplateTypeEnums.PAY_SUCCESS_TEMPLATE.getType()); }测试POST http://localhost:9006/user/sendCode Content-Type: application/json; charsetUTF-8代码语言javascriptAI代码解释{ code: 400015, message: 短信发送太频繁请隔一会再发送, data: null }