使用AOP和Semaphore对项目中具体的某一个接口进行限流
整体思路:
一 具体接口,可以自定义一个注解,配置限流量,然后对需要限流的方法加上注解即可!
二 容器初始化的时候扫描所有所有controller,并找出需要限流的接口方法,获取对应的限流量
三 使用拦截器或者aop,对加上注解的方法进行限流,采用配置的信号量
自定义注解
/**
* 限流注解
*/
@Target(ElementType.METHOD) //作用与方法上
@Retention(RetentionPolicy.RUNTIME) //注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
@Documented
public @interface ApiRateLimit {
int value(); //控制并发最大数量
}
出初始化限流配置,注意:这里设置的如果限流量一样,则两个方法一起限流,比如两个方法限流量都是5,则两个方法总共可以支持最多5个线程访问
实际可以自己调整,加个方法名当key,则可以保证每个方法都独自限流:
/**
* ApplicationContextAware实现类可以获得spring上下文
* 间接获取ApplicationContext中的所有bean,向切面添加所有接口的配置的限流量
*/
@Component
public class InitApiLimit implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(RestController.class);
System.out.println(beanMap.size());
beanMap.forEach((k,v)->{
Class<?> controllerClass = v.getClass();
System.out.println(controllerClass.toString());
System.out.println(controllerClass.getSuperclass().toString());
//获取所有声明的方法
Method[] allMethods = controllerClass.getSuperclass().getDeclaredMethods();
for (Method method:allMethods){
System.out.println(method.getName());
//判断方法是否使用了限流注解
if (method.isAnnotationPresent(ApiRateLimit.class)){
//获取配置的限流量,实际值可以动态获取,配置key,根据key从配置文件获取
int value = method.getAnnotation(ApiRateLimit.class).value();
String key = String.valueOf(value);
//key作为key.value为具体限流量,传递到切面的map中
ApiLimitAspect.semaphoreMap.put(key,new Semaphore(value));
}
}
System.out.println("----信号量个数:"+ApiLimitAspect.semaphoreMap.size());
});
}
}
注意:这里有一点需要说明,一旦使用了代理,因为是controller',没有借口,所以是cglib,会创建子类
,此时从容器中获取的是代理的子类,默认是不会有自定义注解的,所以得getSuperClass,从父类,即controller中获取注解信息
编写切面,这里是最主要的,使用jdk自带的信号量:
限流切面
/**
* 限流切面
*/
@Aspect
@Order(value = Ordered.HIGHEST_PRECEDENCE) //最高优先级
@Component
public class ApiLimitAspect {
//存储限流量和方法,必须是static且线程安全,保证所有线程进入都唯一
public static Map<String, Semaphore> semaphoreMap= new ConcurrentHashMap<>();
//拦截所有controller 的所有方法
@Around("execution(* com.hou.serviceorder.controller.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint){
Object result=null;
Semaphore semaphore=null;
Class<?> clz = joinPoint.getTarget().getClass();//获取目标对象
Signature signature = joinPoint.getSignature();//获取增强方法信息
String name = signature.getName();
String limitKey = String.valueOf(getLimitKey(clz, name));
if(limitKey!=null && !"".equals(limitKey)){
semaphore = semaphoreMap.get(limitKey);
try {
semaphore.acquire();
result=joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
return result;
} //获取拦截方法配置的限流key,没有返回null
private Integer getLimitKey(Class<?> clz, String methodName){
for (Method method:clz.getDeclaredMethods()){
if(method.getName().equals(methodName)){//找出目标方法
if(method.isAnnotationPresent(ApiRateLimit.class)){//判断是否是限流方法
return method.getAnnotation(ApiRateLimit.class).value();
}
}
}
return null;
}
}
使用注解
@ApiRateLimit(value = 5)
@GetMapping("/name")
public String getOrderName() throws InterruptedException {
System.out.println("-----进入getOrder方法------");
TimeUnit.SECONDS.sleep(2);
return "order";
} @ApiRateLimit(value = 5)
@GetMapping("/order")
public Order getOrder(String id) throws InterruptedException {
System.out.println("-----进入getOrder方法------");
TimeUnit.SECONDS.sleep(2);
return new Order(id,"侯征");
}
测试
public class TestSe {
public static void main(String[] args) {
//测试信号并发量
for (int i = 0; i < 10; i++) {
new Thread(()->{
//访问目标接口
RestTemplate restTemplate = new RestTemplate();
restTemplate.getForObject("http://localhost:8081/order/name",String.class);
}).start();
}
}
}
会发现最多5个一起打印:

使用AOP和Semaphore对项目中具体的某一个接口进行限流的更多相关文章
- 转:C4项目中验证用户登录一个特性就搞定
转:C4项目中验证用户登录一个特性就搞定 在开发过程中,需要用户登陆才能访问指定的页面这种功能,微软已经提供了这个特性. // 摘要: // 表示一个特性,该特性用于限制调用 ...
- java web项目(spring项目)中集成webservice ,实现对外开放接口
什么是WebService?webService小示例 点此了解 下面进入正题: Javaweb项目(spring项目)中集成webservice ,实现对外开放接口步骤: 准备: 采用与spring ...
- 一个项目中:只能存在一个 WebMvcConfigurationSupport (静态文件失效之坑)
一个项目中:只能存在一个 WebMvcConfigurationSupport 在一个项目中WebMvcConfigurationSupport只能存在一个,多个的时候,只有一个会生效. 静态文件访问 ...
- 《 .NET并发编程实战》一书中的节流为什么不翻译成限流
有读者问,为什么< .NET并发编程实战>一书中的节流为什么不翻译成限流? 这个问题问得十分好!毕竟“限流”这个词名气很大,耳熟能详,知名度比“节流”大多了. 首先,节流的原词Thrott ...
- Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级
相关文章 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网 ...
- iOS中AOP与Method Swizzling 项目中的应用
引子:项目中需要对按钮点击事件进行统计分析,现在项目中就是在按钮的响应代码中添加点击事件,非常繁琐.所以使用了AOP(面向切面编程),将统计的业务逻辑统一抽离出来. 项目中添加的开源库:https:/ ...
- C#.NET常见问题(FAQ)-程序如何把窗体文件从从一个项目中复制到另一个项目
一个窗体有三个文件,全部拷贝到新的项目中 在新的项目中点击显示所有文件,然后右击导入的文件,点击包括在项目中,会自动修改颜色(此时还没有被识别为窗体) 重启这个项目,三个文件已经被识别出来了 ...
- C#程序如何把窗体文件从从一个项目中复制到另一个项目
一个窗体有三个文件,全部拷贝到新的项目中 在新的项目中点击显示所有文件,然后右击导入的文件,点击包括在项目中,会自动修改颜色(此时还没有被识别为窗体) 重启这个项目,三个文件已经被识别出来了 ...
- 在.net core web api项目中安装swagger展示api接口(相当于生成api文档)
1, 建立或打开项目后,在“程序包管理器控制台”中执行以下命令添加包引用: Install-Package Swashbuckle.AspNetCore 2,在项目中打开Startup.cs文件,找 ...
随机推荐
- Win7安装和配置Apache
一.版本介绍 首先,我们需要下载Apache2.4服务器:http://www.apachehaus.com/cgi-bin/download.plx#APACHE24VC14 关于现在那个版 ...
- 序列化表单数据$("form").serializeArray()
在做一个后台管理系统类似的项目中发现不能直接取得表单中的数值,于是想到先将表单数据转化为json,然后再用js从json中获取数据,那不就简单了吗? 于是我用了jquery的serializeArra ...
- POJ-1741 树上分治--点分治(算法太奇妙了)
给你1e5个节点的树,(⊙﹏⊙) 你能求出又几对节点的距离小于k吗??(分治NB!) 这只是一个板子题,树上分治没有简单题呀!(一个大佬说的) #include<cstdio> #incl ...
- 前端Tips#2 - 将 arguments 转换成Array的最佳实践
本文同步自 JSCON简时空 - 技术博客,点击阅读 视频讲解 文字讲解 1.先讲结论 有很多种方式将 arguments 转换成数组,那么哪一种方式是最优的? 为节约大伙儿的时间,这里先说一下结论: ...
- 【合集】有标号的DAG图计数(合集)
[合集]有标号的DAG图计数(合集) orz 1tst [题解]有标号的DAG计数1 [题解]有标号的DAG计数2 [题解]有标号的DAG计数3 [题解]有标号的DAG计数4
- $CF311B\ Cats\ Transport$ 斜率优化
AcWing Description Sol 设f[i][j]表示前i个饲养员接走前j只猫咪的最小等待时间. 要接到j猫咪,饲养员的最早出发时间是可求的,设为d: $ d[j]=Tj-\sum_{k= ...
- java通过freemarker模板导出pdf
需求:将网页内容导出为pdf文件,其中包含文字,图片,echarts图 原理:利用freemarker模板与数据渲染所得到的html内容,通过ITextRenderer对象解析html内容生成pdf ...
- 「学习笔记」动态规划 I『初识DP』
写在前面 注意:此文章仅供参考,如发现有误请及时告知. 更新日期:2018/3/16,2018/12/03 动态规划介绍 动态规划,简称DP(Dynamic Programming) 简介1 简介2 ...
- java基础之----非空判断
大家好,第一次写博客,一直想写博客,用于自我总结,也用于帮助新同学成长. 平常我们开发的时候,用到很多非空判断,但是很多同学用到的地方不是很准确,这里,我把自己平时遇到的坑跟大家说说.我废话不多,只想 ...
- Hadoop以及组件介绍
一.背景介绍 在接触过大数据相关项目的时候常常都会听到Hadoop这个东西,简单来说,他是一个用分布式计算来处理大数据的开源软件,下面包含了许多的组件和子项目,这篇文章将会介绍Hadoop的原理以及一 ...