限流,是防止用户恶意刷新接口。常见的限流方式有阿里开源的sentinel、redis等。
1、google的guava,令牌桶算法实现限流
Guava的 RateLimiter提供了令牌桶算法实现:平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp)实现。

// RateLimiter提供了两个工厂方法,最终会调用下面两个函数,生成RateLimiter的两个子类。
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond) {RateLimiter rateLimiter = new SmoothBursty(stopwatch, 1.0 /* maxBurstSeconds */);rateLimiter.setRate(permitsPerSecond);return rateLimiter;
}
static RateLimiter create(SleepingStopwatch stopwatch, double permitsPerSecond, long warmupPeriod, TimeUnit unit,double coldFactor) {RateLimiter rateLimiter = new SmoothWarmingUp(stopwatch, warmupPeriod, unit, coldFactor);rateLimiter.setRate(permitsPerSecond);return rateLimiter;
}

平滑突发限流:使用 RateLimiter的静态方法创建一个限流器,设置每秒放置的令牌数为10个。返回的RateLimiter对象可以保证1秒内不会给超过10个令牌,并且以固定速率进行放置,达到平滑输出的效果。
平滑预热限流:RateLimiter的 SmoothWarmingUp是带有预热期的平滑限流,它启动后会有一段预热期,逐步将分发频率提升到配置的速率。

@RestController
public class HomeController {// 这里的10表示每秒允许处理的量为10个private RateLimiter limiter = RateLimiter.create(10);private RateLimiter limiter2 = RateLimiter.create(2, 1000, TimeUnit.SECONDS);//permitsPerSecond: 表示 每秒新增 的令牌数;warmupPeriod: 表示在从 冷启动速率 过渡到 平均速率 的时间间隔@GetMapping("/test/{name}")public String test(@PathVariable("name") String name) {// 请求RateLimiter, 超过permits会被阻塞final double acquire = limiter.acquire();System.out.println("acquire=" + acquire);//判断double是否为空或者为0if (acquire == 0) {return name;} else {return "操作太频繁";}}@AccessLimit(limit = 2, sec = 10)@GetMapping("/test2/{name}")public String test2(@PathVariable("name") String name) {return name;}
}

2、interceptor+redis根据注解限流

public class AccessLimitInterceptor implements HandlerInterceptor {@Resourceprivate RedisTemplate<String, Integer> redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();if (!method.isAnnotationPresent(AccessLimit.class)) {return true;}AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);if (accessLimit == null) {return true;}int limit = accessLimit.limit();int sec = accessLimit.sec();String key = IPUtil.getIpAddress(request) + request.getRequestURI();//资源唯一标识Integer maxLimit = redisTemplate.opsForValue().get(key);if (maxLimit == null) {//set时一定要加过期时间redisTemplate.opsForValue().set(key, 1, sec, TimeUnit.SECONDS);} else if (maxLimit < limit) {redisTemplate.opsForValue().set(key, maxLimit + 1, sec, TimeUnit.SECONDS);} else {output(response, "请求太频繁!");return false;}}return true;}public void output(HttpServletResponse response, String msg) throws IOException {response.setContentType("application/json;charset=UTF-8");ServletOutputStream outputStream = null;try {outputStream = response.getOutputStream();outputStream.write(msg.getBytes("UTF-8"));} catch (IOException e) {e.printStackTrace();} finally {outputStream.flush();outputStream.close();}}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {@Beanpublic AccessLimitInterceptor accessLimitInterceptor() {return new AccessLimitInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {//addPathPatterns 添加拦截规则registry.addInterceptor(accessLimitInterceptor()).addPathPatterns("/**");}@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/");}
}
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();template.setConnectionFactory(redisConnectionFactory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());template.afterPropertiesSet();return template;}
}

限流方式还有很多,后续继续尝试。

springboot工程中限流方式相关推荐

  1. springboot工程中maven插件浅析

    springboot工程中都会配置插件进行编译.打包等操作,下面对常用的maven插件进行简单分析. 一.spring-boot-maven-plugin spring-boot-maven-plug ...

  2. application terminated怎么解决_优雅解决 SpringBoot 工程中多环境下 application.properties 的维护问题...

    个人微信号:geekoftaste, 期待与大家一起探讨! 背景 我们知道 SpringBoot 有一个全局的配置文件 application.properties, 可以把工程里用到的占位符,第三方 ...

  3. springboot工程中各个层次的作用+springboot连接数据库的工具汇总+Mybatis的开发方式/语法

    下面这个是hibernate的相关工程 下面这个是Mybatis的相关工程 \ 可以看出无论使用哪一种,方式都是一致的. --------------------------------------- ...

  4. springboot工程中使用spring.version导致无法启动

    今天弄了一个netty的服务端工程,结果一直启动不了,debug报错如图: 经过查找,发现是因为pom.xml文件中,有spring.version导致 [解决办法] 将spring.version注 ...

  5. 热部署在java中的包名_09-springboot工程中的热部署实现。

    热部署简介 Spring Boot 开发者为Spring Boot项目中提供了一个热部署(spring-boot-devtools)模块,支持项目的热部署(修改了某些资源以后无需重启服务),以提高开发 ...

  6. 02-SpringBoot工程中JDBC应用实践

    文章目录 HikariCP应用实践 背景分析 池化思想分析 连接池原理分析 Java中的连接池 HikariCP入门实践 数据初始化 创建项目模块 添加项目依赖 配置HikariCP连接池 创建项目启 ...

  7. Spring-Boot:写出来的网站访问不到静态资源?怎样通过url访问SpringBoot项目中的静态资源?localhost:8989/favicon.ico访问不了工程中的图标资源?

    Spring-Boot:Spring-Boot写出来的网站访问不到静态资源?怎样通过url访问SpringBoot项目中的静态资源?localhost:8989/favicon.ico访问不了工程中的 ...

  8. 如何创建springboot工程?springboot中的静态资源如何处理?

    创建springboot工程的第一种方式 1.创建工程在pom文件中,继承父工程[springboot工程] 导入spring-boot-starter依赖 导入spring-boot-starter ...

  9. 超简单:解析 yml 类型(application.yml)配置文件 、springboot 工程读取 yml 文件中的值

    方法三是我觉得最简单的. 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 工程结构: 2. 我要读取  application.yml 中属性 ...

最新文章

  1. FPGA设计细节和实现(初学者)
  2. 安装esp8266库_基于ESP8266,DIY低成本智能远程开关灯小装置
  3. 微软服务器应用软件,HTTP 服务器示例应用程序
  4. java 执行cd_Java调用Linux命令(cd的处理)
  5. React的组件生命周期
  6. scrollview复用节点_利用ScrollView实现TableView效果(实现复用)
  7. 直流UPS的研究和应用前景
  8. 匹夫细说C#:庖丁解牛迭代器,那些藏在幕后的秘密
  9. 软件测试工程师-计算机基础
  10. Redis2.8的安装教程,linux下
  11. 不能从远程创建com+对象_链路追踪SkyWalking源码分析——Collector Remote远程通信服务...
  12. Qt Model/View 学习(6) - Delegate教程之——渲染
  13. 《5G应用“扬帆”行动计划(2021-2023年)》征求意见稿发布
  14. c# NPOI按模板导出
  15. java 通配符 删除文件_jQuery removeClass通配符
  16. Arduino ESP32 深度睡眠与外部唤醒(EXT0)
  17. 小程序支持HTML标签
  18. UrlRewrite---实现url伪静态化
  19. echarts地图插小红旗
  20. LeetCode-912-排序数组

热门文章

  1. iperf测试工具使用方法
  2. Java实现AD域登录认证
  3. visio中直线交叉处消除跨线的方法
  4. vue中加载腾讯地图(html形式)
  5. 决策树与R语言(RPART)
  6. 计算机网络--七层协议/五层协议
  7. intellij idea 合并分支到主分支,主分支代码同步到某一分支
  8. as ssd测试软件得分少,教大家AS SSD Benchmark如何测试硬盘性能
  9. 怎么把图片的边缘弄圆_怎么把图片边角变圆?
  10. 好用的IPv6归属地 API