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/message2
Access, 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-product
Service, restartshop-order
Services, 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