Sentinel客户端持久化改造【Pull拉模式】

在客户端改造持久化方案,需要通过SPI模式实现。具体思路就是接收到Sentinel推送的规则后,将规则保存到本地。

第一步

新增一个实现类。如【PullModeByFileDataSource】。

package com.example.demo.sentinelSpi;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

/**
 * Sentinel 拉模式持久化方案
 * 
 * @author AdminMall
 *
 */
public class PullModeByFileDataSource implements InitFunc {

	/**
	 * 初始化方法
	 */
	@Override
	public void init() throws Exception {
		System.out.println("-------开始创建Sentinel规则目录");
		// 先创建保存Sentinel规则的目录
		String saveDirct = "G:/sentinel/rules";
		File fileDirct = new File(saveDirct);
		if (!fileDirct.isDirectory()) {
			fileDirct.mkdirs();
		}

		// 创建规则文件
		Map<String, String> fileMap = new HashMap<>();
		fileMap.put("flowRule", saveDirct + "/flowRule.json");// 流控规则文件
		fileMap.put("degradeRule", saveDirct + "/degradeRule.json");// 降级规则文件
		fileMap.put("systemRule", saveDirct + "/systemRule.json");// 系统规则文件
		fileMap.put("authRule", saveDirct + "/authRule.json");// 授权规则文件
		fileMap.put("hotRule", saveDirct + "/hotRule.json");// 热点规则文件
		for (String key : fileMap.keySet()) {
			File file = new File(fileMap.get(key));
			if (!file.exists()) {
				file.createNewFile();
			}
		}

		// 流控规则持久化
		flowRule(saveDirct + "/flowRule.json");
		// 降级规则持久化
		degradeRule(saveDirct + "/degradeRule.json");
		// 系统规则持久化
		systemRule(saveDirct + "/systemRule.json");
		// 授权规则持久化
		authRule(saveDirct + "/authRule.json");
		// 热点规则持久化
		hotRule(saveDirct + "/hotRule.json");
	}

	/**
	 * 流控规则启用
	 * 
	 * @param flowRulePath
	 * @throws FileNotFoundException
	 */
	public void flowRule(String flowRulePath) throws FileNotFoundException {
		// 流控规则
		ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(flowRulePath,
				SentinelConverTool.flowRuleListParser);
        	// 可以指定刷新时间,比如20秒,默认是3秒钟
           //参数说明;文件,轮询秒数,文件大小,字符集
		// ReadableDataSource<String, List<FlowRule>> flowRuleRDS2 = new
		// FileRefreshableDataSource<>(new
		// File(flowRulePath),SentinelConverTool.flowRuleListParser, 20000L, (1024 *
		// 1024), Charset.forName("utf-8"));	
      
  
          // 将可读数据源注册至FlowRuleManager
		// 这样当规则文件发生变化时,就会更新规则到内存
		FlowRuleManager.register2Property(flowRuleRDS.getProperty());

		// 写数据源
		WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(flowRulePath,
				SentinelConverTool.flowRuleStringParser);

		// 第二种写法
		// WritableDataSource<List<FlowRule>> flowRuleWDS = new
		// FileWritableDataSource<>(flowRulePath,this::encodeJson;

		// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
		// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
		WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
	}

	/**
	 * 降级规则启用
	 * 
	 * @param degradeRulePath
	 * @throws FileNotFoundException
	 */
	public void degradeRule(String degradeRulePath) throws FileNotFoundException {
		// 降级规则
		ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(degradeRulePath,
				SentinelConverTool.degradeRuleListParser);
		// 将可读数据源注册至DegradeRuleManager
		// 这样当规则文件发生变化时,就会更新规则到内存
		DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());

		// 写数据源
		WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(degradeRulePath,
				this::encodeJson);
		// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
		// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
		WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);
	}

	/**
	 * 系统规则启用
	 * 
	 * @param systemRulePath
	 * @throws FileNotFoundException
	 */
	public void systemRule(String systemRulePath) throws FileNotFoundException {
		// 系统规则
		ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(systemRulePath,
				SentinelConverTool.systemRuleListParser);
		// 将可读数据源注册至SystemRuleManager
		// 这样当规则文件发生变化时,就会更新规则到内存
		SystemRuleManager.register2Property(systemRuleRDS.getProperty());

		// 写数据源
		WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(systemRulePath,
				this::encodeJson);
		// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
		// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
		WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);
	}

	/**
	 * 授权规则启用
	 * 
	 * @param authRulePath
	 * @throws FileNotFoundException
	 */
	public void authRule(String authRulePath) throws FileNotFoundException {
		// 授权规则
		ReadableDataSource<String, List<AuthorityRule>> authRuleRDS = new FileRefreshableDataSource<>(authRulePath,
				SentinelConverTool.authRuleListParser);
		// 将可读数据源注册至AuthorityRuleManager
		// 这样当规则文件发生变化时,就会更新规则到内存
		AuthorityRuleManager.register2Property(authRuleRDS.getProperty());

		// 写数据源
		WritableDataSource<List<AuthorityRule>> authRuleWDS = new FileWritableDataSource<>(authRulePath,
				this::encodeJson);
		// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
		// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
		WritableDataSourceRegistry.registerAuthorityDataSource(authRuleWDS);
	}

	/**
	 * 热点规则启用
	 * 
	 * @param hotRulePath
	 * @throws FileNotFoundException
	 */
	public void hotRule(String hotRulePath) throws FileNotFoundException {
		// 系统规则
		ReadableDataSource<String, List<ParamFlowRule>> hotRuleRDS = new FileRefreshableDataSource<>(hotRulePath,
				SentinelConverTool.hotRuleListParser);
		// 将可读数据源注册至ParamFlowRuleManager
		// 这样当规则文件发生变化时,就会更新规则到内存
		ParamFlowRuleManager.register2Property(hotRuleRDS.getProperty());

		// 写数据源
		WritableDataSource<List<ParamFlowRule>> hotRuleWDS = new FileWritableDataSource<>(hotRulePath,
				this::encodeJson);
		// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
		// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
		ModifyParamFlowRulesCommandHandler.setWritableDataSource(hotRuleWDS);
	}

	private <T> String encodeJson(T t) {
		return JSON.toJSONString(t);
	}
}

依赖的配置类【SentinelConverTool】

package com.example.demo.sentinelSpi;

import java.util.List;

import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

public class SentinelConverTool {
	// 流控转换
	public static Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(source,
			new TypeReference<List<FlowRule>>() {
			});
	// 降级转换
	public static Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(source,
			new TypeReference<List<DegradeRule>>() {
			});
	// 系统转换
	public static Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(source,
			new TypeReference<List<SystemRule>>() {
			});
	// 授权转换
	public static Converter<String, List<AuthorityRule>> authRuleListParser = source -> JSON.parseObject(source,
			new TypeReference<List<AuthorityRule>>() {
			});

	// 热点
	public static Converter<String, List<ParamFlowRule>> hotRuleListParser = source -> JSON.parseObject(source,
			new TypeReference<List<ParamFlowRule>>() {
			});

	// 转码
	public static Converter<List<FlowRule>, String> flowRuleStringParser = new Converter<List<FlowRule>, String>() {
		@Override
		public String convert(List<FlowRule> source) {
			return JSON.toJSONString(source);
		}
	};

}

第二步

在【resource】目录下创建【META-INF/services】目录。如图
在这里插入图片描述

第三步

在services目录下创建【com.alibaba.csp.sentinel.init.InitFunc】文件。文件名称为固定写法。如图。
在这里插入图片描述

第四步

编辑文件内容。将自定义的【PullModeByFileDataSource】类全路径,写到文件中。
在这里插入图片描述

第五步

测试。访问接口后,在【Sentinel】控制台配置相关规则后,客户端会持久化。文件中的内容也会自动填充。
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

铁蛋的铁,铁蛋的蛋

留一杯咖啡钱给作者吧

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

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

打赏作者

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

抵扣说明:

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

余额充值