Spring?Cloud?Gateway服務(wù)網(wǎng)關(guān)限流問題及解決
網(wǎng)關(guān)是所有請求的公共入口,所以可以在網(wǎng)關(guān)進(jìn)行限流,而且限流的方式也很多,我們本次采用前面學(xué)過的 Sentinel 組件來實(shí)現(xiàn)網(wǎng)關(guān)的限流。
Sentinel 支持對 SpringCloud Gateway、Zuul等主流網(wǎng)關(guān)進(jìn)行限流。

從1.6.0版本開始,Sentinel提供了SpringCloud Gateway的適配模塊,可以提供兩種資源維度的限流:
- route維度:即在Spring配置文件中配置的路由條目,資源名為對應(yīng)的routeld;
- 自定義API維度:用戶可以利用Sentinel提供的API來自定義一些API分組;
route限流
導(dǎo)入依賴
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> </dependency>
編寫配置類
基于Sentinel的Gateway限流是通過其提供的Filter來完成的,使用時只需注入對應(yīng)的SentinelGatewayFilter實(shí)例以及SentinelGatewayBlockExceptionHandler實(shí)例即可。
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
//初始化一個限流的過濾器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
//配置初始化的限流參數(shù)
@PostConstruct
public void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("shop-product")//資源名稱,對應(yīng)路由id
.setCount(1)//限流閥值
.setIntervalSec(1)//統(tǒng)計(jì)時間窗口,單位是秒,默認(rèn)是1秒
);
GatewayRuleManager.loadRules(rules);
}
//配置限流異常處理器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
//自定義限流異常頁面
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map= new HashMap<>();
map.put("code", 0);
map.put("message", "接口被限流了");
return ServerResponse
.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(BodyInserters.fromObject(map));
}
} ;
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}其中,GatewayFlowRule 網(wǎng)關(guān)限流規(guī)則中提供了如下屬性:
resource:資源名稱,可以是網(wǎng)關(guān)中的route名稱或者用戶自定義的API分組名稱。resourceMode:資源模型,限流規(guī)則是針對API Gateway的 route(RESOURCE_MODE_ROUTE_ID)還是用戶在Sentinel 中定義的API分組(RESOURCE_MODE_CUSTOM_API_NAME),默認(rèn)route。grade:限流指標(biāo)維度,同限流規(guī)則的 grade 字段。count:限流閾值。intervalSec:統(tǒng)計(jì)時間窗口,單位是秒, 默認(rèn)是1 秒。controlBehavior:流量整形的控制效果,同限流規(guī)則的controlBehavior字段,目前支持快速失敗和勻速排隊(duì)兩種模式,默認(rèn)快速失敗。burst:應(yīng)對突發(fā)請求時額外允許的請求數(shù)目。maxQueueingTimeoutMs:勻速排隊(duì)模式下的最長排隊(duì)時間,單位是毫秒,僅在勻速排隊(duì)模式下生效。paramItem:參數(shù)限流配置。若不提供,則代表針對參數(shù)進(jìn)行限流,該網(wǎng)關(guān)規(guī)則將會被轉(zhuǎn)換成普通流控規(guī)則;否則會轉(zhuǎn)換熱點(diǎn)規(guī)則。其中的字段如下:arseStrategy:從請求中提取參數(shù)的策略,目前支持提取來源IP(PARAM_PARSE_STRATEGY_CLIENT_IP)、Host(PARAM_PARSE_STRATEGY_HOST)、任意Header(PARAM_PARSE_STRATEGY_HEADER)和任意URL 參數(shù)(PARAM_PARSE_STRATEGY_URL_PARAM)四種模式。fieldName:若提取策略選擇Header模式或者URL參數(shù)模式,則需要指定對應(yīng)的Header名稱或URL參數(shù)名稱。pattern和matchStrategy:為后續(xù)參數(shù)匹配特性預(yù)留,目前末實(shí)現(xiàn)。
測試
在一秒鐘內(nèi)多次訪問http://localhost:7000/product/product/1?token=1232就可以看到限流啟作用了。

自定義API分組
自定義API分組是一種更細(xì)粒度的限流規(guī)則定義
//配置初始化的限流參數(shù)
@PostConstruct
public void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("shop_product_api").setCount(1).setIntervalSec(1));
rules.add(new GatewayFlowRule("shop_order_api").setCount(1).setIntervalSec(1));
GatewayRuleManager.loadRules(rules);
}
//自定義API分組
@PostConstruct
private void initCustomizedApis(){
Set<ApiDefinition> definitions = new HashSet<>();
//定義小組1
ApiDefinition api1 = new ApiDefinition("shop_product_api")
.setPredicateItems(new HashSet<ApiPredicateItem>(){{
//以/product/product/api1開頭的請求
add(new ApiPathPredicateItem().setPattern("/product/product/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
//定義小組2
ApiDefinition api2 = new ApiDefinition("shop_order_api")
.setPredicateItems(new HashSet<ApiPredicateItem>(){{
//完全匹配/order/order2/message
add(new ApiPathPredicateItem().setPattern("/order/order2/message"));
}});
definitions.add(api1);
definitions.add(api2);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}在一秒鐘內(nèi)多次訪問http://localhost:7000/product/product/1?token=1232也可以看到限流啟作用了。

總結(jié)
到這兒,Gateway 服務(wù)網(wǎng)關(guān)限流的內(nèi)容就已經(jīng)介紹完了。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring+springmvc整合mabytis時mapper注入失敗問題解決方法
這篇文章主要介紹了spring+springmvc整合mabytis時mapper注入失敗問題解決方法 ,需要的朋友可以參考下2017-08-08
解決IDEA Gradle構(gòu)建報(bào)錯''Cause: zip END header not found''
這篇文章主要介紹了解決IDEA Gradle構(gòu)建報(bào)錯"Cause: zip END header not found"的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
Java程序設(shè)計(jì)之12個經(jīng)典樣例
這篇文章主要給大家分享關(guān)于Java程序設(shè)計(jì)11個經(jīng)典樣例,主要以舉例的形式詳細(xì)的講解了Java程序設(shè)計(jì)的各種方法,需要的朋友可以參考一下文章具體的內(nèi)容2021-10-10
Sublime Text 打開Java文檔中文亂碼的解決方案
這篇文章主要介紹了Sublime Text 中文亂碼的解決方案,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12

