Writing in the front

I drew a map using XMindRecord study notes on Spring Cloud Alibaba(The source file has detailed remarks and references for some nodes, but not all of them are shown because they are too large.Welcome to follow my official account: A Feng architecture Notes background send [map] to get the download link,Has been improved and updated) :

preface

Consider this question:

The configuration of Sentinel degrade fuse, when used in production environment, is generally managed on the console and persisted to Nacos; Microservices listen for configuration changes in Nacos to implement a degraded circuit breaker strategy for service invocation.

If there are many Feign interfaces, for example, service A and service B have some remote calls to Feign interfaces, which need to be configured one by one. ** And most of the parameters configured are the same. Such as:

1. Configure degrade policy for slow response policy of Feign remote call

2. Configure degrade policy for Feign remote call exceptions

3. Configure degradation strategy for the abnormal proportion of Feign remote calls

1-2 service methods are fine for the above configuration; But now that companies have 100-200 microservices in their production environments, there are many more ways to call each other. That for common standard downgrade fuse configuration need manual configuration one by one, that is not too troublesome.

This article will solve this problem, then continue to read.

Source code analysis

Let’s take a look at how Sentinel sets up its circuit breaker policy. In the figure above, we know that Sentinel is configured through the Sentinel console, and then microservices can subscribe to these configurations. Let’s take a look at the source code.

This is the code that listens for nacOS configuration

The core of the above code is the updateValue rule when configuration changes are found. It all adds up to a separated manager class with ruleMap and circuitBreakers. We can guess the demotion rule set and the circuit breaker rule set.

Further down the line, there is a RulePropertyListener in which the reloadFrom method **** reloads the rule; There’s a buildCircuitBreakers method in there, which you can tell by its name is buildCircuitBreakers.

In looking at the buildCircuitBreakers method, we see that it is essentially a matter of traversing the DegradeRule collection and then initializing the CircuitBreaker.

Here we see how the circuit breaker works; The essence is generated by a Survival ule.

The solution

It provides a custom DegradeRule object to generate a fuse. When we were studying Sentinel, they had an Api for defining the degradation rules, and you can go back and look at the previous article, which explained in detail how the Api defined the rules. Let’s look at the case

Provides a definition of a Survival Ule object and a Survival Manager object. The above code defines a slow response degradation policy for the resource name API.

Have you come up with some ideas? To look down.

Solution ideas

Give the overall solution first

The process described in the figure above

1When starting the service, scan the JAR and obtain@FeignClientAnnotated interface (technical difficulty 1: which JAR packages to scan)2Get the calling method in the Feign interface3Creates a DegradeRule object locally. (Technical difficulty 2: Sentinel resource name supports dynamic configuration)4, synchronize the default downgrade circuit breaker rules set to NacosCopy the code

Based on the above flow, we can see that once the microservice is started, the Feign interface is automatically configured with the default degrade circuit breaker and synchronized to Nacos. Combined with the Sentinel console transformation described in the previous article, these reversion rules are immediately displayed on the console without being considered configured.

** Note: ** The above is just an overview of the overall process, we need to consider many scenarios when writing code, such as:

A) When the service is started for the second time, relevant configuration has been found in NACOS. Do you need to modify the configuration of NACOS?

B) how is the default global configuration compatible with manual configuration for some special services degraded in Sentinel console?

These are not here to talk about, this article only introduces the core scheme ideas, core code

Other interested partners can follow the source code

Technical difficulties

The difficulties in the

We scan jar packages, and we scan jars that contain the @FeignClient annotation interface. We know that when using the Feign function, we need to add @enablefeignclients to the SpringBootApplication startup class;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ApplicationA {
  public static void main(String[] args) { SpringApplication.run(ApplicationA.class, args); }}Copy the code

Sometimes Feign packages are stored as third-party jars, and the code becomes

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.rainbow.demo1.feign","com.rainbow.demo2.feign"})
public class ApplicationA {
  public static void main(String[] args) { SpringApplication.run(ApplicationA.class, args); }}Copy the code

The ** @enableFeignClients attribute basePackages explicitly points to the Feign package location **. This is easier to fix by using the ClassScan utility class.

The ClassScan utility class supports subpackage scanning

There is no explicit definition of basePackages, so how to get the jar package path?

We can refer to the source code implementation method of SpringCloud to see the code.

Above is the start class object of the main method based on the stack information when the service is started.

Get the EnableFeignClients object based on the launch class object, or if there are no basePackages, the start class package is the entry to the scan.

This solves the problem of scanning jar entries.

The difficulties in the second

The conventional way

Get the resource name, for example

@FeignClient(name = "service-provider")
public interface ProviderServiceFeign {
    @GetMapping("/transferHeaders")
    public BaseRestResponse<String> transferHeaders(a);
}
Copy the code

According to the Sentinel resource name definition of microservice, @feignClient (name = “service-provider”), the microservice name is service-provider; The resource name of the degrade policy for the transferHeaders() method is

lb://service-provider/transferHeaders
Copy the code

The simple implementation is to get the @feignClient name value and the @getMapping value to concatenate the resource name.

Specify the Url address

@FeignClient(name = "service-provider",url = "http://xxxxx")
public interface ProviderServiceFeign {
    @GetMapping("/transferHeaders")
    public BaseRestResponse<String> transferHeaders(a);
}
Copy the code

In this case, the resource name of Sentinel is

http://xxxxx/transferHeaders
Copy the code

The technical implementation is also relatively simple, just need to consider this scenario, it is ok.

Dynamically Configuring the Url

Another situation is that when connecting to a third-party platform, we generally do not write dead Url, but through configuration, such as

@FeignClient(name = "service-provider",url = "${reqUrl}")
public interface ProviderServiceFeign {
    @GetMapping("/transferHeaders")
    public BaseRestResponse<String> transferHeaders(a);
}
Copy the code

${reqUrl} = ${reqUrl}; ** Essentially, the resource name is also the Url+ the specific requested address, i.e

http://${reqUrl}/transferHeaders
Copy the code

However, setting the resource name in this way is definitely not correct, you need to take the specific configuration value to concatenate. ${reqUrl} ${reqUrl} ${reqUrl} It’s just using

Environment environment ;// Environment variable object
this.environment.resolvePlaceholders(url);// Get the value of the variable
Copy the code

The core code

After the above technical difficulties are solved, we will let go of the hands of the code, here attached to the core code; Guys.

public class DegradeRuleInitializer implements ApplicationRunner.EnvironmentAware
Copy the code

Implementing ApplicationRunner, EnvironmentAware enables you to implement the run method in ApplicationRunner at startup, to scan the entry.

Scan class

Scanning FeignClient

Initialize the default rule

Default degradation rules are set and the configuration information is published to NACOS

The effect

Once the microservice is started, the NACOS configuration is available

We will publish the default values to nacOS. You can see the resource names in detail, and there will be a lot of degradation rules.

Take a look at the Sentinel console, which displays a list of downgrading rules. This paper designs three types of degraded circuit breaker strategies for the same resource name, such as number of exceptions, proportion of exceptions and slow response.

The global default value, exactly what the threshold is, can be configured, these will not be described. It’s easy.

By now, the default configuration of the degraded fuse policy of Feign interface in microservice has been realized. There is no need to add it manually. Of course, manual modification is supported. If the threshold value needs to be modified, it can be manually modified.

conclusion

In this paper, the implementation scheme of Sentinel global Feign default fuse is introduced. The overall idea and principle are not too complicated, but some extensions are made by using its own functions. This is more convenient for users.

Three things to watch ❤️

If you find this article helpful, I’d like to invite you to do three small favors for me:

  1. Like, forward, have your “like and comment”, is the motivation of my creation.
  2. Follow the public account “ARCHITECTURE Notes of A Wind” and share original knowledge from time to time.
  3. Also look forward to the follow-up article ing🚀
  4. [666] Scan code to obtain the architecture advanced learning materials package