irpas技术客

spring cloud gateway整合sentinel + nacos 实现网关限流和持久化动态配置_隆咚强_gateway sentinel

大大的周 1381

Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。 从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

Sentinel 1.6.0 引入了 Sentinel API Gateway Adapter Common 模块,此模块中包含网关限流的规则和自定义 API 的实体和管理逻辑:

GatewayFlowRule :网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的 限流。 ApiDefinition :用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以 定义一个 API 叫 customized_api ,请求 path 模式为 /api/v8/**, /api/v5/ 的匹配路径都归到 customized_api 这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。

这篇文章主要介绍了spring cloud gateway整合sentinel实现网关限流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下,Spring Cloud Gateway工程的搭建和Nacos的搭建不在这里讲述。

说明: sentinel可以作为各微服务的限流(点击查看),也可以作为gateway网关的限流组件。 spring cloud gateway有限流功能,但此处用sentinel来作为替待。

说明:sentinel流控可以放在gateway网关端,也可以放在各微服务端。

1、sentinel_dashboard的引入

下载sentinel-dashboard-1.6.3.jar 由于dashboard是springboot的项目,在CMD模式下使用命令 java -Dserver.port=8090 -Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=sentinel-dashboard -jar F:\workspace\sentinel\sentinel-dashboard-1.6.3.jar

-Dcsp.sentinel.app.type=1 表示 Sentinel 网关类型

浏览器访问地址:http://localhost:8090/#/login 登录后看到菜单有 “API管理“ 表示成功启动了Sentinel网关类型的控制台 2、Spring cloud gateway服务引入Nacos,Sentinel 依赖包(注意版本)

<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> <version>1.6.3</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-transport-simple-http</artifactId> <version>1.7.2</version> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> <version>1.8.0</version> </dependency>

Spring cloud gateway服务添加Nacos 相关配置

spring: application: # 应用名称 name: gateway-master cloud: nacos: discovery: server-addr: localhost:8848 gateway: httpclient: pool: max-idle-time: 10000 discovery: locator: enabled: true

Spring cloud gateway服务增加Sentinel配置类

@Configuration public class GatewaySentinelConfiguration { private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewaySentinelConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } /** * 配置SentinelGatewayBlockExceptionHandler,限流后异常处理 * * @return */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } // 自定义限流异常页面 @PostConstruct public void initBlockHandlers() { BlockRequestHandler blockRequestHandler = new BlockRequestHandler() { public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { Map result = new HashMap(); result.put("Suc","false"); result.put("ErrCode",0); result.put("Info","接口被限流了"); return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(result)); } }; GatewayCallbackManager.setBlockHandler(blockRequestHandler); } /** * 配置SentinelGatewayFilter * * @return */ @Bean @Order(-1) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } }

3、进入nacos控制台-配置列表添加配置

dataId: sentinel-gateway-rules groupId: sentinel

[ { "resource": "api-v8-order1", "resourceMode": 0, "count": 1, "intervalSec": 10 }, { "resource": "customized_api", "resourceMode": 1, "pattern": "/api/v5/**", "count": 1, "intervalSec": 10 } ]

resource: 资源名称 resourceMode: 资源模式 0-路由ID模式 1-自定义API模式 count:限流阈值 intervalSec: 统计时间窗口,单位是秒,默认是 1 秒 pattern: 自定义API模式下的限流资源路径 Spring cloud gateway服务添加Nacos配置监听类,服务启动自动加载Nacos已有的限流配置

@Component public class DynamicFlowRulesServiceImplByNacos implements CommandLineRunner { protected static final Logger log = LoggerFactory.getLogger(DynamicFlowRulesServiceImplByNacos.class); @Autowired private NacosGatewayProperties nacosGatewayProperties; private ConfigService configService; /** * 监听Nacos Server下发的动态配置 */ public void dynamicByNacosListener() { if (configService == null) { try { configService = NacosFactory.createConfigService(nacosGatewayProperties.getAddress()); } catch (NacosException e) { e.printStackTrace(); } } sentinelConfigByNacosListener(); } /** * 网关动态配置基础信息 */ public void sentinelConfigByNacosListener() { try { String dataId = "sentinel-gateway-rules"; String groupId = "sentinel"; String fristConfigInfo = configService.getConfigAndSignListener(dataId, groupId, 5000, new Listener() { @Override public void receiveConfigInfo(String configInfo) { addListenerByConfig(dataId, groupId, configInfo); } @Override public Executor getExecutor() { return null; } }); addListenerByConfig(dataId, groupId, fristConfigInfo); } catch (NacosException e) { e.printStackTrace(); } } /** * */ public void addListenerByConfig(String dataId, String groupId, String configInfo) { log.info("DataId:" + dataId + ",GroupId:" + groupId + ",监听器获取的nacos-sentinel流控配置信息:" + configInfo); //配置删除或不存在 if (configInfo == null) { initDefultGatewaySentinelRules(); return; } List<GatewaySentinelConfig> gatewaySentinelConfigs = null; try { gatewaySentinelConfigs = new Gson().fromJson(configInfo, new TypeToken<List<GatewaySentinelConfig>>() { }.getType()); } catch (JsonSyntaxException e) { log.error("JsonSyntaxException", e, e.getMessage()); } if (gatewaySentinelConfigs == null || gatewaySentinelConfigs.size() == 0) { return; } //加载流控规则 initGatewaySentinelRules(gatewaySentinelConfigs); } public void initGatewaySentinelRules(List<GatewaySentinelConfig> gatewaySentinelConfigs) { Set<GatewayFlowRule> rules = new HashSet<>(); Set<ApiDefinition> definitions = new HashSet<>(); for (GatewaySentinelConfig sentinelConfig : gatewaySentinelConfigs) { rules.add(new GatewayFlowRule(sentinelConfig.resource) .setResourceMode(sentinelConfig.resourceMode) .setCount(sentinelConfig.count) // 限流阈值 .setIntervalSec(sentinelConfig.intervalSec) // 统计时间窗口,单位是秒,默认是 1 秒 ); if (sentinelConfig.resourceMode == 1) { //自定义API模式 ApiDefinition api1 = new ApiDefinition(sentinelConfig.resource).setPredicateItems(new HashSet<ApiPredicateItem>() {{ if (sentinelConfig.pattern.contains("**")) { //前缀匹配 add(new ApiPathPredicateItem().setPattern(sentinelConfig.pattern).setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); } }}); definitions.add(api1); } } GatewayApiDefinitionManager.loadApiDefinitions(definitions); GatewayRuleManager.loadRules(rules); } //配置删除,初始化一个默认规则 public void initDefultGatewaySentinelRules() { Set<GatewayFlowRule> rules = new HashSet<>(); rules.add(new GatewayFlowRule("no-rule") .setResourceMode(0) .setCount(10000000) // 限流阈值 .setIntervalSec(1)); // 统计时间窗口,单位是秒,默认是 1 秒 GatewayRuleManager.loadRules(rules); } @Override public void run(String... args) throws Exception { dynamicByNacosListener(); } }

4、启动Spring cloud gateway服务 增加系统启动参数:-Dcsp.sentinel.app.type=1 -Dcsp.sentinel.dashboard.server=localhost:8090 -Dproject.name=gateway-sentinel

-Dcsp.sentinel.app.type=1 Sentinel 网关类型 -Dcsp.sentinel.dashboard.server=localhost:8090 限流控制服务地址 -Dproject.name=gateway-sentinel 注册到限流服务控制的项目名称

5、连续访问接口地址验证限流

出现以下信息表示限流成功 查看Sentinel控制台流控规则

6、Nacos配置中心修改限流规则验证动态加载配置 idea控制台会输出监听到的新配置 Sentinel控制台查看规则是否自动更新 以上就是本文的全部内容,希望对大家的学习有所帮助。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #gateway #Sentinel #支持对 #Spring #Cloud #GatewayZuul #等主流的