springboot工程中限流方式
限流,是防止用户恶意刷新接口。常见的限流方式有阿里开源的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工程中限流方式相关推荐
- springboot工程中maven插件浅析
springboot工程中都会配置插件进行编译.打包等操作,下面对常用的maven插件进行简单分析. 一.spring-boot-maven-plugin spring-boot-maven-plug ...
- application terminated怎么解决_优雅解决 SpringBoot 工程中多环境下 application.properties 的维护问题...
个人微信号:geekoftaste, 期待与大家一起探讨! 背景 我们知道 SpringBoot 有一个全局的配置文件 application.properties, 可以把工程里用到的占位符,第三方 ...
- springboot工程中各个层次的作用+springboot连接数据库的工具汇总+Mybatis的开发方式/语法
下面这个是hibernate的相关工程 下面这个是Mybatis的相关工程 \ 可以看出无论使用哪一种,方式都是一致的. --------------------------------------- ...
- springboot工程中使用spring.version导致无法启动
今天弄了一个netty的服务端工程,结果一直启动不了,debug报错如图: 经过查找,发现是因为pom.xml文件中,有spring.version导致 [解决办法] 将spring.version注 ...
- 热部署在java中的包名_09-springboot工程中的热部署实现。
热部署简介 Spring Boot 开发者为Spring Boot项目中提供了一个热部署(spring-boot-devtools)模块,支持项目的热部署(修改了某些资源以后无需重启服务),以提高开发 ...
- 02-SpringBoot工程中JDBC应用实践
文章目录 HikariCP应用实践 背景分析 池化思想分析 连接池原理分析 Java中的连接池 HikariCP入门实践 数据初始化 创建项目模块 添加项目依赖 配置HikariCP连接池 创建项目启 ...
- Spring-Boot:写出来的网站访问不到静态资源?怎样通过url访问SpringBoot项目中的静态资源?localhost:8989/favicon.ico访问不了工程中的图标资源?
Spring-Boot:Spring-Boot写出来的网站访问不到静态资源?怎样通过url访问SpringBoot项目中的静态资源?localhost:8989/favicon.ico访问不了工程中的 ...
- 如何创建springboot工程?springboot中的静态资源如何处理?
创建springboot工程的第一种方式 1.创建工程在pom文件中,继承父工程[springboot工程] 导入spring-boot-starter依赖 导入spring-boot-starter ...
- 超简单:解析 yml 类型(application.yml)配置文件 、springboot 工程读取 yml 文件中的值
方法三是我觉得最简单的. 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 工程结构: 2. 我要读取 application.yml 中属性 ...
最新文章
- FPGA设计细节和实现(初学者)
- 安装esp8266库_基于ESP8266,DIY低成本智能远程开关灯小装置
- 微软服务器应用软件,HTTP 服务器示例应用程序
- java 执行cd_Java调用Linux命令(cd的处理)
- React的组件生命周期
- scrollview复用节点_利用ScrollView实现TableView效果(实现复用)
- 直流UPS的研究和应用前景
- 匹夫细说C#:庖丁解牛迭代器,那些藏在幕后的秘密
- 软件测试工程师-计算机基础
- Redis2.8的安装教程,linux下
- 不能从远程创建com+对象_链路追踪SkyWalking源码分析——Collector Remote远程通信服务...
- Qt Model/View 学习(6) - Delegate教程之——渲染
- 《5G应用“扬帆”行动计划(2021-2023年)》征求意见稿发布
- c# NPOI按模板导出
- java 通配符 删除文件_jQuery removeClass通配符
- Arduino ESP32 深度睡眠与外部唤醒(EXT0)
- 小程序支持HTML标签
- UrlRewrite---实现url伪静态化
- echarts地图插小红旗
- LeetCode-912-排序数组