Sentinel Dashboard支持规则配置持久化至Nacos

前言

Sentinel控制台规则管理和推送主要有3种方式:原始模式Pull模式Push模式,如果不做任何修改,默认使用的是原始模式

所谓原始模式就是Sentinel控制台通过相关API直接将规则推送至客户端并直接更新到内存中,下面是三种模式的对比。
在这里插入图片描述
原始模式规则配置由于是在内存中,重启就会消失。

因此在生产环境中Sentinel官方推荐我们使用Push模式实现动态规则配置和持久化,我们一般会依赖一些第三方中间件,如NacosApolloZookeeperRedis等来实现。


一、Push模式原理

Push模式的推送流程是:Sentinel控制台新增/修改配置持久化至配置中心(Nacos)Sentinel数据源监听配置中心最新配置Sentinel客户端从数据源中读取配置

整体流程图如下:
在这里插入图片描述

更多内容请参考:在生产环境中使用Sentinel



二、Sentinel控制台改造支持配置持久化至Nacos

由于Sentinel控制台本身并不支持在前端界面修改规则配置后推送至第三方配置中心,因此我们需要对Sentinel Dashboard的代码进行修改。

控制台代码修改的思路参考:Sentinel控制台集群流控管理

1、拉取最新代码

直接从Github上拉取sentinel-dashboard的代码即可,我拉取的版本是1.8.1

2、开始搬运代码

拉下代码后,可以看到在test目录下,有关于Nacos规则推送的类,我们可以直接搬过去。
在这里插入图片描述
这里我自己其实做了一些代码优化和小调整,调整后的文件目录如下:
在这里插入图片描述

(1) 调整点之修改NacosConfig类

@Configuration
@EnableConfigurationProperties(NacosConfigProperties.class)
public class NacosConfig {

	@Autowired
	private NacosConfigProperties nacosConfigProperties;

	@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 ConfigService nacosConfigService() throws Exception {
		Properties properties = new Properties();
		// 这里在创建ConfigService实例时加了Nacos实例地址和命名空间两个属性。
		properties.put(PropertyKeyConst.SERVER_ADDR, nacosConfigProperties.getServerAddr());
		properties.put(PropertyKeyConst.NAMESPACE, nacosConfigProperties.getNamespace());
		return ConfigFactory.createConfigService(properties);
	}
}

(2) 调整点之新增NacosConfigProperties类

@ConfigurationProperties(prefix = "sentinel.config.nacos")
public class NacosConfigProperties {

	/**
	 * nacos服务器地址
	 */
	private String serverAddr;

	/**
	 * nacos命名空间
	 */
	private String namespace;

	/**
	 * 分组名
	 */
	private String groupId = NacosConfigUtil.GROUP_ID;

	/**
	 * 限流规则dataId后缀
	 */
	private String flowRuleDataIdSuffix = NacosConfigUtil.FLOW_DATA_ID_POSTFIX;

	/**
	 * 降级规则dataId后缀
	 */
	private String degradeRuleDataIdSuffix = NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX;

	public String getServerAddr() {
		return serverAddr;
	}

	public void setServerAddr(String serverAddr) {
		this.serverAddr = serverAddr;
	}

	public String getNamespace() {
		return namespace;
	}

	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	public String getGroupId() {
		return groupId;
	}

	public void setGroupId(String groupId) {
		this.groupId = groupId;
	}

	public String getFlowRuleDataIdSuffix() {
		return flowRuleDataIdSuffix;
	}

	public void setFlowRuleDataIdSuffix(String flowRuleDataIdSuffix) {
		this.flowRuleDataIdSuffix = flowRuleDataIdSuffix;
	}

	public String getDegradeRuleDataIdSuffix() {
		return degradeRuleDataIdSuffix;
	}

	public void setDegradeRuleDataIdSuffix(String degradeRuleDataIdSuffix) {
		this.degradeRuleDataIdSuffix = degradeRuleDataIdSuffix;
	}
}

(3) 调整点之修改NacosConfigUtil类

public final class NacosConfigUtil {

	public static final String GROUP_ID = "SENTINEL_GROUP";

	public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
	public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules";
	public static final String SYSTEM_FULE_DATA_ID_POSTFIX = "-system-rules";
	public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules";
	public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";
	public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";

	/**
	 * cc for `cluster-client`
	 */
	public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config";
	/**
	 * cs for `cluster-server`
	 */
	public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config";
	public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config";
	public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set";

	private NacosConfigUtil() {
	}
}

(4) DynamicRuleProvider和DynamicRulePublisher实现优化

这里我用模板方法模式优化了一下代码,新增了AbstractNacosProviderAbstractNacosPublisher两个类。

1) AbstractNacosProvider类
public abstract class AbstractNacosProvider<T> implements DynamicRuleProvider<List<T>> {

	private static final long timeoutInMills = 3000;

	@Autowired
	private NacosConfigProperties nacosConfigProperties;

	@Autowired
	private ConfigService configService;

	@Autowired
	private Converter<String, List<T>> converter;

	@Override
	public List<T> getRules(String appName) throws Exception {
		String dataId = appName + getDataIdSuffix();
		String groupId = nacosConfigProperties.getGroupId();
		String rules = configService.getConfig(dataId, groupId, timeoutInMills);
		return StringUtil.isEmpty(rules) ? Collections.emptyList() : converter.convert(rules);
	}

	protected NacosConfigProperties getNacosConfigProperties() {
		return nacosConfigProperties;
	}

	protected abstract String getDataIdSuffix();
}
2) AbstractNacosPublisher类
public abstract class AbstractNacosPublisher<T> implements DynamicRulePublisher<List<T>> {

	@Autowired
	private NacosConfigProperties nacosConfigProperties;

	@Autowired
	private ConfigService configService;

	@Autowired
	private Converter<List<T>, String> converter;

	@Override
	public void publish(String app, List<T> rules) throws Exception {
		AssertUtil.notEmpty(app, "app name cannot be empty");
		if (CollectionUtils.isEmpty(rules)) {
			return;
		}

		String dataId = app + getDataIdSuffix();
		String groupId = nacosConfigProperties.getGroupId();
		configService.publishConfig(dataId, groupId, converter.convert(rules));
	}

	protected NacosConfigProperties getNacosConfigProperties() {
		return nacosConfigProperties;
	}

	protected abstract String getDataIdSuffix();
}
3) FlowRuleNacosProvider类
@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider extends AbstractNacosProvider<FlowRuleEntity> {

	@Override
	protected String getDataIdSuffix() {
		return super.getNacosConfigProperties().getFlowRuleDataIdSuffix();
	}
}
4) FlowRuleNacosPublisher类
@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher extends AbstractNacosPublisher<FlowRuleEntity> {

	@Override
	protected String getDataIdSuffix() {
		return super.getNacosConfigProperties().getFlowRuleDataIdSuffix();
	}
}

备注:降级规则相关实现类参考上面的FlowRuleNacosProviderFlowRuleNacosPublisher即可。

3、修改Controller

(1) FlowControllerV2类

需要注意的是,FlowControllerV2类主要用于集群流控相关的规则配置读取和发布,而FlowControllerV1类用于单个应用维度流控的规则配置和发布。

这个类这里我们把动态规则获取和发布相关实现类改成了我们自己实现的基于Nacos的实现,如下:
在这里插入图片描述

备注:其它修改处,如从Nacos中读取流控规则配置,发布流控规则配置到Nacos的代码示例,请参考代码:FlowControllerV2

(2) DegradeControllerV2类

降级规则配置读取和发布控制器的修改和FlowControllerV2基本差不多,只不过降级是针对单个应用。
在这里插入图片描述

备注:这里我新复制了一个DegradeControllerV2类,注意把DegradeController类上的@RestController注解给干掉。其它细节修改请参考:DegradeControllerV2

4、修改前端路由配置文件sidebar.html

之前这里的流控规则的路由是:dashboard.flowV1,也就是路由到FlowController。现在我们把修改为dashboard.flow,也就是路由到FlowControllerV2
在这里插入图片描述

备注:到这里sentinel控制台的代码修改就差不多了,至于其它规则Controller的修改,如:热点规则、系统规则、授权规则等,可以参考上面的DegradeControllerV2类。

5、Sentinel控制台application.properties

新增Nacos数据源相关的自定义配置,我们在NacosConfigProperties类中有定义过。

# nacos server address
sentinel.config.nacos.server-addr=localhost:8848
# nacos namespace to use
sentinel.config.nacos.namespace=d3a61a32-1c74-4fc6-a9f2-1cf18675c4ee

6、启动Sentinel控制台

在这里插入图片描述

备注:用户名和密码都是sentinel



三、Sentinel客户端接入Nacos数据源

NacosSentinel都是Spring Cloud Alibaba的开源组件,这里我们就选用Nacos作为配置中心。

1、Maven依赖

<dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--动态扩展之数据源支持-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>${sentinel-datasouce-nacos.version}</version>
        </dependency>
</dependencies>

备注:Spring Cloud Alibaba的版本我用的是2.2.6.RELEASEsentinel-datasource-nacos的版本是1.8.1


2、bootstrap.yaml

server:
  port: 9010
spring:
  application:
    name: sentinel-client

3、application.yml

这里我们流控和降级相关的规则都是从Nacos中读取,如下:

spring:
  cloud:
    sentinel:
      datasource:
        flow-ds:
          nacos:
            server-addr: localhost:8848
            namespace: d3a61a32-1c74-4fc6-a9f2-1cf18675c4ee
            data-id: ${spring.application.name}-flow-rules
            group-id: SENTINEL_GROUP
            data-type: json
            rule-type: flow
        degrade-ds:
          nacos:
            server-addr: localhost:8848
            namespace: d3a61a32-1c74-4fc6-a9f2-1cf18675c4ee
            data-id: ${spring.application.name}-degrade-rules
            group-id: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
      transport:
        port: 8719 #与sentinel dashboard的通信端口,会启动一个http server,供dashboard调用
        dashboard: localhost:9999 #dashboard地址和端口

更多内容请参考:Sentinel集成Spring Cloud Alibaba动态数据源支持



四、Sentinel客户端测试用例

1、SentinelController

@RestController
public class SentinelController {

	@GetMapping("/order")
	@SentinelResource(value = ResourceDefConst.ORDER_INFO, blockHandler = "exceptionHandler", fallback = "fallback")
	public String queryOrderInfo(long orderId) {
		Random random = new Random();
		int timeout = random.nextInt(150);
		LockSupport.parkNanos(timeout * 1000 * 1000);
		System.out.println(String.format("调用时间为:%d", timeout));
		return String.format("订单信息:%d", orderId);
	}

	/**
	 * 若blockHandler和fallback都进行了配置,则被限流降级时抛出BlockException时只会进入blockHandler逻辑
	 * @param orderId
	 * @param e
	 * @return
	 */
	public String exceptionHandler(long orderId, BlockException e) {
		e.printStackTrace();
		return "服务降级啦!";
	}

	public String fallback(long orderId, Throwable t) {
		t.printStackTrace();
		return "服务异常啦!";
	}
}

备注:启动Sentinel客户端,当有相应的资源请求到来时,Sentinel控制台会展示Sentinel客户端应用的资源调用信息。

2、登录Sentinel控制台修改流控规则

这里我们修改了资源名为order_info的流控规则为基于QPS的限流且阈值为2。
在这里插入图片描述

3、登录Nacos控制台查看流控规则

在上一步我们已经在Sentinel控制台修改了集群流控相关的规则,我们登录Nacos控制台看看配置是否已经持久化到了Nacos上。
在这里插入图片描述

备注:可以看到Sentinel控制台的修改确实同步到了Nacos上。

4、请求示例

当我们访问http://localhost:9010/order?orderId=1,可以看到当QPS超过2时会触发FlowException,说明我们的流控规则修改是生效的。
在这里插入图片描述

备注:关于降级规则的测试同样可以在Sentinel控制台上进行操作。

在这里插入图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌波漫步&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值