Skip to content

Commit ad9a1d6

Browse files
committed
ApiBoot RateLimiter 修改为AOP方式实现
1 parent afa7139 commit ad9a1d6

File tree

9 files changed

+249
-164
lines changed

9 files changed

+249
-164
lines changed

api-boot-project/api-boot-plugins/api-boot-plugin-rate-limiter/pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<parent>
2323
<artifactId>api-boot-plugins</artifactId>
2424
<groupId>org.minbox.framework</groupId>
25-
<version>2.0.7.RELEASE</version>
25+
<version>2.0.8.RC1</version>
2626
</parent>
2727
<modelVersion>4.0.0</modelVersion>
2828
<artifactId>api-boot-plugin-rate-limiter</artifactId>
@@ -50,6 +50,11 @@
5050
<groupId>org.springframework.boot</groupId>
5151
<artifactId>spring-boot-starter-web</artifactId>
5252
</dependency>
53+
<!--SpringBoot Aop-->
54+
<dependency>
55+
<groupId>org.springframework.boot</groupId>
56+
<artifactId>spring-boot-starter-aop</artifactId>
57+
</dependency>
5358
<!--SpringBoot Data Redis-->
5459
<dependency>
5560
<groupId>org.springframework.boot</groupId>

api-boot-project/api-boot-plugins/api-boot-plugin-rate-limiter/src/main/java/org/minbox/framework/api/boot/plugin/rate/limiter/ApiBootRateLimiter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ public interface ApiBootRateLimiter {
3333
* Attempt to obtain a request current limit token
3434
*
3535
* @param QPS queries per second
36-
* @param requestUri request uri
36+
* @param requestKey request key
3737
* @return true : allow access to
3838
*/
39-
boolean tryAcquire(Double QPS, String requestUri);
39+
boolean tryAcquire(Double QPS, String requestKey);
4040
}

api-boot-project/api-boot-plugins/api-boot-plugin-rate-limiter/src/main/java/org/minbox/framework/api/boot/plugin/rate/limiter/ApiBootRateLimiterConfiguration.java

Lines changed: 0 additions & 64 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright [2019] [恒宇少年 - 于起宇]
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package org.minbox.framework.api.boot.plugin.rate.limiter.aop.advisor;
19+
20+
import org.aopalliance.aop.Advice;
21+
import org.minbox.framework.api.boot.plugin.rate.limiter.annotation.RateLimiter;
22+
import org.minbox.framework.api.boot.plugin.rate.limiter.aop.interceptor.ApiBootRateLimiterMethodInterceptor;
23+
import org.springframework.aop.Pointcut;
24+
import org.springframework.aop.support.AbstractPointcutAdvisor;
25+
import org.springframework.aop.support.ComposablePointcut;
26+
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
27+
import org.springframework.beans.BeansException;
28+
import org.springframework.beans.factory.BeanFactory;
29+
import org.springframework.beans.factory.BeanFactoryAware;
30+
import org.springframework.util.Assert;
31+
32+
/**
33+
* ApiBoot RateLimiter Advisor
34+
*
35+
* @author:恒宇少年 - 于起宇
36+
* <p>
37+
* DateTime:2019-05-09 16:03
38+
* Blog:http://blog.yuqiyu.com
39+
* WebSite:http://www.jianshu.com/u/092df3f77bca
40+
* Gitee:https://gitee.com/hengboy
41+
* GitHub:https://github.com/hengboy
42+
*/
43+
public class ApiBootRateLimiterAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
44+
private Advice advice;
45+
private Pointcut pointcut;
46+
private BeanFactory beanFactory;
47+
48+
public ApiBootRateLimiterAdvisor(ApiBootRateLimiterMethodInterceptor apiBootRateLimiterMethodInterceptor) {
49+
// build pointcut instance
50+
this.pointcut = buildPointcut();
51+
// build advice instance
52+
this.advice = apiBootRateLimiterMethodInterceptor;
53+
if (this.advice instanceof BeanFactoryAware) {
54+
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
55+
}
56+
}
57+
58+
@Override
59+
public Pointcut getPointcut() {
60+
Assert.notNull(this.pointcut, "pointcut is required.");
61+
return this.pointcut;
62+
}
63+
64+
@Override
65+
public Advice getAdvice() {
66+
Assert.notNull(this.advice, "advice is required.");
67+
return this.advice;
68+
}
69+
70+
@Override
71+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
72+
this.beanFactory = beanFactory;
73+
}
74+
75+
/**
76+
* build pointcut instance
77+
*/
78+
private Pointcut buildPointcut() {
79+
// method
80+
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(RateLimiter.class);
81+
return new ComposablePointcut(mpc);
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright [2019] [恒宇少年 - 于起宇]
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package org.minbox.framework.api.boot.plugin.rate.limiter.aop.interceptor;
19+
20+
import org.aopalliance.intercept.MethodInterceptor;
21+
import org.aopalliance.intercept.MethodInvocation;
22+
import org.minbox.framework.api.boot.plugin.rate.limiter.ApiBootRateLimiter;
23+
import org.minbox.framework.api.boot.plugin.rate.limiter.annotation.RateLimiter;
24+
import org.minbox.framework.api.boot.plugin.tools.AopTools;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
import org.springframework.aop.support.AopUtils;
28+
import org.springframework.util.Assert;
29+
30+
import java.lang.reflect.Method;
31+
32+
/**
33+
* ApiBoot RateLimiter MethodInterceptor
34+
* Current Limitation Request
35+
*
36+
* @author:恒宇少年 - 于起宇
37+
* <p>
38+
* DateTime:2019-05-09 16:01
39+
* Blog:http://blog.yuqiyu.com
40+
* WebSite:http://www.jianshu.com/u/092df3f77bca
41+
* Gitee:https://gitee.com/hengboy
42+
* GitHub:https://github.com/hengboy
43+
*/
44+
public class ApiBootRateLimiterMethodInterceptor implements MethodInterceptor {
45+
/**
46+
* logger instance
47+
*/
48+
static Logger logger = LoggerFactory.getLogger(ApiBootRateLimiterMethodInterceptor.class);
49+
/**
50+
* ApiBoot RateLimiter
51+
*/
52+
private ApiBootRateLimiter apiBootRateLimiter;
53+
54+
public ApiBootRateLimiterMethodInterceptor(ApiBootRateLimiter apiBootRateLimiter) {
55+
this.apiBootRateLimiter = apiBootRateLimiter;
56+
Assert.notNull(apiBootRateLimiter, "No ApiBootRateLimiter implementation class instance.");
57+
logger.info("ApiBootDefaultRateLimiterInterceptorHandler load complete.");
58+
}
59+
60+
/**
61+
* Processing Current Limited Business Logic
62+
*
63+
* @param invocation method invocation
64+
* @return method result
65+
* @throws Throwable error instance
66+
*/
67+
@Override
68+
public Object invoke(MethodInvocation invocation) throws Throwable {
69+
try {
70+
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
71+
Method executeMethod = invocation.getMethod();
72+
73+
RateLimiter rateLimiter = AopTools.getMethodAnnotation(targetClass, executeMethod, RateLimiter.class);
74+
75+
// request key
76+
String requestKey = formatRequestKey(targetClass, executeMethod);
77+
logger.debug("RateLimiter Request Key:{}", requestKey);
78+
boolean acquire = apiBootRateLimiter.tryAcquire(rateLimiter.QPS(), requestKey);
79+
if (acquire) {
80+
return invocation.proceed();
81+
}
82+
} catch (Exception e) {
83+
logger.error("Current Limiting Request Encountered Exception.", e);
84+
}
85+
return null;
86+
}
87+
88+
/**
89+
* format request key
90+
*
91+
* @param targetClass target class
92+
* @param executeMethod execute method
93+
* @return request key
94+
*/
95+
private String formatRequestKey(Class<?> targetClass, Method executeMethod) {
96+
return String.format("%s#%s", targetClass.getName(), executeMethod.getName());
97+
}
98+
}

api-boot-project/api-boot-plugins/api-boot-plugin-rate-limiter/src/main/java/org/minbox/framework/api/boot/plugin/rate/limiter/handler/ApiBootDefaultRateLimiterInterceptorHandler.java

Lines changed: 0 additions & 89 deletions
This file was deleted.

api-boot-project/api-boot-plugins/api-boot-plugin-rate-limiter/src/main/java/org/minbox/framework/api/boot/plugin/rate/limiter/support/GoogleGuavaRateLimiter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ public GoogleGuavaRateLimiter(Long globalQPS, RateLimiterConfigCentre rateLimite
4040
* google guava away
4141
*
4242
* @param annotationQPS RateLimiter QPS value
43-
* @param requestUri request uri
43+
* @param requestKey request key
4444
* @return true : allow access to
4545
*/
4646
@Override
47-
public boolean tryAcquire(Double annotationQPS, String requestUri) {
48-
Long QPS = getPriorityQPS(requestUri, annotationQPS);
47+
public boolean tryAcquire(Double annotationQPS, String requestKey) {
48+
Long QPS = getPriorityQPS(requestKey, annotationQPS);
4949
if (QPS <= 0) {
5050
return true;
5151
}
52-
com.google.common.util.concurrent.RateLimiter rateLimiter = ApiBootRateLimiterContext.cacheRateLimiter(requestUri, QPS);
52+
com.google.common.util.concurrent.RateLimiter rateLimiter = ApiBootRateLimiterContext.cacheRateLimiter(requestKey, QPS);
5353
return rateLimiter.tryAcquire();
5454
}
5555
}

0 commit comments

Comments
 (0)