Recommended reading:

Notes on the Learning route of Spring Cloud Alibaba microservice Architecture

Problems with high concurrency

In micro service architecture, we will split into small business service, service and service can call each other between, but due to network or its own reasons, 100% of the service does not guarantee available, if a single service problems, invoking the service network delay will occur and then if there is a lot of network, will form the task, Eventually, the service crashed.

Next, let’s simulate a high concurrency scenario

1 Write Java code

@RestController 

@Slf4j 

public class OrderController2 { 

@Autowired 

private OrderService orderService; 

@Autowired 

private ProductService productService; 

@RequestMapping("/order/prod/{pid}") 

public Order order(@PathVariable("pid") Integer pid) { 

log.info("Received the order request for item {}, then call the product microservice to query the information of this item", pid);// Call product microservice to query product information

Product product = productService.findByPid(pid); 

log.info("The information of item {} was found :{}", pid, JSON.toJSONString(product)); 

// Simulate a network delay

try {

Thread.sleep(100); 

} catch (InterruptedException e) { 

e.printStackTrace(); 

}

// Place an order

Order order = new Order(); 

order.setUid(1); 

order.setUsername("Test user"); 

order.setPid(pid); 

order.setPname(product.getPname()); 

order.setPprice(product.getPprice()); 

order.setNumber(1); 

// In order not to generate too much garbage data, do not do order save temporarily

//orderService.createOrder(order); 

log.info("Order created successfully with order information {}", JSON.toJSONString(order)); 

return order; 

}

@RequestMapping("/order/message") 

public String message(a) { 

return "Problem testing at high concurrency"; }}Copy the code

2 Change the number of Concurrent Tomcat entries in the configuration file

Server: port: 8091 Tomcat: max-threads: 10 # Change the maximum concurrency value of Tomcat to 10. The default is 200Copy the code

3 Next, use the pressure test tool to stress the request

Download from jmeter.apache.org/

Step 1: Modify the configuration and start the software

Go to the bin directory, change the language support in the jmeter.properties file to language=zh_CN, and then click jmeter.bat to start the software.

Step 2: Add a thread group Step 3: Configure the number of concurrent threads Step 4: Add Http sampling Step 5: Configure sampling and start testing 4 Access the message method to observe the effect Conclusion:You find that the Message method is having trouble accessing because the Order method is hoarding requests, and this is the beginning of a service avalanche.

Service avalanche effect

In distributed systems, services are generally not guaranteed to be 100% available due to network or its own reasons. If there is a problem with a service, a thread blocking occurs when calling the service. If a large number of requests come in, multiple threads will block and wait, causing the service to crash.

The “avalanche effect” of service failures is the spread of failures due to service-to-service dependencies, which can have catastrophic consequences for the entire microservice system.

Avalanches can happen for a variety of reasons, from poor capacity design, to a method that is slow to respond to high concurrency, to a machine that runs out of resources. We cannot completely eliminate the avalanche source, only to do enough fault tolerance, to ensure that a problem in one service will not affect the normal operation of other services. That is, “Snow falls, not avalanche”.

Common fault tolerance schemes

To prevent the spread of avalanche, we need to do a good job of service fault tolerance, fault tolerance is to protect yourself from being dragged down by pig teammates some measures, the following introduces common service fault tolerance ideas and components.

Common fault tolerance ideas

Common fault tolerance ideas include isolation, timeout, current limiting, fusing and degradation, which are introduced below.

  • isolation

It refers to the system is divided into several service modules according to certain principles, each module is relatively independent, no strong dependence. When a fault occurs, the problem and impact can be isolated in a module, and the risk does not spread, does not affect other modules, does not affect the overall system service. Common isolation methods are: thread pool isolation and semaphore isolation.

  • timeout

When the upstream service calls the downstream service, set a maximum response time. If the downstream does not respond after this time, the request is disconnected and the thread is released.

  • Current limiting

Current limiting is to limit the input and output flow of the system to protect the system. In order to ensure the stable operation of the system, once the threshold of limiting traffic is reached, it is necessary to limit traffic and take a few measures to complete the purpose of limiting traffic.

  • fusing

In an Internet system, when downstream services respond slowly or fail due to excessive access pressure, upstream services can temporarily cut off calls to downstream services to protect the overall availability of the system. This measure of sacrificing part while preserving the whole is called circuit breaker.

Service fuses generally have three states:

  • Fusing Closed state

The state in which the fuse is in when the service is not faulty does not restrict the call of the caller

  • Fusing on state (Open)

Subsequent calls to the service interface no longer go over the network and execute the local fallback method directly

  • Half-open state

Try to resume the service invocation, allowing limited traffic to invoke the service, and monitor the success rate of invocation. If the success rate reaches the expected, it indicates that the service has been restored and enters the fusing shutdown state. If the success rate is still low, the circuit breaker is re-entered.

  • demotion

A downgrade is simply a fallback scheme for a service to be used when the service cannot be called properly.

Common fault tolerant components

  • Hystrix

Hystrix is an open-source delay and fault tolerance library provided by Netflflix to isolate access to remote systems, services, or third-party libraries to prevent cascading failures, thereby improving system availability and fault tolerance.

  • Resilience4J

Resilicence4J is a very lightweight, simple, well-documented, and rich fuse breaker, which is an official Hystrix recommended alternative. Resilicence4j also natively supports Spring Boot 1.x/2.x, and monitoring supports integration with several major products such as Prometheus.

  • Sentinel

Sentinel is an open source circuit breaker implementation of Alibaba. Sentinel itself has been adopted on a large scale in Alibaba and is very stable.

Here’s how the three components compare in all respects:

Sentinel Hystrix resilience4j
Isolation strategy Semaphore isolation (concurrent thread flow limiting) Thread pool isolation/semaphore isolation Semaphore isolation
Fuse downgrading strategy Based on response time, exception ratio, number of exceptions Based on abnormal ratio Based on exception rate, response time
Real-time statistical implementation Sliding Windows (LeapArray) Sliding Windows (based on RxJava) Ring Bit Buffer
Dynamic Rule Configuration Support for multiple data sources Support for multiple data sources Support co., LTD.
scalability Multiple extension points Plug-in form Interface form
Annotation-based support support support support
Current limiting Based on QPS, traffic limiting based on call relationships is supported Limited support Rate Limiter
Traffic shaping Support preheating mode, uniform speed mode, preheating queuing mode Does not support Simple Rate Limiter mode
System adaptive protection support Does not support Does not support
The console Provides out-of-the-box console for configuring rules, viewing second-level monitoring, machine discovery, and more Simple monitoring view No console is provided, and other monitoring systems can be connected
# # Sentinel primer

What is a Sentine

Sentinel (Traffic Defender for Distributed System) is a comprehensive solution for service fault tolerance developed by Alibaba. It in flow

As the entry point, the stability of service is protected from multiple dimensions such as flow control, fusing downgrading and system load protection.

Sentinel has the following characteristics:

  • Rich application scenarios: Sentinel has undertaken the core scenarios of Alibaba’s double Eleven traffic drive in the past 10 years, such as SEC killing (i.e. burst traffic control within the range of system capacity), message peaking and valley filling, cluster flow control, real-time fusing of unavailable downstream applications, etc.

  • Complete real-time monitoring: Sentinel provides real-time monitoring capabilities. The console allows you to see the second-level data of a single machine connected to an application, and even the summary performance of a cluster of less than 500 machines.

  • Extensive Open source ecosystem: Sentinel provides out-of-the-box integration modules with other open source frameworks/libraries, such as SpringCloud, Dubbo, and gRPC. Sentinel can be accessed quickly by introducing dependencies and simple configuration.

  • Sophisticated SPI extension points: Sentinel provides an easy-to-use, sophisticated SPI extension interface. You can quickly customize the logic by implementing an extension interface. For example, customize rule management and adapt dynamic data sources.

Sentinel is divided into two parts:

  • The core library (Java client) is independent of any framework/library, can run in all Java runtime environments, and has good support for frameworks such as Dubbo /Spring Cloud.

  • The Console (Dashboard) is based on Spring Boot and can be packaged to run directly without the need for additional application containers such as Tomcat.

Sentinel microservices integration

Integrating Sentinel for microservices is very simple, just adding the Sentinel dependencies

1 Add the following dependencies to pom.xml

<dependency> 

<groupId>com.alibaba.cloud</groupId> 

<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> 

</dependency>
Copy the code

Write a Controller test to use

@RestController 

@Slf4j 

public class OrderController3 { 

@RequestMapping("/order/message1") 

public String message1(a) { 

return "message1"; 

}

@RequestMapping("/order/message2") 

public String message2(a) { 

return "message2"; }}Copy the code

Install Sentinel console

Sentinel provides a lightweight console that provides machine discovery, real-time monitoring of stand-alone resources, and rule management.

Procedure 1 Download the JAR package and decompress it to the folder

Github.com/alibaba/Sen…

2 Starting the Console

Java-dserver.port = use jar command directly to start project (console itself is a SpringBoot project) java-dserver.port =8080 -Dcsp.sentinel.dashboard.server=localhost:8080 - 

Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7. 0.jar
Copy the code

Modify shop-order and add the configuration about the console in it

Spring: Cloud: sentinel: transport: port: 9999 # Specify an unused port to communicate with the consoleCopy the code

Step 4: Access the console by accessing localhost:8080 from your browser (default username password is sentinel/sentinel)

Addendum: Understand how the console works

Sentinel’s console is actually a program written by SpringBoot. We need to register our microserver with the console, that is, specify the address of the console in the microservice, and open a port to pass data to the console. The console can also call the monitor in the microservice through this port to get various information about the microservice.

Implement traffic limiting for an interface

1 Add a flow control rule to Message1 on the console

2 Quickly and frequently access the console to observe the effect

Concept and function of Sentinel

The basic concept

  • resources

Resources are what Sentinel is trying to protect

Resources are the key concept of Sentinel. It can be anything in a Java application, a service, a method, or even a piece of code.

The Message1 method in our introductory example can be considered a resource

  • The rules

Rules define how to protect resources, right

Function on resources, define the way to protect resources, mainly including flow control rules, fuse degradation rules and system protection rules.

In our introductory case, we set a flow control rule for Message1 resources, limiting the flow into Message1

Important features

The main function of Sentinel is fault tolerance, which is mainly reflected in the following three aspects:

  • Flow control

Flow control is a common concept in network transport, which is used to adjust the data of network packets. Requests arriving at any time are often random and uncontrollable, and the processing capacity of the system is limited. We need to control the flow according to the processing capacity of the system. Sentinel acts as a dispatcher that adjusts random requests to fit as needed.

  • Fusing the drop

When a resource in the invocation link is detected to be unstable, for example, the request response time is long or the proportion of exceptions is high, the invocation of this resource is restricted to ensure that the request fails quickly and avoid cascading faults caused by other resources

Sentinel approaches this problem in two ways:

  • Limit by the number of concurrent threads

Sentinel reduces the impact of unstable resources on other resources by limiting the number of concurrent threads for resources. When a resource is unstable, such as a long response time, the direct effect on the resource is a gradual accumulation of threads. When the number of threads accumulates to a certain number on a particular resource, new requests for that resource are rejected. The stacked thread completes its task before continuing to receive requests.

  • Degrade resources by response time

In addition to controlling the number of concurrent threads, Sentinel can quickly degrade unstable resources through response time. If the response time of a dependent resource is too long, all access to the resource is denied until the specified time window expires.

Difference between Sentinel and Hystrix

The principle of both is that when a resource fails, let it fail quickly and do not spill over to other services

But with regard to the means of restraint, a completely different method was adopted:

  • Hystrix uses thread pool isolation, which has the advantage of isolating resources from each other, but has the disadvantage of increasing the cost of thread switching.
  • Sentinel uses the number of concurrent threads and response time to limit resources.
  • System load protection

Sentinel also provides adaptive protection at the system dimension. When the system is under high load, continuing to let requests in can cause the system to crash and fail to respond. In a clustered environment, traffic that should be carried by this machine is forwarded to other machines. If other machines are in an edge state at this time, Sentinel provides a protection mechanism to balance the system’s incoming traffic with the system’s load, ensuring that the system can handle the most requests within its capacity

In short: What we need to do is to configure various rules on Sentinel resources to implement various fault-tolerant features.

Sentinel rule

Flow control rules

Traffic control monitors application traffic indicators, such as QPS(query rate per second) or number of concurrent threads, and controls the traffic when it reaches a specified threshold to avoid being overwhelmed by instantaneous traffic peaks and ensure high availability of applications.

Step 1: Click the cluster link, we can see the address of the interface visited, and then click the corresponding flow control button to enter the flow control rule configuration page. The flow control rule page is added as follows:

Resource name: unique name, default is the request path, can be customized

Source specific: Specifies which microservice to limit traffic. The default value is default, which means that all microservices are restricted regardless of source

Threshold Type Single-node threshold:

  • QPS (Number of requests per second) : Traffic limiting is performed when the NUMBER of QPS calling the interface reaches the threshold

  • Number of threads: When the number of threads calling the interface reaches the threshold, traffic limiting is performed

Cluster or not: No cluster is required

Next, we take QPS as an example to study the configuration of traffic limiting rules.

Simple configuration

Let’s do a simple configuration and set the threshold type to QPS and the single-machine threshold to 3. That is, traffic limiting starts when the number of requests per second is greater than 3. Next, you can see this configuration on the flow Control Rules page.

Configure the flow control mode

Click the edit button above to set flow control rules, and then click advanced options in the edit page, you will see the column of flow control mode

Sentinel has three flow control modes:

  • Direct (default) : Enables traffic limiting when the interface meets traffic limiting conditions

  • Association: Enable traffic limiting when the associated resource reaches the traffic limiting condition.

  • Link: Enables traffic limiting when the resources from an interface meet traffic limiting conditions

Here are three modes:

Direct flow control mode

Direct flow control is the simplest mode. When the specified interface reaches the traffic limiting condition, enable traffic limiting. The above case uses the direct flow control mode.

Associated flow control mode

In associated flow control mode, when the interface associated with the specified interface reaches the traffic limiting condition, enable traffic limiting for the specified interface. Step 1: Configure traffic limiting rules. Set the flow control mode to Association and the associated resource to /order/message2.

Step 3: Send the request to /order/ Message2 continuously via postman software. Note that the QPS must be greater than 3

Step 4: Access /order/message1 to find that the stream has been restricted

Link flow control mode

In link flow control mode, when the resources from an interface meet traffic limiting conditions, traffic limiting is enabled. Its function is somewhat similar to that of the source-specific configuration item, except that source-specific is for the upper-level microservice, whereas link-flow control is for the upper-level interface, which means it is more granular.

Step 1: Write a service and add a method message to it

@Service 

public class OrderServiceImpl3 { 

@SentinelResource("message") 

public void message(a) { 

System.out.println("message"); }}Copy the code

Step 2: Declare two methods in Controller, each calling method M in Service

@RestController 

@Slf4j 

public class OrderController3 { 

@Autowired 

private OrderServiceImpl3 orderServiceImpl3; 

@RequestMapping("/order/message1") 

public String message1(a) { 

orderServiceImpl3.message(); 

return "message1"; 

}

@RequestMapping("/order/message2") 

public String message2(a) { 

orderServiceImpl3.message(); 

return "message2"; }}Copy the code

Step 3: Forbid convergence of URL entry context

Starting from version 1.6.3, Sentinel Web FiFilter converges the entry context of all urls by default, so link limiting does not take effect.

As of version 1.7.0 (corresponding to SCA’s 2.1.1.release), CommonFilter was officially introduced

Web_context_unity parameter, which controls whether context convergence is enabled. Set this parameter to false to perform traffic limiting based on different urls.

SCA 2.1.1. After the RELEASE of version, can be configured spring. Cloud. Sentinel. The web context – unity = false convergence we can shut down the current used version is SpringCloud Alibaba 2.1.0.release, link traffic limiting cannot be realized.

Currently, SCA 2.1.2.RELEASE has not been officially released, so we can only use 2.1.1.RELEASE, which needs to be implemented in the form of writing code

(1) Temporarily adjust the version of SpringCloud Alibaba to 2.1.1.release

<spring-cloud-alibaba.version>2.1.1. RELEASE</spring-cloud-alibaba.version>
Copy the code

(2) Disable CommonFilter instantiation of sentinel in config file

spring: 

cloud:

sentinel: 

filter: 

enabled: false
Copy the code

(3) Add a configuration class and build your own CommonFilter instance

package com.itheima.config; 

import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; 

import org.springframework.boot.web.servlet.FilterRegistrationBean; 

import org.springframework.context.annotation.Bean; 

import org.springframework.context.annotation.Configuration; 

@Configuration 

public class FilterContextConfig { 

@Bean 

public FilterRegistrationBean sentinelFilterRegistration(a) { 

FilterRegistrationBean registration = new FilterRegistrationBean(); 

registration.setFilter(new CommonFilter()); 

registration.addUrlPatterns("/ *"); 

// Close aggregation of incoming resources

registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false"); 

registration.setName("sentinelFilter"); 

registration.setOrder(1); 

returnregistration; }}Copy the code

Step 4: Configure traffic limiting rules on the console

Step 5: Pass separately/ order/message1 and/order/message2Access, found that 2 is ok, 1 is restricted

Configure the flow control effect

  • Fail fast (default) : Fail directly, throwing an exception without doing any extra processing, is the simplest effect

  • Warm Up: It has a buffering phase from the start threshold to the maximum QPS threshold, starting at 1/3 of the maximum QPS threshold and growing slowly until it reaches the maximum threshold. It is suitable for scenarios where sudden increases in traffic are converted into slow increases.

  • Queuing: Let the requests pass at a uniform speed, the single-machine threshold is the number of passes per second, the rest of the queuing; It also lets you set a timeout period, and when a request exceeds the elapsed time and is not processed, it will be discarded

4.6.2 Demotion rules

A degrade rule is a service that is degraded when certain conditions are met. Sentinel provides three measures:

  • Average response time: When the average response time of a resource exceeds the threshold (in ms), the resource enters the quasi-degraded state. If five requests continue to come in for the next 1s, and their RT continues to exceed this threshold, the method will be degraded within the next time window (in s).

Pay attention to the Sentinel default statistical RT limit is 4900 ms, is beyond the threshold will be classified as 4900 ms, if need to change this limit by startup configuration items – Dcsp. Sentinel. Statistic. Max. RT = XXX to configure.

  • Exception ratio: When the ratio of the total number of exceptions per second to the number of passes of a resource exceeds the threshold, the resource enters the degraded state, that is, in the next time window (in s), all calls to this method are automatically returned. The threshold range for abnormal ratios is [0.0,1.0].

Step 1: First simulate an exception

int i = 0; 

@RequestMapping("/order/message2") 

public String message2(a) { 

i++; 

// The exception ratio is 0.333

if (i % 3= =0) {throw new RuntimeException(); 

}

return "message2"; 

}
Copy the code

Step 2: Set the exception ratio to 0.25

  • Number of exceptions: When the number of exceptions in one minute exceeds the threshold, services are degraded. Note that the statistical time window is divided

Bell-level. If the time window is less than 60s, the circuit breaker may enter the circuit breaker again after ending the circuit breaker.

Q: The exception page returned by the flow control rule is the same as the exception page returned by the degrade rule. How can we distinguish the cause?

Hot rules

Hot parameter flow control rule is a more fine-grained flow control rule that allows rules to be specific to parameters.

Hotspot rules are simple to use

Step 1: Write code

@RequestMapping("/order/message3") 

@SentinelResource("message3")// Note that this annotation must be used to indicate that the hotspot rule is not in effect

public String message3(String name, Integer age) { 

return name + age; 

}
Copy the code

Step 2: Configure hotspot rules

Step 3: Access the two parameters separately, and you will find that only the first parameter is limited

Enhanced use of hotspot rules

Parameter exceptions allow flow control of the specific value of a parameter

Edit the rule you just defined to add parameter exceptions

Authorization rules

In many cases, we need to determine whether a request is allowed to pass based on the source of the call. In this case, Sentinel can use source access control. Source access control Restricts access to resources based on their origin:

  • If a whitelist is configured, the request can pass only when the request source is in the whitelist.

  • If a blacklist is configured, the request source in the blacklist does not pass, and the rest of the requests pass.

The above resource names and authorization types are not difficult to understand, but how to fill in the flow control application?

Sentinel provides the RequestOriginParser interface to handle the source.

Whenever an interface resource protected by Sentinel is accessed, Sentinel calls the Implementation class of RequestOriginParser to resolve the source of the access.

Step 1: Customize the source handling rules

@Component public class RequestOriginParserDefinition implements RequestOriginParser{ @Override public String parseOrigin(HttpServletRequest request) { String serviceName = request.getParameter("serviceName"); return serviceName; }}Copy the code

Step 2: Configure authorization rules

This configuration means that only serviceName= PC cannot access (blacklist)

Step 3: Accesshttp://localhost:8091/order/message1?serviceName=pc observations

Rules of the system

System protection rules control the incoming flow at the application level, and monitor application data from the total Load, RT, incoming QPS, CPU usage and threads of a single machine, so that the system can run at the maximum throughput and ensure the overall stability of the system. System protection rules are application-wide, not resource-wide, and only apply to incoming traffic (traffic entering the application).

  • Load (only for Linux or UNIX-like machines) : When load1 exceeds the threshold and the number of concurrent threads exceeds the system capacity, system protection is triggered. The system capacity is calculated by the system maxQps * minRt. The reference values are typically CPU cores * 2.5.

  • RT: System protection is triggered when the average RT of all incoming traffic on a single machine reaches a threshold, in milliseconds.

  • Number of threads: System protection is triggered when the number of concurrent threads for all incoming traffic on a single machine reaches a threshold.

  • Inlet QPS: System protection is triggered when the QPS of all inlet flows on a single machine reaches the threshold.

  • CPU usage: When the CPU usage of all incoming traffic on a single machine reaches the threshold, system protection is triggered

Extension: Custom exception return

// Exception handling page

@Component 

public class ExceptionHandlerPage implements UrlBlockHandler { 

//BlockException exception interface, which contains five exceptions of Sentinel

@SentinelResourceDefines resources and provides optional exception handling and Fallback configuration items. Its main parameters are as follows:// FlowException Flow limiting exception

// DegradeException Degraded exception

// ParamFlowException Parameter flow limiting is abnormal

// AuthorityException AuthorityException

// SystemBlockException System load exception

@Override 

public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException { 

response.setContentType("application/json; charset=utf-8"); 

ResponseData data = null; 

if (e instanceof FlowException) { 

data = new ResponseData(-1."The interface is restricted..."); 

} else if (e instanceof DegradeException) { 

data = new ResponseData(-2."The interface has been degraded..."); } response.getWriter().write(JSON.toJSONString(data)); }}@Data 

@AllArgsConstructor// full parameter construction

@NoArgsConstructor// No arguments

class ResponseData { 

private int code; 

private String message; 

}
Copy the code

The use of the @ SentinelResource

After defining resource points, we can use Dashboard to set traffic limiting and degrade policies to protect resource points. You can also specify the handling strategy when an exception occurs via @SentinelResource.

@SentinelResource is used to define resources and provides optional exception handling and Fallback configuration items. Its main parameters are as follows:

attribute role
value The name of the resource
entryType The value is IN/OUT. The default value is OUT
blockHandler Specifies the name of the function to handle BlockException. The function requirements are as follows: 1. The return type parameter must be the same as the original method. 3. By default, the returned type parameter must be in the same class as the original method. If you want to use functions of other classes, you can configure blockHandlerClass and specify the methods in the blockHandlerClass.
blockHandlerClass The class that holds blockHandler must be static.
fallback Provides fallback handling logic when an exception is thrown. The fallback function handles all types of exceptions except those excluded from exceptionsToIgnore. Function requirements: 1. The return type must be the same as the original method. 2. The default must be in the same class as the original method. If you want to use functions of other classes, you can configure fallbackClass and specify methods in fallbackClass.
fallbackClass Classes to store fallback. The corresponding handler must be static.
defaultFallback Fallback logic for general purpose. The default fallback function handles all types of exceptions. If both Fallback and defaultFallback are configured, fallback prevails. The return type of the method must be the same as that of the original method. 2. The parameter list of the method must be empty or have a Throwable parameter. 3. The default method must be in the same class as the original method. If you want to use functions of other classes, you can configure fallbackClass and specify methods in fallbackClass.
exceptionsToIgnore Specifies which exceptions to exclude. Exceptions that are excluded will not be counted in the exception statistics and will not enter fallback logic, but will be thrown as is
exceptionsToTrace Exceptions that need to be traced
Define how to handle traffic limiting and degradation

Method 1: Directly define the limiting and degrading methods in the method

@Service 

@Slf4j 

public class OrderServiceImpl3 { 

int i = 0; 

@SentinelResource( value = "message", BlockHandler = "blockHandler",// specify the method to enter when BlockException occurs fallback = "fallback"// specify the method to enter when Throwable occurs)

public String message(a) { 

i++; 

if (i % 3= =0) { 

throw new RuntimeException(); 

}

return "message"; 

}

// The method of entry when BlockException occurs

public String blockHandler(BlockException ex) { 

log.error("{}", ex); 

return "The interface is restricted or degraded..."; 

}

//Throwable entry method

public String fallback(Throwable throwable) { 

log.error("{}", throwable); 

return "The interface is abnormal..."; }}Copy the code

Approach 2: Externalize the limiting and degrading methods into separate classes

@Service 

@Slf4j 

public class OrderServiceImpl3 { 

int i = 0; 

@SentinelResource( value = "message", blockHandlerClass = OrderServiceImpl3BlockHandlerClass.class, blockHandler = "blockHandler", fallbackClass = OrderServiceImpl3FallbackClass.class, fallback = "fallback" )

public String message(a) { 

i++; 

if (i % 3= =0) { 

throw new RuntimeException(); 

}

return "message4"; }}@Slf4j 

public class OrderServiceImpl3BlockHandlerClass { 

// Note that the static modifier must be used

public static String blockHandler(BlockException ex) {

1Write the handling class log.error("{}", ex); 

return "The interface is restricted or degraded..."; }}@Slf4j 

public class OrderServiceImpl3FallbackClass { 

// Note that the static modifier must be used

public static String fallback(Throwable throwable) { 

log.error("{}", throwable); 

return "The interface is abnormal..."; }}Copy the code

Sentinel rule persistence

As we’ve already seen, Dashboard can be used to set up various rules for each Sentinel client, but one problem is that these rules are stored in memory by default and are extremely unstable, so they need to be persisted.

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 Sentinel console first pushes the rules to the client via the API and updates them to memory. The registered write data source then saves the new rules to a local file.

1 Write processing classes

package com.itheima.config; 

// Rule persistence

public class FilePersistence implements InitFunc { 

@Value("spring.application:name") 

private String appcationName; 

@Override 

public void init(a) throws Exception { 

String ruleDir = System.getProperty("user.home") + "/sentinel- rules/"+appcationName; 

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 paramFlowRulePath = ruleDir + "/param-flow-rule.json"; 

this.mkdirIfNotExits(ruleDir); 

this.createFileIfNotExits(flowRulePath); 

this.createFileIfNotExits(degradeRulePath); 

this.createFileIfNotExits(systemRulePath); 

this.createFileIfNotExits(authorityRulePath); 

this.createFileIfNotExits(paramFlowRulePath); 

// Flow control rule

ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new 

FileRefreshableDataSource<>( 

flowRulePath, 

flowRuleListParser 

);

FlowRuleManager.register2Property(flowRuleRDS.getProperty()); 

WritableDataSource<List<FlowRule>> flowRuleWDS = new 

FileWritableDataSource<>( 

flowRulePath, 

this::encodeJson 

);

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<>( 

authorityRulePath, 

authorityRuleListParser 

);

AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty()); 

WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new 

FileWritableDataSource<>( 

authorityRulePath, 

this::encodeJson 

); 

WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS); 

// Hotspot parameter rules

ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new 

FileRefreshableDataSource<>( 

paramFlowRulePath, 

paramFlowRuleListParser 

);

ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty()); 

WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new 

FileWritableDataSource<>( 

paramFlowRulePath, 

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>> paramFlowRuleListParser = 

source -> JSON.parseObject( 

source, 

new TypeReference<List<ParamFlowRule>>() { 

} 

);

private void mkdirIfNotExits(String filePath) throws IOException { 

File file = new File(filePath); 

if (!file.exists()) { 

file.mkdirs(); 

} 

}

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); 

}
Copy the code

2 Adding a Configuration

Under the resources to create the configuration directory meta-inf/services, then add files com. Alibaba. CSP. The sentinel. Init. InitFunc

Add the full path of the configuration class to the file

com.itheima.config.FilePersistence
Copy the code

Feign integration Sentinel

Step 1: Introduce sentinel dependencies

<! -- Sentinel client --> 

<dependency> 

<groupId>com.alibaba.cloud</groupId> 

<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> 

</dependency> 
Copy the code

Step 2: Enable Feign support for Sentinel in the configuration file

feign: 

sentinel: 

enabled: true 
Copy the code

Step 3: Create fault-tolerant classes

Fault tolerant classes require that the interface to be fault-tolerant be implemented and that a fault tolerant scheme be implemented for each method

@Component 

@Slf4j 

public class ProductServiceFallBack implements ProductService { 

@Override 

public Product findByPid(Integer pid) { 

Product product = new Product(); 

product.setPid(-1); 

returnproduct; }}Copy the code

Step 4: Specify fault-tolerant classes for the container’s interfaces

//value specifies which microservice under NACOS is invoked

//fallback is used to specify fault-tolerant classes

@FeignClient(value = "service-product", fallback = ProductServiceFallBack.class) 

public interface ProductService { 

@RequestMapping("/product/{pid}")// Specify the URI part of the request

Product findByPid(@PathVariable Integer pid); 

} 
Copy the code

Step 5: Modify the Controller

@RestController 

@Slf4j 

public class OrderController { 

@Autowired 

private OrderService orderService; 

@Autowired 

private ProductService productService; 

/ / order -- fegin @ RequestMapping ("/order/prod / {pid} ")

public Order order(@PathVariable("pid") Integer pid) { 

log.info("Received the order request for item {}, then call the product microservice to query the information of this item", pid); 

// Call product microservice to query product information

Product product = productService.findByPid(pid); 

if (product.getPid() == -1) { 

Order order = new Order(); 

order.setPname("Order failed"); 

return order; 

}

log.info("The information of item {} was found :{}", pid, JSON.toJSONString(product)); 

// Place an order

Order order = new Order(); 

order.setUid(1); 

order.setUsername("Test user"); 

order.setPid(pid); 

order.setPname(product.getPname()); 

order.setPprice(product.getPprice()); 

order.setNumber(1); 

orderService.createOrder(order); 

log.info("Order created successfully with order information {}", JSON.toJSONString(order)); 

try {

Thread.sleep(100); 

} catch (InterruptedException e) { 

e.printStackTrace(); 

}

returnorder; }}Copy the code

Step 6: Stop allshop-productService, restartshop-orderServices, access requests, and observe fault tolerance

Extension: If you want to get specific errors in a fault tolerant class, you can use the following method

@FeignClient( value = "service-product", //fallback = ProductServiceFallBack.class, fallbackFactory = ProductServiceFallBackFactory.class) 

public interface ProductService { 

// @feignClient value + @requestMapping value is the completed request address

"http://service-product/product/" + pid 

@RequestMapping("/product/{pid}")// Specify the URI part of the request

Product findByPid(@PathVariable Integer pid); 

}

@Component 

public class ProductServiceFallBackFactory implements 

FallbackFactory<ProductService> { 

@Override 

public ProductService create(Throwable throwable) { 

return new ProductService() { 

@Override 

public Product findByPid(Integer pid) { 

throwable.printStackTrace(); 

Product product = new Product(); 

product.setPid(-1); 

returnproduct; }}; }}Copy the code

Note: Only one of these methods can be used for fallback and fallbackFactory