Following the spring Cloud: Microservices Environment (Alibaba) enhancement (limiting, degrading, fusing) rule configuration, this part of the rule persistence.

Refer to the official

1. Rule management and push

Generally speaking, there are three modes for pushing rules:

Push model instructions advantages disadvantages
The original pattern The API pushes rules to the client and updates them directly to memory, extending the Write datasource Simple, without any dependencies Consistency is not guaranteed; The rules are saved in memory and disappear upon reboot. Very not recommended for production
The Pull model Extended write datasource, where the client actively polls the pull rules to a rule management center on a regular basis, be it an RDBMS, a file, etc Simple, without any dependencies; Rule persistence Consistency is not guaranteed; Real-time is not guaranteed, too often pull may have performance problems.
Push model Extended Read data source (ReadableDataSource), rule center unified push, the client through the registration of listener constantly monitor changes, such as the use of Nacos, Zookeeper and other configuration center. This method has better real-time performance and consistency assurance.Data sources in push mode are generally used in production environments. Rule persistence; Consistency; fast Introducing third party dependencies

2. Raw mode

If no changes are made, Dashboard pushes rules to clients through APIS and updates them directly into memory, as shown in the following diagram:

The advantage of this approach is simplicity and no dependence; The downside is that the application of the restart rule disappears and is only used for simple testing, not production. This is the pattern we experimented with earlier.

3. Pull Pull mode

Data sources in Pull mode (such as local files, RDBMS, and so on) are generally writable. When using need to register on the client data source: read the corresponding data source registered to the corresponding RuleManager, will write WritableDataSourceRegistry registered to transport data source. Take the local file data source as an example:

The local file data source periodically polls the file for changes and reads the rules. This allows us to either update the rules locally by modifying the files directly or push the rules through the Sentinel console. Taking local file data source as an example, the push process is shown in the figure below:

The advantage of this implementation method is that it is simple and does not introduce new dependencies, while the disadvantage is that it cannot guarantee the consistency of monitoring data.

  • Step 1: Add the configuration

Temp – gateway project

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-extension</artifactId>
    </dependency>
Copy the code
  • Step 2: write the persistence code implementation com. Alibaba. CSP. Sentinel. Init. InitFunc

FileDataSourceInit.java

package com.temp.conf;
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 org.springframework.stereotype.Component;

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

/** * Custom sentry storage file data source load class */
@Component
public class FileDataSourceInit implements InitFunc {
	@Override
	public void init(a) throws Exception {
		// TIPS: If you don't like this path, you can change it to your preferred path.
		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);
		// Flow control rule
		ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(
				flowRulePath,
				flowRuleListParser
		);
		// Register the readable data source with the FlowRule Manager
		// When the rules file changes, the rules are updated to memory.
		FlowRuleManager.register2Property(flowRuleRDS.getProperty());

		WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
				flowRulePath,
				this::encodeJson
		);
		// Register the writable data source registry in the transport module
		// In this way, Sentinel updates the rules to memory and then writes them to a file when it receives the pushed rules from the console.
		WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);

		// Demote rule
		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);

		// System Rules
		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);

		// Authorization rules
		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);

		// Hot spot parameter rule
		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);
	}

	/** * Object Conversion of Flow Control Rules */
	private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(
			source,
			new TypeReference<List<FlowRule>>() {
			}
	);
	/** * Degradation Rule Object Conversion */
	private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(
			source,
			new TypeReference<List<DegradeRule>>() {
			}
	);
	/** * System Rule Object Conversion */
	private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(
			source,
			new TypeReference<List<SystemRule>>() {
			}
	);

	/** * Authorization Rule Object Conversion */
	private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject(
			source,
			new TypeReference<List<AuthorityRule>>() {
			}
	);

	/** * Hot Rule Object Conversion */
	private Converter<String, List<ParamFlowRule>> hotParamFlowRuleListParser = source -> JSON.parseObject(
			source,
			new TypeReference<List<ParamFlowRule>>() {
			}
	);

	/**
	 * Create directories
	 *
	 * @param filePath
	 */
	private void mkdirIfNotExits(String filePath) {
		File file = new File(filePath);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	/**
	 * create a file
	 *
	 * @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) {
		returnJSON.toJSONString(t); }}Copy the code
  • Create a configuration directory meta-INF /services under Resources.

Then add files com. Alibaba. CSP. Sentinel. Init. InitFunc

In this file, add the full path of the previous configuration file

com.temp.conf.FilePersistence
Copy the code

After restarting service-gateway, you can find json file groups in the User directory

And notice what you see here,The file sizes are all 0KB

  • Step 4: Modify “/ flow-rule-json”

flow-rule.json

[{"resource": "item_route"."count": 1.0."intervalSec": 3}]Copy the code
  • Step 5: test – test – http://localhost:7000/item-serv/item/1

It is found that the execution response API limiting is in effect, although the console rule is not displayed

Push mode

In production environments, data sources in Push mode are more commonly used. For data sources in Push mode, such as remote configuration centers (ZooKeeper, Nocos, Apollo, etc.), Push operations should not be performed by Sentinel clients; The data source is only responsible for obtaining the configuration pushed by the configuration center and updating it locally. Therefore, the correct way of push rule should be configuration center console /Sentinel control center — “configuration center –” Sentinel data source — “Sentinel, instead of being pushed to the configuration center by Sentinel data source. The process is pretty clear.

By default, when we configure rules in the Sentinel console, the console pushes the rules to the client via the API and updates them directly into memory. Once we restart the application, the rule will disappear. Let’s take a look at how to persist configuration rules, using Nacos as an example.

  • Push rules to Nacos or other remote configuration centers
  • Sentinel client linked to Nacos to obtain the rule configuration. And listens for Nacos configuration changes, updating the local cache if any (so that the local cache is always consistent with Nacos)

The console listens for Nacos configuration changes and updates the local cache if they occur (so that the console local cache is always consistent with Nacos)

Data sources in push mode are commonly used in production environments. Delete the meta-inf/services/com. Alibaba. CSP. Sentinel. Init. InitFunc content

5. Implement persistence for recommended Push mode transformation

5.1. Download Sentinel 1.8.1 source code

Download: github.com/alibaba/Sen…

After decompression, we opened it in IDEA, updated maven dependencies, and obtained project files. Sentinel-dashboard module is the main role of this time, and our transformation is carried out in this module.

5.2 modified pom. XML

Open the sentinel-Dashboard module’s pom. XML file, find the Sentinel-datasource-nacos dependency, remove test:

5.3 Example code for Copying traffic Limiting Rules

The SRC/test/Java/com/alibaba/CSP/sentinel/dashboard/rule/nacos folder copy to the SRC/main/Java/com/alibaba/CSP/sentinel/dashboard/rule Record:

Left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left down down down down down

5.4 Connecting to Nacos

5.4.1 Open the application.properties file and add the nacOS-related configuration.

#spring settings
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true

#cookie name setting
server.servlet.session.cookie.name=sentinel_dashboard_cookie

#logging settings
logging.level.org.springframework.web=INFO
logging.file=${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}
# nacOS-related configuration
nacos.address=localhost:8848
# SENTINEL_GROUP = public, groupId = SENTINEL_GROUP
nacos.namespace=dev
If Nacos has authentication enabled, add username/password
nacos.username=nacos
nacos.password=nacos
Copy the code

5.4.2 open com. Alibaba. CSP. Sentinel. Dashboard. Rule. Nacos. NacosConfig, introducing just fill out the configuration information, if there is no open authentication nacos does not need the username and password.

NacosConfig.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Properties;

/ * * *@author Eric Zhao
 * @since1.4.0 * /
@Configuration
public class NacosConfig {

    /** * Nacos console address */
    @Value("${nacos.address}")
    private String address;
    /** * Nacos namespace */
    @Value("${nacos.namespace}")
    private String namespace;
    /** * Nacos authentication user name */
    @Value("${nacos.username}")
    private String username;
    /** * Nacos authentication password */
    @Value("${nacos.password}")
    private String password;
    @Bean
    public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, FlowRuleEntity.class);
    }

    /** * Modify the Nacos configuration *@return
     * @throws Exception
     */
    @Bean
    public ConfigService nacosConfigService(a) throws Exception {
// return ConfigFactory.createConfigService("localhost");
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR,address);
        properties.put(PropertyKeyConst.NAMESPACE,namespace);
        properties.put(PropertyKeyConst.USERNAME,username);
        properties.put(PropertyKeyConst.PASSWORD,password);
        returnConfigFactory.createConfigService(properties); }}Copy the code

5.4.3 Modifying beans injected by flow Control Rules

Open com. Alibaba. CSP. Sentinel. Dashboard. Controller. V2. FlowControllerV2 class, we just injection of current limiting rule class. FlowControllerV2.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.controller.v2;

import java.util.Date;
import java.util.List;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.util.StringUtil;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.domain.Result;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Flow rule controller (v2).
 *
 * @author Eric Zhao
 * @since1.4.0 * /
@RestController
@RequestMapping(value = "/v2/flow")
public class FlowControllerV2 {

    private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);

    @Autowired
    private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;

    @Autowired
// @Qualifier("flowRuleDefaultProvider")
    @Qualifier("flowRuleNacosProvider")
    private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
    @Autowired
// @Qualifier("flowRuleDefaultPublisher")
    @Qualifier("flowRuleNacosPublisher")
    privateDynamicRulePublisher<List<FlowRuleEntity>> rulePublisher; .Copy the code

5.4.4 Modifying a Static File

  • Open the SRC/main/webapp/resources/app/scripts/directives/sidebar sidebar. HTML, find dashboard. FlowV1 ({app: Entry.app}) to dashboard.flow({app: entry.app}).

  • Open the SRC/main/webapp/resources/app/scripts/controllers/identity, js, the FlowServiceV1 FlowServiceV2 instead.

5.5 Startup Test

At this point, the traffic limiting rule part of the console has been modified. DashboardApplication class is directly started in IDEA to test the effect, and then a micro-service is started to connect to Sentinel. The micro-service interface is accessed once so that the sentinel console can detect the path. Click flow control rules on the console, add a new flow limiting rule in the upper right corner, and check whether the corresponding configuration file is generated in Nacos.

Jar package, copy to /run_env/, and start start_sentinel.bat

5.5.1 Adding Rules to Sentinel Console — View the Nacos configuration

At this point, may appear question Q1: java.net.ConnectException: Connection refused: no further information

A1: indicates the IP address of the machine to be viewed

I’m stuck here. I can’t get out. Turn off the computer and go to sleep. Later that night, I booted up my computer and something wonderful happened.

Q2: The screen style will also be different, which needs to be confirmed

V1 layoutV2 Layout – View number of items

Add new flow control —

Check it out at Nacos right now

Go to edit for a closer look (accident happened) :

And then we change it to JSON, and we change the data to see if we can reflect it on Sentinel Dashboard.

Make two changes to see Sentinel Dashboard changes.

Current limiting experiment:

Summary: It can be seen that the flow control rule is persisted successfully.

5.6 Modify Other Rules

5.6.1 Setting the Configuration File

Open the com. Alibaba. CSP. Sentinel. Dashboard. Rule. Nacos. NacosConfigUtil class, add rule configuration file suffix.

Nacosconfigutil.java add-on

/ / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left the add new rule down down down down down postfix left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left left down down down down down down down down down
    public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules";
    public static final String SYSTEM_DATA_ID_POSTFIX = "-system-rules";
    public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules";
/ / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write
Copy the code

5.6.2 Adding a rule push class

Several folders have been built in NacOS to facilitate differentiation. Respectively is:

  • Authority (Licensing Rules)
  • Don’t degrade yourself.
  • Flow (Flow regulation)
  • Param (Hotspot Rule)
  • System (System rules)

And move the previous traffic limiting rules to the corresponding folder. Degrade the FlowRuleNacosProvider and FlowRuleNacosPublisher services by copying them into the degrade directory. Modify in order:

5.6.2.1 Authority/Push class

AuthorityRuleNacosProvider.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.authority;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("authorityRuleNacosProvider")
public class AuthorityRuleNacosProvider implements DynamicRuleProvider<List<AuthorityRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<AuthorityRuleEntity>> converter;

    @Override
    public List<AuthorityRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.AUTHORITY_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        returnconverter.convert(rules); }}Copy the code

AuthorityRuleNacosPublisher.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.authority;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("authorityRuleNacosPublisher")
public class AuthorityRuleNacosPublisher implements DynamicRulePublisher<List<AuthorityRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<AuthorityRuleEntity>, String> converter;

    @Override
    public void publish(String app, List<AuthorityRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return; } configService.publishConfig(app + NacosConfigUtil.AUTHORITY_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, converter.convert(rules)); }}Copy the code

Degrade/Push class

DegradeRuleNacosProvider.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("degradeRuleNacosProvider")
public class DegradeRuleNacosProvider implements DynamicRuleProvider<List<DegradeRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<DegradeRuleEntity>> converter;

    @Override
    public List<DegradeRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        returnconverter.convert(rules); }}Copy the code

DegradeRuleNacosPublisher.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.degrade;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("degradeRuleNacosPublisher")
public class DegradeRuleNacosPublisher implements DynamicRulePublisher<List<DegradeRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<DegradeRuleEntity>, String> converter;

    @Override
    public void publish(String app, List<DegradeRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return; } configService.publishConfig(app + NacosConfigUtil.DEGRADE_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, converter.convert(rules)); }}Copy the code

5.6.2.3 Flow/push class

FlowRuleNacosProvider.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<FlowRuleEntity>> converter;

    @Override
    public List<FlowRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        returnconverter.convert(rules); }}Copy the code

FlowRuleNacosPublisher.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.flow;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<FlowRuleEntity>, String> converter;

    @Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return; } configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, converter.convert(rules)); }}Copy the code

5.6.2.4 Param/push classes

ParamFlowRuleNacosProvider.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.param;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("paramFlowRuleNacosProvider")
public class ParamFlowRuleNacosProvider implements DynamicRuleProvider<List<ParamFlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<ParamFlowRuleEntity>> converter;

    @Override
    public List<ParamFlowRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        returnconverter.convert(rules); }}Copy the code

ParamFlowRuleNacosPublisher.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.param;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("paramFlowRuleNacosPublisher")
public class ParamFlowRuleNacosPublisher implements DynamicRulePublisher<List<ParamFlowRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<ParamFlowRuleEntity>, String> converter;

    @Override
    public void publish(String app, List<ParamFlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return; } configService.publishConfig(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, converter.convert(rules)); }}Copy the code

5.6.2.5 System/Push classes

SystemRuleNacosProvider.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.system;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("systemFlowRuleNacosProvider")
public class SystemRuleNacosProvider implements DynamicRuleProvider<List<SystemRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<SystemRuleEntity>> converter;

    @Override
    public List<SystemRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.SYSTEM_DATA_ID_POSTFIX,
            NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        returnconverter.convert(rules); }}Copy the code

SystemRuleNacosPublisher.java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.rule.nacos.system;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/ * * *@author luds
 * @since1.4.0 * /
@Component("systemRuleNacosPublisher")
public class SystemRuleNacosPublisher implements DynamicRulePublisher<List<SystemRuleEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<SystemRuleEntity>, String> converter;

    @Override
    public void publish(String app, List<SystemRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return; } configService.publishConfig(app + NacosConfigUtil.SYSTEM_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, converter.convert(rules)); }}Copy the code

5.6.3 NacosConfig Added rule conversion

    @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<SystemRuleEntity>, String> systemRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String, List<SystemRuleEntity>> systemRuleEntityDecoder() {
        return s -> JSON.parseArray(s, SystemRuleEntity.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<ParamFlowRuleEntity>, String> paramFlowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String, List<ParamFlowRuleEntity>> paramFlowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
    }
Copy the code

5.6.4 Modifying a Controller of the Degrade Rule

Com. Alibaba. CSP. Sentinel. Dashboard. Controller. DegradeController replaced with the following contents: DegradeController. Java

Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License"). * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the  License. */
package com.alibaba.csp.sentinel.dashboard.controller;

import java.util.Date;
import java.util.List;

import com.alibaba.csp.sentinel.dashboard.auth.AuthAction;
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient;
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo;
import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType;
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.CircuitBreakerStrategy;
import com.alibaba.csp.sentinel.util.StringUtil;

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity;
import com.alibaba.csp.sentinel.dashboard.domain.Result;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

** * Controller regarding APIs of degrade rules. Refactored since 1.8.0. **@author Carpenter Lee
 * @author Eric Zhao
 */
@RestController
@RequestMapping("/degrade")
public class DegradeController {

    private final Logger logger = LoggerFactory.getLogger(DegradeController.class);

    @Autowired
    private RuleRepository<DegradeRuleEntity, Long> repository;
    / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
// @Autowired
// private SentinelApiClient sentinelApiClient;
    @Autowired
    @Qualifier("degradeRuleNacosProvider")
    private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;
    @Autowired
    @Qualifier("degradeRuleNacosPublisher")
    private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;
    / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write
    @GetMapping("/rules.json")
    @AuthAction(PrivilegeType.READ_RULE)
    public Result<List<DegradeRuleEntity>> apiQueryMachineRules(String app, String ip, Integer port) {
        if (StringUtil.isEmpty(app)) {
            return Result.ofFail(-1."app can't be null or empty");
        }
        if (StringUtil.isEmpty(ip)) {
            return Result.ofFail(-1."ip can't be null or empty");
        }
        if (port == null) {
            return Result.ofFail(-1."port can't be null");
        }
        try {
            / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
// List
      
        rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);
      
            List<DegradeRuleEntity> rules = ruleProvider.getRules(app);
            / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write
            rules = repository.saveAll(rules);
            return Result.ofSuccess(rules);
        } catch (Throwable throwable) {
            logger.error("queryApps error:", throwable);
            return Result.ofThrowable(-1, throwable); }}@PostMapping("/rule")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<DegradeRuleEntity> apiAddRule(@RequestBody DegradeRuleEntity entity) throws Exception {
        Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
        if(checkResult ! =null) {
            return checkResult;
        }
        Date date = new Date();
        entity.setGmtCreate(date);
        entity.setGmtModified(date);
        try {
            entity = repository.save(entity);
        } catch (Throwable t) {
            logger.error("Failed to add new degrade rule, app={}, ip={}", entity.getApp(), entity.getIp(), t);
            return Result.ofThrowable(-1, t);
        }
        / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
// if (! publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
// logger.warn("Publish degrade rules failed, app={}", entity.getApp());
/ /}
        / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write
        publishRules(entity.getApp());
        return Result.ofSuccess(entity);
    }

    @PutMapping("/rule/{id}")
    @AuthAction(PrivilegeType.WRITE_RULE)
    public Result<DegradeRuleEntity> apiUpdateRule(@PathVariable("id") Long id,
                                                     @RequestBody DegradeRuleEntity entity) throws Exception {
        if (id == null || id <= 0) {
            return Result.ofFail(-1."id can't be null or negative");
        }
        DegradeRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofFail(-1."Degrade rule does not exist, id=" + id);
        }
        entity.setApp(oldEntity.getApp());
        entity.setIp(oldEntity.getIp());
        entity.setPort(oldEntity.getPort());
        entity.setId(oldEntity.getId());
        Result<DegradeRuleEntity> checkResult = checkEntityInternal(entity);
        if(checkResult ! =null) {
            return checkResult;
        }

        entity.setGmtCreate(oldEntity.getGmtCreate());
        entity.setGmtModified(new Date());
        try {
            entity = repository.save(entity);
        } catch (Throwable t) {
            logger.error("Failed to save degrade rule, id={}, rule={}", id, entity, t);
            return Result.ofThrowable(-1, t);
        }
        / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
// if (! publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
// logger.warn("Publish degrade rules failed, app={}", entity.getApp());
/ /}
        publishRules(entity.getApp());
        / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write
        return Result.ofSuccess(entity);
    }

    @DeleteMapping("/rule/{id}")
    @AuthAction(PrivilegeType.DELETE_RULE)
    public Result<Long> delete(@PathVariable("id") Long id) throws Exception {
        if (id == null) {
            return Result.ofFail(-1."id can't be null");
        }

        DegradeRuleEntity oldEntity = repository.findById(id);
        if (oldEntity == null) {
            return Result.ofSuccess(null);
        }

        try {
            repository.delete(id);
        } catch (Throwable throwable) {
            logger.error("Failed to delete degrade rule, id={}", id, throwable);
            return Result.ofThrowable(-1, throwable);
        }
        / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
        / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write
// if (! publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
// logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
/ /}
        publishRules(oldEntity.getApp());
        return Result.ofSuccess(id);
    }
    / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
// private boolean publishRules(String app, String ip, Integer port) {
// List
      
        rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
      
// return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
/ /}
    private void publishRules(String app) throws Exception {
        List<DegradeRuleEntity> rules = repository.findAllByApp(app);
        rulePublisher.publish(app, rules);
    }
    / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write


    private <R> Result<R> checkEntityInternal(DegradeRuleEntity entity) {
        if (StringUtil.isBlank(entity.getApp())) {
            return Result.ofFail(-1."app can't be blank");
        }
        / / left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left left down down down down down down down down down left left left left modified start left left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down
// if (StringUtil.isBlank(entity.getIp())) {
// return Result.ofFail(-1, "ip can't be null or empty");
/ /}
// if (entity.getPort() == null || entity.getPort() <= 0) {
// return Result.ofFail(-1, "invalid port: " + entity.getPort());
/ /}
        / / write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write write corrected write write write write write write write write write write write write write write write write write write write write write write write write write write write
        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");
        }
        Double threshold = entity.getCount();
        if (threshold == null || threshold < 0) {
            return Result.ofFail(-1."invalid threshold: " + threshold);
        }
        Integer recoveryTimeoutSec = entity.getTimeWindow();
        if (recoveryTimeoutSec == null || recoveryTimeoutSec <= 0) {
            return Result.ofFail(-1."recoveryTimeout should be positive");
        }
        Integer strategy = entity.getGrade();
        if (strategy == null) {
            return Result.ofFail(-1."circuit breaker strategy cannot be null");
        }
        if (strategy < CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()
            || strategy > RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
            return Result.ofFail(-1."Invalid circuit breaker strategy: " + strategy);
        }
        if (entity.getMinRequestAmount()  == null || entity.getMinRequestAmount() <= 0) {
            return Result.ofFail(-1."Invalid minRequestAmount");
        }
        if (entity.getStatIntervalMs() == null || entity.getStatIntervalMs() <= 0) {
            return Result.ofFail(-1."Invalid statInterval");
        }
        if (strategy == RuleConstant.DEGRADE_GRADE_RT) {
            Double slowRatio = entity.getSlowRatioThreshold();
            if (slowRatio == null) {
                return Result.ofFail(-1."SlowRatioThreshold is required for slow request ratio strategy");
            } else if (slowRatio < 0 || slowRatio > 1) {
                return Result.ofFail(-1."SlowRatioThreshold should be in range: [0.0, 1.0]"); }}else if (strategy == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
            if (threshold > 1) {
                return Result.ofFail(-1."Ratio threshold should be in range: [0.0, 1.0]"); }}return null; }}Copy the code

5.6.5 Modifying an Authorization Rule Controller

Com. Alibaba. CSP. Sentinel. Dashboard. Controller. AuthorityRuleController replaced with the following contents: AuthorityRuleController. Java reference to modify the relegation rule controller

5.6.6 Modifying a Hotspot Rule Controller

Com. Alibaba. CSP. Sentinel. Dashboard. Controller. ParamFlowRuleController replaced with the following contents: ParamFlowRuleController. Java reference to modify the relegation rule controller

5.6.7 Modifying the System Rule Controller

Com. Alibaba. CSP. Sentinel. Dashboard. Controller. The SystemController replaced with the following contents: SystemController. Java reference to modify the relegation rule controller

5.7 test

The Sentinel side adds a degradation rule:

Check whether the Nacos side appears:

Code: gitee.com/actual-comb…