- 前面我们已经说了WebFlux集成sentinel,此集成在gateway中同样适用.
- gateway集成sentinel开发包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
-
sentinel中可以做为 resource 的资源
- 网关中 的 route.id
- 自定义api分组
- 链接
-
接下来我们 自定义 api分组,限流规则及异常处理器
package com.cloud.alibaba.config.sentinel.gateway;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import javax.annotation.PostConstruct;
import java.util.*;
/**
* 限流规则配置类
*
* @author admin
*/
@Configuration
public class GatewayConfiguration {
@PostConstruct
public void doInit() {
// 自定义api分组
initCustomizedApis();
// 加载网关限流规则
initGatewayRules();
// 加载自定义限流异常处理器
initBlockHandler();
}
/**
* 自定义api分组
*/
private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();
// product-api 组
ApiDefinition api1 = new ApiDefinition("producer-example-api")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/producer/**")
/**
* 网址匹配策略前缀 /producer 和 /producer/**
*/
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
/**
* 只匹配/producer/getUser
*/
add(new ApiPathPredicateItem().setPattern("/producer/getUser"));
}});
definitions.add(api1);
/**
* 加载限流分组
*/
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
/**
* 网关限流规则
*/
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
/**
* PARAM_PARSE_STRATEGY_URL_PARAM 参数提取策略 任意 URL 参数
* PARAM_MATCH_STRATEGY_CONTAINS 匹配规则 URL 参数中是否包含 FieldName。示例中是type字段
* 通俗讲就是 如果url携带type参数。将走此规则。否则不走此规则
* 示例 http://192.168.1.25:10004/producer/getUserName?type=1 走此规则
* 示例 http://192.168.1.25:10004/producer/getUserName 不走此规则
* 其余的规则 参考 https://github.com/alibaba/Sentinel/blob/master/sentinel-demo/sentinel-demo-spring-cloud-gateway/src/main/java/com/alibaba/csp/sentinel/demo/spring/sc/gateway/GatewayConfiguration.java
*/
rules.add(new GatewayFlowRule("producer-example-api")
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setGrade(1)
.setCount(1)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("type")
.setMatchStrategy(SentinelGatewayConstants.PARAM_MATCH_STRATEGY_CONTAINS)
)
);
GatewayRuleManager.loadRules(rules);
}
/**
* 自定义限流异常处理器
*/
private void initBlockHandler() {
BlockRequestHandler blockRequestHandler = (serverWebExchange, throwable) -> {
ParamFlowException paramFlowException = (ParamFlowException) throwable;
Map<String, String> result = new HashMap<>(3);
result.put("state", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
result.put("msg", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
result.put("route", paramFlowException.getResourceName());
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(result));
};
// 加载自定义限流异常处理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}