Skip to content

Commit 09ac22c

Browse files
committed
ApiBoot Rate Limiter 插件
1 parent 46792cc commit 09ac22c

File tree

6 files changed

+291
-0
lines changed

6 files changed

+291
-0
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545
<groupId>com.google.guava</groupId>
4646
<artifactId>guava</artifactId>
4747
</dependency>
48+
<!--SpringBoot Web-->
49+
<dependency>
50+
<groupId>org.springframework.boot</groupId>
51+
<artifactId>spring-boot-starter-web</artifactId>
52+
</dependency>
4853
</dependencies>
4954

5055
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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;
19+
20+
import org.minbox.framework.api.boot.plugin.rate.limiter.config.RateLimiterConfig;
21+
import org.springframework.util.Assert;
22+
import org.springframework.web.servlet.HandlerInterceptor;
23+
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
24+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
25+
26+
/**
27+
* ApiBoot RateLimiter Configuration
28+
*
29+
* @author:恒宇少年 - 于起宇
30+
* <p>
31+
* DateTime:2019-04-26 11:07
32+
* Blog:http://blog.yuqiyu.com
33+
* WebSite:http://www.jianshu.com/u/092df3f77bca
34+
* Gitee:https://gitee.com/hengboy
35+
* GitHub:https://github.com/hengboy
36+
*/
37+
public class ApiBootRateLimiterConfiguration implements WebMvcConfigurer {
38+
/**
39+
* rate limiter config
40+
*/
41+
private RateLimiterConfig rateLimiterConfig;
42+
/**
43+
* spring mvc interceptor
44+
*/
45+
private HandlerInterceptor handlerInterceptor;
46+
47+
/**
48+
* init instance
49+
*
50+
* @param rateLimiterConfig rate limiter config
51+
* @param handlerInterceptor rate limiter interceptor
52+
*/
53+
public ApiBootRateLimiterConfiguration(RateLimiterConfig rateLimiterConfig, HandlerInterceptor handlerInterceptor) {
54+
this.rateLimiterConfig = rateLimiterConfig;
55+
this.handlerInterceptor = handlerInterceptor;
56+
Assert.notNull(rateLimiterConfig, "RateLimiterConfig can not be null.");
57+
Assert.notNull(rateLimiterConfig, "HandlerInterceptor can not be null.");
58+
}
59+
60+
@Override
61+
public void addInterceptors(InterceptorRegistry registry) {
62+
registry.addInterceptor(handlerInterceptor).addPathPatterns(rateLimiterConfig.getInterceptorUrl());
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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.annotation;
19+
20+
import java.lang.annotation.*;
21+
22+
/**
23+
* ApiBoot Rate Limiter Annotation
24+
* Configure to intercept request method
25+
*
26+
* @author:恒宇少年 - 于起宇
27+
* <p>
28+
* DateTime:2019-04-26 11:23
29+
* Blog:http://blog.yuqiyu.com
30+
* WebSite:http://www.jianshu.com/u/092df3f77bca
31+
* Gitee:https://gitee.com/hengboy
32+
* GitHub:https://github.com/hengboy
33+
*/
34+
@Retention(RetentionPolicy.RUNTIME)
35+
@Target({ElementType.METHOD})
36+
@Documented
37+
public @interface RateLimiter {
38+
/**
39+
* QPS(Access frequency per second)
40+
* default once a second
41+
*
42+
* @return qps value
43+
*/
44+
double qps() default 1;
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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.config;
19+
20+
import lombok.Data;
21+
22+
/**
23+
* ApiBoot RateLimiter Config
24+
*
25+
* @author:恒宇少年 - 于起宇
26+
* <p>
27+
* DateTime:2019-04-26 10:48
28+
* Blog:http://blog.yuqiyu.com
29+
* WebSite:http://www.jianshu.com/u/092df3f77bca
30+
* Gitee:https://gitee.com/hengboy
31+
* GitHub:https://github.com/hengboy
32+
*/
33+
@Data
34+
public class RateLimiterConfig {
35+
/**
36+
* interceptor url prefix
37+
*/
38+
private String[] interceptorUrl;
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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.context;
19+
20+
import com.google.common.util.concurrent.RateLimiter;
21+
import org.springframework.util.ObjectUtils;
22+
23+
import java.util.concurrent.ConcurrentHashMap;
24+
import java.util.concurrent.ConcurrentMap;
25+
26+
/**
27+
* ApiBoot Rate Limiter Context
28+
*
29+
* @author:恒宇少年 - 于起宇
30+
* <p>
31+
* DateTime:2019-04-26 13:36
32+
* Blog:http://blog.yuqiyu.com
33+
* WebSite:http://www.jianshu.com/u/092df3f77bca
34+
* Gitee:https://gitee.com/hengboy
35+
* GitHub:https://github.com/hengboy
36+
*/
37+
public class ApiBootRateLimiterContext {
38+
/**
39+
* Cache a rateLimiter for each request address
40+
*/
41+
private static final ConcurrentMap<String, RateLimiter> RATE_LIMITER_MAP = new ConcurrentHashMap();
42+
43+
/**
44+
* get rate limiter
45+
*
46+
* @param requestUri request uri
47+
* @return RateLimiter
48+
*/
49+
public static RateLimiter getRateLimiter(String requestUri) {
50+
return RATE_LIMITER_MAP.get(requestUri);
51+
}
52+
53+
/**
54+
* cache request uri rate limiter
55+
*
56+
* @param requestUri request uri
57+
* @param qps qps
58+
* @return RateLimiter
59+
*/
60+
public static RateLimiter cacheRateLimiter(String requestUri, double qps) {
61+
RateLimiter rateLimiter = getRateLimiter(requestUri);
62+
if (ObjectUtils.isEmpty(rateLimiter)) {
63+
rateLimiter = RateLimiter.create(qps);
64+
RATE_LIMITER_MAP.put(requestUri, rateLimiter);
65+
}
66+
return rateLimiter;
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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.handler;
19+
20+
import org.minbox.framework.api.boot.plugin.rate.limiter.annotation.RateLimiter;
21+
import org.minbox.framework.api.boot.plugin.rate.limiter.context.ApiBootRateLimiterContext;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
import org.springframework.web.method.HandlerMethod;
25+
import org.springframework.web.servlet.HandlerInterceptor;
26+
27+
import javax.servlet.http.HttpServletRequest;
28+
import javax.servlet.http.HttpServletResponse;
29+
30+
/**
31+
* ApiBoot Default Rate Limiter Interceptor Implement
32+
*
33+
* @author:恒宇少年 - 于起宇
34+
* <p>
35+
* DateTime:2019-04-26 10:50
36+
* Blog:http://blog.yuqiyu.com
37+
* WebSite:http://www.jianshu.com/u/092df3f77bca
38+
* Gitee:https://gitee.com/hengboy
39+
* GitHub:https://github.com/hengboy
40+
*/
41+
public class ApiBootDefaultRateLimiterInterceptorHandler implements HandlerInterceptor {
42+
/**
43+
* logger instance
44+
*/
45+
static Logger logger = LoggerFactory.getLogger(ApiBootDefaultRateLimiterInterceptorHandler.class);
46+
47+
/**
48+
* Executing traffic restrictions
49+
*
50+
* @param request http request
51+
* @param response http response
52+
* @param handler method handler
53+
* @return true:pass,false:intercept
54+
* @throws Exception Method Execute Exception
55+
*/
56+
@Override
57+
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
58+
try {
59+
HandlerMethod handlerMethod = (HandlerMethod) handler;
60+
// get method declared RateLimiter
61+
RateLimiter rateLimiterAnnotation = handlerMethod.getMethodAnnotation(RateLimiter.class);
62+
com.google.common.util.concurrent.RateLimiter rateLimiter = ApiBootRateLimiterContext.cacheRateLimiter(request.getRequestURI(), rateLimiterAnnotation.qps());
63+
double acquire = rateLimiter.acquire();
64+
logger.debug("ApiBoot rate limiter acquire:{}", acquire);
65+
} catch (Exception e) {
66+
return false;
67+
}
68+
return true;
69+
}
70+
}

0 commit comments

Comments
 (0)