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> 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> 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】目录。如图
Sentinel客户端持久化改造【Pull拉模式】_第1张图片

第三步

在services目录下创建【com.alibaba.csp.sentinel.init.InitFunc】文件。文件名称为固定写法。如图。
Sentinel客户端持久化改造【Pull拉模式】_第2张图片

第四步

编辑文件内容。将自定义的【PullModeByFileDataSource】类全路径,写到文件中。
Sentinel客户端持久化改造【Pull拉模式】_第3张图片

第五步

测试。访问接口后,在【Sentinel】控制台配置相关规则后,客户端会持久化。文件中的内容也会自动填充。
Sentinel客户端持久化改造【Pull拉模式】_第4张图片

你可能感兴趣的:(java,spring,cloud,alibaba)