背景
sentinel-dashborad的配置默认是存储到内存中的,生产环境肯定不能这样使用,官网支持zookeeper、nacos、apollo的配置,本文就来介绍apollo的持久化
apollo
sentinel-dashboard 整合 apollo 进行规则的持久化配置,主要方式是通过 apollo 开放平台的授权方式进行写入与读取。所以需要先在apollo上开放出授权的token
sentinel-dashboard
首先将sentinel下载下来然后找到sentinel-dashboard模块,基于1.8.1版本
新建apllo需要的相关配置 ApolloProperties
@ConfigurationProperties(prefix = "apollo")
@Data
public class ApolloProperties {
/**
* apollo地址
* */
private String portalUrl;
/**
* 授权token
* */
private String token;
/**
* appId
* */
private String appId;
/**
* 环境
* */
private String env;
/**
* clusterName(默认为default)
* */
private String clusterName;
/**
* 命名空间
* */
private String namespace;
/**
* 操作人
* */
private String operator;
}
新建ApolloConfig 里面包括各种规则和apollo交互需要的编解码工具和操作apollo的api
@Configuration
@EnableConfigurationProperties(ApolloProperties.class)
public class ApolloConfig {
@Autowired
private ApolloProperties apolloProperties;;
/**
* 流控规则编码
*/
@Bean
public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 流控规则解码
*/
@Bean
public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
return s -> JSON.parseArray(s, FlowRuleEntity.class);
}
/**
* 降级规则编码
*/
@Bean
public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 降级规则解码
*/
@Bean
public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
return s -> JSON.parseArray(s, DegradeRuleEntity.class);
}
/**
* 授权规则编码
*/
@Bean
public Converter<List<AuthorityRuleEntity>, String> authorityRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 授权规则解码
*/
@Bean
public Converter<String, List<AuthorityRuleEntity>> authorityRuleEntityDecoder() {
return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
}
/**
* 系统规则编码
*/
@Bean
public Converter<List<SystemRuleEntity>, String> systemRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 系统规则解码
*/
@Bean
public Converter<String, List<SystemRuleEntity>> systemRuleEntityDecoder() {
return s -> JSON.parseArray(s, SystemRuleEntity.class);
}
/**
* 热点规则编码
*/
@Bean
public Converter<List<ParamFlowRuleEntity>, String> paramFlowRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 热点规则解码
*/
@Bean
public Converter<String, List<ParamFlowRuleEntity>> paramFlowRuleEntityDecoder() {
return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
}
/**
* 集群流控规则编码
*/
@Bean
public Converter<List<ClusterAppAssignMap>, String> clusterGroupEntityEncoder() {
return JSON::toJSONString;
}
/**
* 集群流控规则解码
*/
@Bean
public Converter<String, List<ClusterAppAssignMap>> clusterGroupEntityDecoder() {
return s -> JSON.parseArray(s, ClusterAppAssignMap.class);
}
/**
* API管理分组编码
*/
@Bean
public Converter<List<ApiDefinitionEntity>, String> apiDefinitionEntityEncoder() {
return JSON::toJSONString;
}
/**
* API管理分组解码
*/
@Bean
public Converter<String, List<ApiDefinitionEntity>> apiDefinitionEntityDecoder() {
return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
}
/**
* 网关流控规则编码
*/
@Bean
public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 网关流控规则解码
*/
@Bean
public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() {
return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
}
/**
* 操作apollo的api
* */
@Bean
public ApolloOpenApiClient apolloOpenApiClient() {
ApolloOpenApiClient client = ApolloOpenApiClient.newBuilder()
.withPortalUrl(apolloProperties.getPortalUrl())
.withToken(apolloProperties.getToken())
.build();
return client;
}
}
新建ApolloConfigUtil 用于生成各种规则存储在apollo中的key名称
public final class ApolloConfigUtil
{
/**
* 网关-api分组id
*/
public static final String GATEWAY_API_GROUP_DATA_ID_POSTFIX = "gw-api-group-rules";
/**
* 网关-流控规则id
*/
public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "gw-flow-rules";
/**
* 流控规则id
*/
public static final String FLOW_DATA_ID_POSTFIX = "flow-rules";
/**
* 降级规则id
*/
public static final String DEGRADE_DATA_ID_POSTFIX = "degrade-rules";
/**
* 热点规则id
*/
public static final String PARAM_FLOW_DATA_ID_POSTFIX = "param-flow-rules";
/**
* 系统规则id
*/
public static final String SYSTEM_DATA_ID_POSTFIX = "system-rules";
/**
* 授权规则id
*/
public static final String AUTHORITY_DATA_ID_POSTFIX = "authority-rules";
/**
* 集群流控id
*/
public static final String CLUSTER_GROUP_DATA_ID_POSTFIX = "cluster-group-rules";
private ApolloConfigUtil()
{
}
public static String getGatewayFlowDataId(String appName)
{
return String.format("%s-%s", appName, GATEWAY_FLOW_DATA_ID_POSTFIX);
}
public static String getGatewayApiGroupDataId(String appName)
{
return String.format("%s-%s", appName, GATEWAY_API_GROUP_DATA_ID_POSTFIX);
}
public static String getClusterGroupDataId(String appName)
{
return String.format("%s-%s", appName, CLUSTER_GROUP_DATA_ID_POSTFIX);
}
public static String getFlowDataId(String appName)
{
return String.format("%s-%s", appName, FLOW_DATA_ID_POSTFIX);
}
public static String getDegradeDataId(String appName)
{
return String.format("%s-%s", appName, DEGRADE_DATA_ID_POSTFIX);
}
public static String getParamFlowDataId(String appName)
{
return String.format("%s-%s", appName, PARAM_FLOW_DATA_ID_POSTFIX);
}
public static String getSystemDataId(String appName)
{
return String.format("%s-%s", appName, SYSTEM_DATA_ID_POSTFIX);
}
public static String getAuthorityDataId(String appName)
{
return String.format("%s-%s", appName, AUTHORITY_DATA_ID_POSTFIX);
}
}
流控规则持久化apollo
项目提供了DynamicRuleProvider
和DynamicRulePublisher
两个接口,这是将整个规则的相关操作抽象了出来,一个用户查询、另一个用于新增、修改、删除。项目中test/rule模块下提供了apollo关于流控规则的示例FlowRuleApolloProvider
和FlowRuleApolloPublisher
,也是将这两个接口进行了实现。本人直接拿这提供好的示例进行改造
FlowRuleApolloProvider
@Component("flowRuleApolloProvider")
public class FlowRuleApolloProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
@Autowired
private ApolloOpenApiClient apolloOpenApiClient;
@Autowired
private Converter<String, List<FlowRuleEntity>> converter;
@Autowired
private ApolloProperties apolloProperties;
/**
* @param appName 服务名
* */
@Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {
//String appId = "appId";
String flowDataId = ApolloConfigUtil.getFlowDataId(appName);
OpenNamespaceDTO openNamespaceDTO = apolloOpenApiClient.getNamespace(apolloProperties.getAppId(), apolloProperties.getEnv(), apolloProperties.getClusterName(), apolloProperties.getNamespace());
String rules = openNamespaceDTO
.getItems()
.stream()
.filter(p -> p.getKey().equals(flowDataId))
.map(OpenItemDTO::getValue)
.findFirst()
.orElse("");
if (StringUtil.isEmpty(rules)) {
return new ArrayList<>();
}
return converter.convert(rules);
}
}
FlowRuleApolloPublisher
@Component("flowRuleApolloPublisher")
public class FlowRuleApolloPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
@Autowired
private ApolloOpenApiClient apolloOpenApiClient;
@Autowired
private Converter<List<FlowRuleEntity>, String> converter;
@Autowired
private ApolloProperties apolloProperties;
@Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
}
// Increase the configuration
//String appId = "appId";
String flowDataId = ApolloConfigUtil.getFlowDataId(app);
OpenItemDTO openItemDTO = new OpenItemDTO();
openItemDTO.setKey(flowDataId);
openItemDTO.setValue(converter.convert(rules));
openItemDTO.setComment("Program auto-join");
openItemDTO.setDataChangeCreatedBy(apolloProperties.getOperator());
apolloOpenApiClient.createOrUpdateItem(apolloProperties.getAppId(), apolloProperties.getEnv(), apolloProperties.getClusterName(), apolloProperties.getNamespace(), openItemDTO);
// Release configuration
NamespaceReleaseDTO namespaceReleaseDTO = new NamespaceReleaseDTO();
namespaceReleaseDTO.setEmergencyPublish(true);
namespaceReleaseDTO.setReleaseComment("Modify or add configurations");
namespaceReleaseDTO.setReleasedBy(apolloProperties.getOperator());
namespaceReleaseDTO.setReleaseTitle("Modify or add configurations");
apolloOpenApiClient.publishNamespace(apolloProperties.getAppId(), apolloProperties.getEnv(), apolloProperties.getClusterName(), apolloProperties.getNamespace(), namespaceReleaseDTO);
}
}
下面是改造controller层,流控规则用到了两个controller,FlowControllerV1
和FlowControllerV2
FlowControllerV2
@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {
private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
@Autowired
private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;
@Autowired
@Qualifier("flowRuleApolloProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleApolloPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app) {
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(app);
if (rules != null && !rules.isEmpty()) {
for (FlowRuleEntity entity : rules) {
entity.setApp(app);
if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {
entity.setId(entity.getClusterConfig().getFlowId());
}
}
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
logger.error("Error when querying flow rules", throwable);
return Result.ofThrowable(-1, throwable);
}
}
private <R> Result<R> checkEntityInternal(FlowRuleEntity entity) {
if (entity == null) {
return Result.ofFail(-1, "invalid body");
}
if (StringUtil.isBlank(entity.getApp())) {
return Result.ofFail(-1, "app can't be null or empty");
}
if (StringUtil.isBlank(entity.getLimitApp())) {
return Result.ofFail(-1, "limitApp can't be null or empty");
}
if (StringUtil.isBlank(entity.getResource())) {
return Result.ofFail(-1, "resource can't be null or empty");
}
if (entity.getGrade() == null) {
return Result.ofFail(-1, "grade can't be null");
}
if (entity.getGrade() != 0 && entity.getGrade() != 1) {
return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
}
if (entity.getCount() == null || entity.getCount() < 0) {
return Result.ofFail(-1, "count should be at lease zero");
}
if (entity.getStrategy() == null) {
return Result.ofFail(-1, "strategy can't be null");
}
if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) {
return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
}
if (entity.getControlBehavior() == null) {
return Result.ofFail(-1, "controlBehavior can't be null");
}
int controlBehavior = entity.getControlBehavior();
if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) {
return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
}
if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) {
return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
}
if (entity.isClusterMode() && entity.getClusterConfig() == null) {
return Result.ofFail(-1, "cluster config should be valid");
}
return null;
}
@PostMapping("/rule")
@AuthAction(value = AuthService.PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
entity.setApp(app);
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
}
Date date = new Date();
entity.setGmtCreate(date);
entity.setGmtModified(date);
entity.setLimitApp(entity.getLimitApp().trim());
entity.setResource(entity.getResource().trim());
try {
entity = repository.save(entity);
publishRules(entity.getApp());
} catch (Throwable throwable) {
logger.error("Failed to add flow rule", throwable);
return Result.ofThrowable(-1, throwable);
}
return Result.ofSuccess(entity);
}
@PutMapping("/rule/{id}")
@AuthAction(AuthService.PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiUpdateFlowRule(@PathVariable("id") Long id,
@RequestBody FlowRuleEntity entity) {
entity.setApp(app);
if (id == null || id <= 0) {
return Result.ofFail(-1, "Invalid id");
}
FlowRuleEntity oldEntity = repository.findById(id);
if (oldEntity == null) {
return Result.ofFail(-1, "id " + id + " does not exist");
}
if (entity == null) {
return Result.ofFail(-1, "invalid body");
}
entity.setApp(oldEntity.getApp());
entity.setIp(oldEntity.getIp());
entity.setPort(oldEntity.getPort());
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
}
entity.setId(id);
Date date = new Date();
entity.setGmtCreate(oldEntity.getGmtCreate());
entity.setGmtModified(date);
try {
entity = repository.save(entity);
if (entity == null) {
return Result.ofFail(-1, "save entity fail");
}
publishRules(oldEntity.getApp());
} catch (Throwable throwable) {
logger.error("Failed to update flow rule", throwable);
return Result.ofThrowable(-1, throwable);
}
return Result.ofSuccess(entity);
}
@DeleteMapping("/rule/{id}")
@AuthAction(PrivilegeType.DELETE_RULE)
public Result<Long> apiDeleteRule(@PathVariable("id") Long id) {
if (id == null || id <= 0) {
return Result.ofFail(-1, "Invalid id");
}
FlowRuleEntity oldEntity = repository.findById(id);
if (oldEntity == null) {
return Result.ofSuccess(null);
}
try {
repository.delete(id);
publishRules(oldEntity.getApp());
} catch (Exception e) {
return Result.ofFail(-1, e.getMessage());
}
return Result.ofSuccess(id);
}
public void publishRules(/*@NonNull*/ String app) throws Exception {
List<FlowRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
}
}
FlowControllerV2
是调用apollo的ruleProvider
和rulePublisher
完成调用的,我把FlowControllerV1
改造成直接调用的FlowControllerV2
FlowControllerV2
@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {
private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
@Autowired
private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;
@Autowired
@Qualifier("flowRuleApolloProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleApolloPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app) {
if (StringUtil.isEmpty(app)) {
return Result.ofFail(-1, "app can't be null or empty");
}
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(app);
if (rules != null && !rules.isEmpty()) {
for (FlowRuleEntity entity : rules) {
entity.setApp(app);
if (entity.getClusterConfig() != null && entity.getClusterConfig().getFlowId() != null) {
entity.setId(entity.getClusterConfig().getFlowId());
}
}
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);
} catch (Throwable throwable) {
logger.error("Error when querying flow rules", throwable);
return Result.ofThrowable(-1, throwable);
}
}
private <R> Result<R> checkEntityInternal(FlowRuleEntity entity) {
if (entity == null) {
return Result.ofFail(-1, "invalid body");
}
if (StringUtil.isBlank(entity.getApp())) {
return Result.ofFail(-1, "app can't be null or empty");
}
if (StringUtil.isBlank(entity.getLimitApp())) {
return Result.ofFail(-1, "limitApp can't be null or empty");
}
if (StringUtil.isBlank(entity.getResource())) {
return Result.ofFail(-1, "resource can't be null or empty");
}
if (entity.getGrade() == null) {
return Result.ofFail(-1, "grade can't be null");
}
if (entity.getGrade() != 0 && entity.getGrade() != 1) {
return Result.ofFail(-1, "grade must be 0 or 1, but " + entity.getGrade() + " got");
}
if (entity.getCount() == null || entity.getCount() < 0) {
return Result.ofFail(-1, "count should be at lease zero");
}
if (entity.getStrategy() == null) {
return Result.ofFail(-1, "strategy can't be null");
}
if (entity.getStrategy() != 0 && StringUtil.isBlank(entity.getRefResource())) {
return Result.ofFail(-1, "refResource can't be null or empty when strategy!=0");
}
if (entity.getControlBehavior() == null) {
return Result.ofFail(-1, "controlBehavior can't be null");
}
int controlBehavior = entity.getControlBehavior();
if (controlBehavior == 1 && entity.getWarmUpPeriodSec() == null) {
return Result.ofFail(-1, "warmUpPeriodSec can't be null when controlBehavior==1");
}
if (controlBehavior == 2 && entity.getMaxQueueingTimeMs() == null) {
return Result.ofFail(-1, "maxQueueingTimeMs can't be null when controlBehavior==2");
}
if (entity.isClusterMode() && entity.getClusterConfig() == null) {
return Result.ofFail(-1, "cluster config should be valid");
}
return null;
}
@PostMapping("/rule")
@AuthAction(value = AuthService.PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
entity.setApp(app);
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
}
Date date = new Date();
entity.setGmtCreate(date);
entity.setGmtModified(date);
entity.setLimitApp(entity.getLimitApp().trim());
entity.setResource(entity.getResource().trim());
try {
entity = repository.save(entity);
publishRules(entity.getApp());
} catch (Throwable throwable) {
logger.error("Failed to add flow rule", throwable);
return Result.ofThrowable(-1, throwable);
}
return Result.ofSuccess(entity);
}
@PutMapping("/rule/{id}")
@AuthAction(AuthService.PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiUpdateFlowRule(@PathVariable("id") Long id,
@RequestBody FlowRuleEntity entity) {
entity.setApp(app);
if (id == null || id <= 0) {
return Result.ofFail(-1, "Invalid id");
}
FlowRuleEntity oldEntity = repository.findById(id);
if (oldEntity == null) {
return Result.ofFail(-1, "id " + id + " does not exist");
}
if (entity == null) {
return Result.ofFail(-1, "invalid body");
}
entity.setApp(oldEntity.getApp());
entity.setIp(oldEntity.getIp());
entity.setPort(oldEntity.getPort());
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
if (checkResult != null) {
return checkResult;
}
entity.setId(id);
Date date = new Date();
entity.setGmtCreate(oldEntity.getGmtCreate());
entity.setGmtModified(date);
try {
entity = repository.save(entity);
if (entity == null) {
return Result.ofFail(-1, "save entity fail");
}
publishRules(oldEntity.getApp());
} catch (Throwable throwable) {
logger.error("Failed to update flow rule", throwable);
return Result.ofThrowable(-1, throwable);
}
return Result.ofSuccess(entity);
}
@DeleteMapping("/rule/{id}")
@AuthAction(PrivilegeType.DELETE_RULE)
public Result<Long> apiDeleteRule(@PathVariable("id") Long id) {
if (id == null || id <= 0) {
return Result.ofFail(-1, "Invalid id");
}
FlowRuleEntity oldEntity = repository.findById(id);
if (oldEntity == null) {
return Result.ofSuccess(null);
}
try {
repository.delete(id);
publishRules(oldEntity.getApp());
} catch (Exception e) {
return Result.ofFail(-1, e.getMessage());
}
return Result.ofSuccess(id);
}
public void publishRules(/*@NonNull*/ String app) throws Exception {
List<FlowRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
}
}
配置文件application.properties
#spring settings
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.port=8082
csp.sentinel.dashboard.server=localhost:8082
project.name=sentinel-dashboard
#cookie name setting
server.servlet.session.cookie.name=sentinel_dashboard_cookie
#logging settings
logging.level.org.springframework.web=INFO
logging.file.name=${user.home}/logs/csp/sentinel-dashboard.log
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
#auth settings
auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version
auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png
# If auth.enabled=false, Sentinel console disable login
auth.username=sentinel
auth.password=sentinel
# Inject the dashboard version. It's required to enable
# filtering in pom.xml for this resource file.
sentinel.dashboard.version=@project.version@
apollo.portalUrl = #apollo地址
apollo.token= #token
apollo.appId= appId
apollo.env= #环境
apollo.clusterName= #集群名字,默认default
apollo.namespace= #命令空间
apollo.operator= #操作人,默认apollo
结构
服务项目
添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
</dependency>
application.yml
#服务端口
server:
port: 8080
# 应用名称
spring:
application:
name: test-service
# nacos
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
port: 8720
dashboard: localhost:8082
datasource:
degrade:
apollo:
flowRulesKey: ${spring.application.name}-${spring.cloud.sentinel.datasource.degrade.apollo.rule-ruleType}-rules
namespace-name: ${sentinel.datasource.rules.apollo.namespace-name}
ruleType: degrade
flow:
apollo:
flowRulesKey: ${spring.application.name}-${spring.cloud.sentinel.datasource.flow.apollo.ruleType}-rules
namespace-name: ${sentinel.datasource.rules.apollo.namespace-name}
ruleType: flow
eager: true
app:
id: #appId
apollo:
meta: #地址
bootstrap:
enabled: true
namespaces: #命令空间
eagerLoad:
enabled: true
sentinel:
datasource:
rules:
apollo:
namespace-name: #命令空间
feign:
sentinel:
enabled: true
management:
endpoints:
web:
exposure:
include: '*'
health:
show-details: always
security:
enabled: false
其他规则和流控规则改造相同,这里就不再介绍了