SpringBoot中间件——封装限流器

背景

    通常能知道一个系统服务在正产增速下流量大小,扩容与压测也是基于此。若有突发或者恶意攻击访问,都要将流量拦截在外。这部分功能不属于业务侧,它是通用非业务的共性需求,所以我们将共性抽取为限流中间件。

方案设计

图解:

  • Ratelimiter
谷歌Guava库中的一个限流工具类,用于限制访问限制某一资源,令牌桶思想的一个实现,可实现流量控制。
用到其两个方法:
  • create():创建一个RateLimiter实例,并设置该实例的限流速率(即允许每秒执行的任务数),例如:
RateLimiter rateLimiter = RateLimiter.create(10);
        上述代码将创建一个每秒允许10个任务的RateLimiter实例。

  • tryAcquire():尝试获取一个许可,若获取成功则返回true,否则返回false。 例如:
    if (rateLimiter.tryAcquire()) {// do something
    }
        上述代码将尝试获取一个许可,如果该实例当前拥有足够的许可,则执行do something操作
使用自定义注解和AOP,拦截需要被限流保护的方法。
拦截后,用Ratelimiter做限流处理
  • 使用自定义注解和AOP,拦截需要被限流保护的方法。
  • 拦截后,用Ratelimiter做限流处理

代码示例

1.自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoRateLimiter {// 每秒访问次数限制public double rate() default 0d;// 超频后的触发熔断默认响应结果public String returnJson() default "";
}

2.常量类

public class Constant {/*** 全局Hashmap,用于存放【方法】对应的限流类* key: 类名 + 方法名* value: 对应限流类*/public static Map<String, RateLimiter> stringRateLimiterMap = Collections.synchronizedMap(new HashMap<String, RateLimiter>());
}

3.切面逻辑处理

PS:切面中的实现细节/注解的使用已经在统一白名单中间件  文章中详细梳理过了,需要请移步

@Component
@Aspect
public class RateLimiterHandle {// 切点@Pointcut("@annotation(com.example.ratelimiteer.annotation.DoRateLimiter)")public void aopPointcut() {}/*** @param jp            切点* @param doRateLimiter 注解实例* @return 方法响应结果* @throws Throwable*/@Around(value = "aopPointcut()&& @annotation(doRateLimiter)")public Object handle(ProceedingJoinPoint jp, DoRateLimiter doRateLimiter) throws Throwable {// 判断是否开启限流if (doRateLimiter.rate() == 0d) {return jp.proceed();}// 构建限流哈希Map的Key: 类名 + "." + "方法名"String className = jp.getTarget().getClass().getName();MethodSignature signature = (MethodSignature) jp.getSignature();Method method = jp.getTarget().getClass().getMethod(signature.getMethod().getName(), signature.getMethod().getParameterTypes());String methodName = method.getName();String key = className + "." + methodName;// 第一次走到该接口if (!Constant.stringRateLimiterMap.containsKey(key)) {Map<String, RateLimiter> rateLimiterMap = Constant.stringRateLimiterMap;rateLimiterMap.put(key, RateLimiter.create(doRateLimiter.rate()));}// 判断是否限流RateLimiter rateLimiter = Constant.stringRateLimiterMap.get(key);if (rateLimiter.tryAcquire()) {// 未超过访问限制,则继续执行对应业务逻辑return jp.proceed();} else {// 超过访问限制,则返回默认熔断响应结果(即注解中的returnJson)return JSON.parseObject(doRateLimiter.returnJson());}}
}

测试

controller如下,仅允许一个并发

压测两个并发

result:尝试拿一个许可(RateLimiter.tryAcquire())未拿到(即超频),返回注解中的returnJson()

✅ 由此可见,限流保护已生效

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14432.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多元回归预测 | Matlab鲸鱼算法(WOA)优化极限梯度提升树XGBoost回归预测,WOA-XGBoost回归预测模型,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab鲸鱼算法(WOA)优化极限梯度提升树XGBoost回归预测,WOA-XGBoost回归预测模型,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源…

LeViT-UNet:transformer 编码器和CNN解码器的有效整合

levi - unet[2]是一种新的医学图像分割架构&#xff0c;它使用transformer 作为编码器&#xff0c;这使得它能够更有效地学习远程依赖关系。levi - unet[2]比传统的U-Nets更快&#xff0c;同时仍然实现了最先进的分割性能。 levi - unet[2]在几个具有挑战性的医学图像分割基准…

【Python】Python基础知识总结

&#x1f389;欢迎来到Python专栏~Python基础知识总结 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望…

线程本地变量交换框架-TransmitterableThreadLocal(阿里开源)

上文 &#xff1a;秒级达百万高并发框架-Disruptor TransmitterableThreadLocal介绍 TransmitterableThreadLocal简称TTL 是阿里巴巴开源的一个框架。TransmittableThreadLocal是对Java中的ThreadLocal进行了增强和扩展。它旨在解决在线程池或异步任务调用链中&#xff0c;Thre…

【DASOU视频记录】Transformer从零详细解读

文章目录 来源transformer的全局理解位置编码多头注意力机制残差Batch NormalLayer NormalDecoder 来源 b站链接 transformer的全局理解 输入中文&#xff0c;输出英文 细化容易理解的结构&#xff0c;就是先编码&#xff0c;再解码 进一步细化的结构&#xff0c;就是多个编…

ARM异常处理详解

前言&#xff1a; 学习一门处理器最重要的就是掌握该处理器的指令集和异常处理。 异常概念&#xff1a; 处理器在正常执行程序时可能会遇到一些不正常的事件发生&#xff0c;这时处理器就要将当前的程序暂停下来转去处理这个异常的事件&#xff0c;异常处理后再返回到被异常打…

Windows下PaddleOCR用NCNN部署

1.所用到的ncnn格式的模型文件 要问这些模型哪里来的&#xff0c;请看下面提示信息: 2.查看字典函数读取方法 char* readKeysFromAssets() {std::ifstream ifs("./model/paddleocr_keys.txt");if (!ifs.is_open()){return 0;}ifs.seekg(0, std::ios_base::end);int …

以太网数据链路层相关技术(六)

目录 一、概述 二、MAC地址 2.1 概述 2.2 MAC地址的意义 三、共享介质型网络与非共享介质网络 四、VLAN技术 一、概述 在各设备之间的数据传输时&#xff0c;物理层和数据链路层是必不可少的。其中&#xff0c;物理层的通信媒介包括双绞线电缆、同轴电缆、光纤、电波以及…

1763_gcc编译c语言makefile自动生成工具的Perl实现_Linux

全部学习汇总&#xff1a; GreyZhang/g_makefile: Learn makefile from all kinds of tutorials on the web. Happy hacking and lets find an common way so we may dont need to touch makefile code any more! (github.com) 其实&#xff0c;调试完这个之后觉得之前Windows上…

docker环境部署postgres版本nacos

1、docker安装postgres 执行命令&#xff1a;docker pull postgres 拉取最新版postgres 2、查看postgres镜像是否安装成功: docker imags(查看镜像)&#xff0c;可以看到已经拉取到了最新版本 的postgres镜像 3、编辑一个docker-compose.yml文件&#xff0c;账号是postgres&a…

DynaSLAM 2018论文翻译

Dynaslam:动态场景下的跟踪、建图和图像修复 摘要-场景刚性假设是SLAM算法的典型特征。这种强假设限制了大多数视觉SLAM系统在人口稠密的现实环境中的使用&#xff0c;而这些环境是服务机器人或自动驾驶汽车等几个相关应用的目标。 在本文中&#xff0c;我们提出了一个基于ORB…