sentinel 网关限流
基本使用配置
-
需要引入的包
本人用的版本:spring cloud Hoxton.SR11 spring cloud alibaba 2.2.6.RELEASE
不同版本可能会导致sentinel无法加载nacos配置的流控规则的奇怪bug
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--支持从nacos中获取流控规则和api规则--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
-
启动sentinel控制台
这里使用的sentinel-dashboard-1.8.0.jar
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar
-
网关中的配置如下 aplication.yml
这里配置了两个datasource,一个加载网关流控规则,一个加载网关自定义api
代码中会根据rule-type来区分,gw-flow表示网关流控规则 ,gw-api-group表示自定义api
server: port: 8082 spring: cloud: gateway: enabled: true discovery: locator: lower-case-service-id: true routes: - id: httpbin_route uri: http://aiforcare.com/ predicates: - Path=/** sentinel: datasource: ds1: #从nacos读取流控规则 nacos: server-addr: 192.168.1.28:8848 data-id: sentinel.json group-id: DEFAULT_GROUP data-type: json rule-type: gw-flow namespace: 3d55ade7-7100-400d-a707-eafdaa58f41d ds2: #从nacos读取api-definition nacos: server-addr: 192.168.1.28:8848 data-id: api-group.json group-id: DEFAULT_GROUP data-type: json rule-type: gw-api-group namespace: 3d55ade7-7100-400d-a707-eafdaa58f41d
-
nacos中配置 注意要用数组
sentinel.json
[ { "burst": 0, "controlBehavior": 0, //0-表示快速失败 "count": 10.0, "grade": 1, //按qps限流 "intervalSec": 1, "maxQueueingTimeoutMs": 500, "paramItem": { "index": 0, "matchStrategy": 0, "parseStrategy": 0 }, "resource": "cos", //api名称 "resourceMode": 1 } ]
api-group.json
[ { "apiName": "cos1", //api名称 "predicateItems": [ { "matchStrategy": 0, //精确匹配 "pattern": "/acl/user/user2" } ] }, { "apiName": "cos", "predicateItems": [ { "matchStrategy": 0, "pattern": "/order/userOrder/view" } ] } ]
-
网关服务启动配置参数
-Dcsp.sentinel.dashboard.server=127.0.0.1:8080 #sentinel控制台地址 -Dproject.name=springcloud-gateway #应用名称 -Dcsp.sentinel.api.port=8888 #sentinel控制台与客户端连接的端口 -Dcsp.sentinel.app.type=1 #1表示是网关流控 这个必须设置 很重要
怎么实现sentinel控制台配置持久化到nacos中
如果没有做持久化,每次服务重启会导致之前在sentinel控制台配置的全部消失,因为它只是保存在内存中
实现代码如下
-
自定义一个WritableDataSource
package com.gaorong.orm; import com.alibaba.csp.sentinel.datasource.WritableDataSource; import com.alibaba.fastjson.JSON; import com.alibaba.nacos.api.NacosFactory; import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.exception.NacosException; import lombok.extern.slf4j.Slf4j; import java.util.Properties; /** * @author leic <lei.chen@hcit.ai>. * @date 2021/8/6 15:27 */ @Slf4j public class NacosWritableDataSource<T> implements WritableDataSource<T> { private ConfigService configService = null; private String groupId; private String dataId; public NacosWritableDataSource(String serverAddr, String groupId, String dataId, String nameSpace) { this.groupId = groupId; this.dataId = dataId; Properties properties = buildProperties(serverAddr, nameSpace); try { this.configService = NacosFactory.createConfigService(properties); } catch (NacosException e) { log.info("初始化nacos客户端失败:", e); throw new RuntimeException(e.getMessage()); } } @Override public void write(T value) throws Exception { try { String convert = JSON.toJSONString(value); //持久化配置到nacos,每一次sentinel规则更新都会给到全量(api或网关流控)的配置信息 configService.publishConfig(dataId, groupId, convert); } catch (NacosException e) { log.error("error:", e); } } @Override public void close() throws Exception { } private static Properties buildProperties(String serverAddr, String namespace) { Properties properties = new Properties(); properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverAddr); properties.setProperty(PropertyKeyConst.NAMESPACE, namespace); return properties; } }
-
将自定义的WritableDataSource绑定到api及流控规则更新的处理类中
package com.gaorong.orm; import com.alibaba.cloud.sentinel.SentinelProperties; import com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration; import com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties; import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; import com.alibaba.csp.sentinel.adapter.gateway.common.command.UpdateGatewayApiDefinitionGroupCommandHandler; import com.alibaba.csp.sentinel.adapter.gateway.common.command.UpdateGatewayRuleCommandHandler; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Map; import java.util.Set; /** * @author leic <lei.chen@hcit.ai>. * @date 2021/8/6 16:26 */ @Service public class SentinelPersistHandler implements ApplicationListener<ContextRefreshedEvent> { @Resource private SentinelProperties sentinelProperties; @Override public void onApplicationEvent(ContextRefreshedEvent event) { initGateWayApiDefinition(); initGatewayFlowRule(); } private void initGatewayFlowRule() { //ds1 与配置文件中对应 NacosDataSourceProperties nacosProperty = getNacosDataSourceProperties("ds1"); NacosWritableDataSource<Set<GatewayFlowRule>> nacosWritableDataSource = new NacosWritableDataSource(nacosProperty.getServerAddr() , nacosProperty.getGroupId(), nacosProperty.getDataId(), nacosProperty.getNamespace()); //网关流控规则处理类 UpdateGatewayRuleCommandHandler.setWritableDataSource(nacosWritableDataSource); } private NacosDataSourceProperties getNacosDataSourceProperties(String key) { Map<String, DataSourcePropertiesConfiguration> datasource = sentinelProperties.getDatasource(); DataSourcePropertiesConfiguration configuration = datasource.get(key); NacosDataSourceProperties nacosProperty = configuration.getNacos(); return nacosProperty; } private void initGateWayApiDefinition() { //ds2 与配置文件中对应 NacosDataSourceProperties nacosProperty = getNacosDataSourceProperties("ds2"); NacosWritableDataSource<Set<ApiDefinition>> nacosWritableDataSource = new NacosWritableDataSource(nacosProperty.getServerAddr() , nacosProperty.getGroupId(), nacosProperty.getDataId(), nacosProperty.getNamespace()); /**api更新处理类**/ UpdateGatewayApiDefinitionGroupCommandHandler.setWritableDataSource(nacosWritableDataSource); } }