官方教程
需要引入的包
本人用的版本:spring cloud Hoxton.SR11 spring cloud alibaba 2.2.6.RELEASE
不同版本可能会导致sentinel无法加载nacos配置的流控规则的奇怪bug
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-datasource-nacosartifactId>
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控制台配置的全部消失,因为它只是保存在内存中
实现代码如下
自定义一个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 .
* @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 .
* @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);
}
}