Nepxion Discovery study notes 5 Sentinel traffic guard/service fault tolerance integrated solution

Note 1:

Sentinel rule persistence:

Various rules are set for each Sentinel client through the Dashboard, but there is a problem here, that is, these rules are stored in the memory by default (the rules will be deleted once the service restarts) , which is extremely unstable, so it is necessary Make it persistent .

The local file data source will periodically poll for file changes and read rules. In this way, we can either directly modify the file locally to update the rules, or push the rules through the Sentinel console. Taking the local file data source as an example, the push process is shown in the following figure:

First, the Sentinel console pushes the rules to the client through the API and updates them to the memory , and then the registered write data source saves the new rules to a local file .

There are two ways to persist Sentinel :

The first type: Push the rules to the client through the API and update to the memory, and then the registered write data source will save the new rules to a local file.

1. Add dependencies

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-extension</artifactId>
    </dependency>

2. Customize the Sentinel storage file data source loading class:

import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
import com.alibaba.csp.sentinel.datasource.*;
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;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * FileDataSourceInit for : 自定义Sentinel存储文件数据源加载类
 *
 * @author <a href="mailto:[email protected]">Isaac.Zhang | 若初</a>
 * @since 2019/7/21
 */
public class FileDataSourceInit implements InitFunc {
    @Override
    public void init() throws Exception {
        // TIPS: 如果你对这个路径不喜欢,可修改为你喜欢的路径
        String ruleDir = System.getProperty("user.home") + "/sentinel/rules";
        String flowRulePath = ruleDir + "/flow-rule.json";
        String degradeRulePath = ruleDir + "/degrade-rule.json";
        String systemRulePath = ruleDir + "/system-rule.json";
        String authorityRulePath = ruleDir + "/authority-rule.json";
        String hotParamFlowRulePath = ruleDir + "/param-flow-rule.json";

        this.mkdirIfNotExits(ruleDir);
        this.createFileIfNotExits(flowRulePath);
        this.createFileIfNotExits(degradeRulePath);
        this.createFileIfNotExits(systemRulePath);
        this.createFileIfNotExits(authorityRulePath);
        this.createFileIfNotExits(hotParamFlowRulePath);
        // 流控规则
        ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(
                flowRulePath,
                flowRuleListParser
        );
        // 将可读数据源注册至FlowRuleManager
        // 这样当规则文件发生变化时,就会更新规则到内存
        FlowRuleManager.register2Property(flowRuleRDS.getProperty());
        WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
                flowRulePath,
                this::encodeJson
        );
        // 将可写数据源注册至transport模块的WritableDataSourceRegistry中
        // 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
        WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);

        // 降级规则
        ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(
                degradeRulePath,
                degradeRuleListParser
        );
        DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
        WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(
                degradeRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);

        // 系统规则
        ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(
                systemRulePath,
                systemRuleListParser
        );
        SystemRuleManager.register2Property(systemRuleRDS.getProperty());
        WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(
                systemRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);

        // 授权规则
        ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>(
                flowRulePath,
                authorityRuleListParser
        );
        AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
        WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(
                authorityRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);

        // 热点参数规则
        ReadableDataSource<String, List<ParamFlowRule>> hotParamFlowRuleRDS = new FileRefreshableDataSource<>(
                hotParamFlowRulePath,
                hotParamFlowRuleListParser
        );
        ParamFlowRuleManager.register2Property(hotParamFlowRuleRDS.getProperty());
        WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(
                hotParamFlowRulePath,
                this::encodeJson
        );
        ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
    }

    /**
     * 流控规则对象转换
     */
    private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<FlowRule>>() {
            }
    );
    /**
     * 降级规则对象转换
     */
    private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<DegradeRule>>() {
            }
    );
    /**
     * 系统规则对象转换
     */
    private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<SystemRule>>() {
            }
    );

    /**
     * 授权规则对象转换
     */
    private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<AuthorityRule>>() {
            }
    );

    /**
     * 热点规则对象转换
     */
    private Converter<String, List<ParamFlowRule>> hotParamFlowRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<ParamFlowRule>>() {
            }
    );

    /**
     * 创建目录
     *
     * @param filePath
     */
    private void mkdirIfNotExits(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 创建文件
     *
     * @param filePath
     * @throws IOException
     */
    private void createFileIfNotExits(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            file.createNewFile();
        }
    }

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

3. Create a resources/META-INF/services directory and create files under resource com.alibaba.csp.sentinel.init.InitFunc写入:

com.sxzhongf.sharedcenter.configuration.sentinel.datasource.FileDataSourceInit

I haven't tried this method, because the disadvantages are big:

  1. Consistency is not guaranteed (the rule is to use FileRefreshableDataSourceregular updates, there will be delays)

  2. Real-time performance is not guaranteed (the rule is to use FileRefreshableDataSourceregular updates)

  3. Pulling too frequently may also cause performance problems

  4. Since the files are stored locally, they are easy to lose

 

I recommend the second:

1. Import dependencies:

        <!--nacos与sentinel连接-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2. Modify the configuration

server:
  port: 8091
#  tomcat:
#    max-threads: 10 #tomcat的最大并发值修改为10,默认是200
spring:
  application:
    name: service-order
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/shop?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: root
  cloud:
    nacos: #nacos的作用就是一个注册中心
      discovery:
        server-addr: localhost:8848
    sentinel:
    # Sentinel是个springboot项目的控制台, 提供服务容错方案,通过流量控制、熔断降级、系统负载保护来维持服务的稳定性
    # cmd命令窗口启动Sentinel控制台命令:(cd 到 jar包所在目录)
    # java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.2.jar
    # -Dserver.port 是sentinel服务地址, -Dcsp.sentinel.dashboard.server是控制台服务地址
    # 若启动多个应用,则需要通过 -Dcsp.sentinel.api.port=xxxx 指定客户端监控 API 的端口
      transport:
        port: 9998 # 指定流控服务的地址, 不同微服务的该端口不可一致
        # 跟控制台交流的端口,随意指定一个未被占用的端口即可
        dashboard: localhost:8080 # Sentinel控制台地址
      filter: # 关闭sentinel的CommonFilter实例化,否则无法实现 链路流控 规则
        enabled: false
      # 流控规则持久化到nacos
      datasource:
        dsl:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow # 规则类型,取值见:org.springframework.cloud.alibaba.sentinel.datasource.RuleType
jpa:
  properties:
    hibernate:
      hbm2ddl:
        auto: update
      dialect: org.hibernate.dialect.MySQL5InnoDBDialect

3.In the nacos registration center, click on the configuration list to create a new configuration:

Enter the configuration code to create current limiting or downgrade rules:

[
    {
        "resource": "/order/message5",  
        "limitApp": "default",         
        "grade": 1,                     
        "count": 5,                     
        "strategy": 0,                  
        "controlBehavior": 0,           
        "clusterMode": false            
    }
]

// resource : resource name, that is, the target of the current limiting rule
// limitApp : the call source targeted by the flow control, if it is default, the call source is not distinguished
// grade : the current limiting threshold type (1: QPS, 0: number of threads )
// count : current limit threshold value
// strategy : call relationship current limit strategy (0: direct, 1: association, 2: link)
// controlBehavior : flow control effect (0: direct rejection, 1: WarmUp, 2: Queue at a constant speed)
// clusterMode : cluster or not

4.Test: After restarting the service, the flow control rules in sentinel exist permanently and correspond to the newly created configuration of nacos:

 

Guess you like

Origin blog.csdn.net/weixin_42585386/article/details/109242600