一個優秀的分散式springboot/SpringCloudAPI限流框架,特別適合微服務架構
啥也不說了,上程式碼先:
-
https://github.com/tangaiyun/redislimiter-spring-boot
或者 - https://gitee.com/aiyuntang/redislimiter-spring-boot
redislimiter-spring-boot
一個優秀的分散式spring boot/Spring Cloud API限流框架,特別適合微服務架構.
快速開始
1. git clone https://github.com/tangaiyun/redislimiter-spring-boot.git
2. cd redislimiter-spring-boot-starter
3. mvn clean install
4. 新建一個Spring boot API 專案,具體參考demo1專案,要在專案依賴中加入
<dependency>
<groupId>com.tay</groupId>
<artifactId>redislimiter-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
5. 修改專案resources/application.yml檔案
server:
port: 8888 #埠
spring:
application:
name: demo1 #應用名稱必須要配置,不然無法啟動
redis-limiter: #限流器配置
redis-host: 127.0.0.1 #redis server ip
check-action-timeout: 100 #訪問檢查動作最大執行時間(單位毫秒)
enable-dynamical-conf: true #開啟動態限流配置
spring.application.name必須配置
6. 新建一個RestController類
package com.tay.demo1;
import com.tay.redislimiter.RateLimiter;
import com.tay.redislimiter.dynamic.DynamicRateLimiter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/demo")
public class DemoController {
@GetMapping("/test")
//基於使用者限流,獨立使用者每分鐘最多2次訪問,使用者id在header中,key為userid
//RateLimiter標籤為靜態配置,此類配置不可動態修改
@RateLimiter(base = "#Headers[`userid`]", permits = 2, timeUnit = TimeUnit.MINUTES)
public String test() {
return "test!";
}
@GetMapping("/dynamictest")
//基於來源ip限流,獨立ip每分鐘最多訪問5次訪問,來源ip位於header中,key為X-Real-IP
//DynamicRateLimiter標籤代表動態配置,此類配置可在執行時動態修改
@DynamicRateLimiter(base = "#Headers[`X-Real-IP`]", permits = 5, timeUnit = TimeUnit.MINUTES)
public String dynamicTest() {
return "dynamictest!";
}
}
7. 在本機安裝redis並啟動,強烈建議在本機安裝docker環境,然後執行
sudo docker run -d -p 6379:6379 redis
就是這麼爽氣!
8. 執行Demo1Application.java
9. 測試
通過postman或者restd訪問url http://localhost:8888/demo/test 在header中指定userid=tom, 可以發現tom一分鐘最多隻能訪問2次
通過postman或者restd訪問url http://localhost:8888/demo/dynamictest 在header中指定X-Real-IP=127.0.0.1, 可以發現127.0.0.1一分鐘最多隻能訪問5次
高階教程
1. 配置項大全
spring:
redis-limiter:
redis-host: 127.0.0.1 # redis server IP 預設值:127.0.0.1
redis-port: 6379 # redis service 埠 預設值:6379
redis-password: test # redis 訪問密碼 預設值:null
redis-connection-timeout: 2000 # redis 連線超時時間 預設值:2000
redis-pool-max-idle: 50 # redis 連線池最大空閒連線數 預設值:50
redis-pool-min-idle: 10 # redis 連線池最小空閒連線數 預設值: 10
redis-pool-max-wait-millis: -1 # 從連線池中獲取連線最大等待時間 預設值: -1
redis-pool-max-total: 200 # 連線池中最大連線數 預設值: 200
redis-key-prefix: #RL # 訪問痕跡key值字首 預設值: #RL
check-action-timeout: 100 # 訪問檢查動作最大執行時間(單位毫秒) 預設值: 100
enable-dynamical-conf: true # 是否開啟動態配置 預設值: false
channel: #RLConfigChannel # 配置變更事件傳送channel名稱 預設值: #RLConfigChannel
2 標籤
@RateLimiter, @DynamicRateLimiter 是使用者最經常使用到的。
2.1 標籤說明 –整體說明
@RateLimiter @DynamicRateLimiter 這兩個標籤用法完全一致,他們都有4個屬性base、path、timeUnit、permits.
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
public @interface RateLimiter {
String base() default "";
String path() default "";
TimeUnit timeUnit() default TimeUnit.SECONDS;
int permits() default 10000;
}
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
public @interface DynamicRateLimiter {
String base() default "";
String path() default "";
TimeUnit timeUnit() default TimeUnit.SECONDS;
int permits() default 10000;
}
2.2 標籤說明 — base引數(Spel表示式)說明
標籤都有一個屬性base,含義就是限流是”基於what”來進行的,如果你不指定base,那麼所有的請求都會聚合在一起統計,base為一個Spel表示式。
@RateLimiter(base = "#Headers[`userid`]", permits = 2, timeUnit = TimeUnit.MINUTES)
@DynamicRateLimiter(base = "#Headers[`X-Real-IP`]", permits = 5, timeUnit = TimeUnit.MINUTES)
目前base表示式僅支援從header和cookie中取值,Headers和Cookies就是兩個Map, 下面兩種配置都是合法的。
"#Headers[`X-Real-IP`]"
"#Cookies[`userid`]"
2.3 標籤使用 — path 引數說明
path 如果不設定預設值是””, 當path為””, 框架內部會把它改寫為request.getRequestURI(),一般情況下框架預設行為就OK了。但在一種情況下你可能需要設定path引數,就是RequestMapping的path裡面包含Path Parameters的情況,例如:
@GetMapping("/user/{userid}")
@DynamicRateLimiter(base = "#Headers[`X-Real-IP`]", path = "/user", permits = 5, timeUnit = TimeUnit.MINUTES)
public User get(@PathVariable String userid) {
User user ...
return user;
}
在這種情況下,我們一般不會基於”/user/001″這樣統計,所有訪問”/user/001″, “/user/002″的請求都會聚合到path “/user`上統計。
2.4 標籤使用 — timeUnit 引數說明
訪問統計時間單位,以下4種都是有效的:
TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS
2.5 標籤使用 — permits 引數說明
單位時間內允許訪問的次數
3. 動態配置
動態配置使用@DynamicRateLimiter標籤,動態配置含義就是在執行時可以動態修改限流配置,這個是通過提供內建配置訪問Rest API來實現的。
RestController
@RequestMapping("/limiterconfig")
@RequiredArgsConstructor
public final class LimiterConfigResource implements InitializingBean, ApplicationContextAware {
...
@PutMapping
public void update(@RequestBody LimiterConfig limiterConfig, HttpServletResponse response) throws IOException {
if(applicationName.equals(limiterConfig.getApplicationName())) {
publish(limiterConfig);
}
else {
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.getWriter().print("Bad request for updating limiter configuration!");
}
}
@GetMapping
public LimiterConfig get(@RequestParam("controller") String controller, @RequestParam("method")String method) {
String limiterConfigKey = controller + ":" + method;
return redisLimiterConfigProcessor.get(limiterConfigKey);
}
@DeleteMapping
public void delete(@RequestParam("controller") String controller, @RequestParam("method")String method) {
LimiterConfig limiterConfig = new LimiterConfig();
limiterConfig.setApplicationName(applicationName);
limiterConfig.setControllerName(controller);
limiterConfig.setMethodName(method);
limiterConfig.setDeleted(true);
publish(limiterConfig);
}
目前提供了修改(PUT), 查詢 (GET), 刪除(DELETE)三種操作。
對於demo1專案
我們可以通過 GET http://localhost:8888/limiterconfig?controller=DemoController&method=dynamicTest 來獲取限流配置,返回值為
{
"applicationName": "demo1",
"controllerName": "DemoController",
"methodName": "dynamicTest",
"baseExp": "#Headers[`userid`]",
"path": "",
"timeUnit": "MINUTES",
"permits": 5,
"deleted": false
}
通過指定Content-Type為application/json PUT http://localhost:8888/limiterconfig 來改動限流配置, 傳送內容如
{
"applicationName": "demo1",
"controllerName": "DemoController",
"methodName": "dynamicTest",
"baseExp": "#Headers[`userid`]",
"path": "",
"timeUnit": "MINUTES",
"permits": 10,
"deleted": false
}
通過 DELETE http://localhost:8888/limiterconfig?controller=DemoController&method=dynamicTest 可刪除限流配置
相關文章
- 分散式架構和微服務架構的區別分散式架構微服務
- 微服務分散式雲架構-springboot執行模式微服務分散式架構Spring Boot模式
- DTM:Golang中微服務架構的分散式事務框架Golang微服務架構分散式框架
- spring cloud springboot mybatis 分散式 微服務 架構原始碼CloudSpring BootMyBatis分散式微服務架構原始碼
- 【分散式架構】(10)---基於Redis元件的特性,實現一個分散式限流分散式架構Redis元件
- 分散式微服務架構(一)分散式微服務架構
- 微服務架構 | 11. 分散式事務微服務架構分散式
- 微服務架構下分散式session管理微服務架構分散式Session
- 微服務分散式架構之redis篇微服務分散式架構Redis
- (一)springcloud微服務分散式雲架構-SpringCloud簡介SpringGCCloud微服務分散式架構
- 微服務架構帶來的分散式單體微服務架構分散式
- 微服務架構中的分散式事務全面詳解 -DZone微服務微服務架構分散式
- 微服務架構分散式事務管理問題微服務架構分散式
- 微服務架構下分散式事務解決方案-hoop(一)微服務架構分散式OOP
- springcloud微服務分散式雲架構簡介SpringGCCloud微服務分散式架構
- 【分散式微服務企業快速架構】SpringCloud分散式、微服務、雲架構快速開發平臺分散式微服務架構SpringGCCloud
- Java架構-(一)spring cloud微服務分散式雲架構 - Spring Cloud簡介Java架構SpringCloud微服務分散式
- spring cloud微服務分散式雲架構--hystrix的使用SpringCloud微服務分散式架構
- 微服務架構及分散式事務解決方案微服務架構分散式
- springcloud微服務分散式雲架構-SpringCloud簡介SpringGCCloud微服務分散式架構
- (一)spring cloud微服務分散式雲架構 - Spring Cloud簡介SpringCloud微服務分散式架構
- (一)spring cloud微服務分散式雲架構-Spring Cloud簡介SpringCloud微服務分散式架構
- 阿里分散式服務框架Dubbo的架構總結阿里分散式框架架構
- 分散式、微服務必須配個日誌管理系統才優秀,Exceptionless走起~~~分散式微服務Exception
- spring cloud微服務分散式雲架構-Gateway入門SpringCloud微服務分散式架構Gateway
- spring cloud微服務分散式雲架構Spring Cloud ZuulSpringCloud微服務分散式架構Zuul
- spring cloud微服務分散式雲架構-Spring Cloud NetflixSpringCloud微服務分散式架構
- spring cloud微服務分散式雲架構-Spring Cloud BusSpringCloud微服務分散式架構
- spring cloud微服務分散式雲架構-Commons 普通抽象SpringCloud微服務分散式架構抽象
- SOA架構和微服務架構的區別架構微服務
- Spring Cloud微服務分散式雲架構 - 整合企業架構的技術點SpringCloud微服務分散式架構
- Kite: 一個分散式微服務框架(翻譯)分散式微服務框架
- Spring Cloud構建微服務架構:分散式配置中心(加密解密)SpringCloud微服務架構分散式加密解密
- spring cloud微服務分散式雲架構--服務註冊(consul)SpringCloud微服務分散式架構
- 微服務架構 | 11.1 整合 Seata AT 模式實現分散式事務微服務架構模式分散式
- spring cloud微服務分散式雲架構-Spring Cloud 分散式的五大重點SpringCloud微服務分散式架構
- Java程式設計微服務架構框架-監控與管理(SpringBoot)Java程式設計微服務架構框架Spring Boot
- (二)spring cloud微服務分散式雲架構 - 整合企業架構的技術點SpringCloud微服務分散式架構