In the previous article, we introduced sentinel, including installing sentinel console, initializing demonstrator and process flow control rules
Next, learn the fusing rules, hotspot key current limiting, system rules, @ SentinelResource annotation, service fusing function and rule persistence.
Fusing rules
Official introduction
- Basic introduction
Fusing strategy
Sentinel provides the following fusing strategies:
- Slow_request_ratio: select the slow call ratio as the threshold, and set the allowed slow call RT (i.e. the maximum response time). If the response time of the request is greater than this value, it will be counted as slow call. When the number of requests in the unit statistical duration (statIntervalMs) is greater than the set minimum number of requests, and the proportion of slow calls is greater than the threshold, the next fusing duration requests will be automatically fused. After fusing for a long time, the fuse will enter the detection recovery state (HALF-OPEN state). If the response time of the next request is less than the set slow call RT, the fusing will be ended. If it is greater than the set slow call RT, it will be blown again.
- Error_ratio: when the number of requests in the unit statistical duration (statIntervalMs) is greater than the set minimum number of requests, and the proportion of exceptions is greater than the threshold, the requests in the next fusing duration will be blown automatically. After fusing for a long time, the fuse will enter the detection recovery state (HALF-OPEN state). If the next request is successfully completed (no error), the fusing will be ended, otherwise it will be blown again. The threshold range of abnormal ratio is [0.0, 1.0], representing 0% - 100%.
- Error_count: when the number of exceptions in the unit statistical time exceeds the threshold, it will automatically fuse. After fusing for a long time, the fuse will enter the detection recovery state (HALF-OPEN state). If the next request is successfully completed (no error), the fusing will be ended, otherwise it will be blown again.
Note that exception degradation is only for business exceptions, and does not take effect for the exception (BlockException) of Sentinel current limiting degradation itself. - RT (average response time in seconds)
The average response time exceeds the threshold and the request passed within the time window is > = 5. The degradation is triggered after the two conditions are met at the same time
Close the circuit breaker after the window period
RT maximum 4900 (larger ones can only take effect through - DCSP. Sentinel. Statistical. Max.rt = XXXX)
The DegradeRule contains the following important attributes:
Field | explain | Default value |
---|---|---|
resource | Resource name, that is, the object of the rule | |
grade | Fusing strategy, supporting slow call proportion / exception proportion / different constant strategy | Slow call ratio |
count | In slow call proportional mode, it is slow call critical RT (exceeding this value is counted as slow call); It is the corresponding threshold in the exception proportion / exception number mode | |
timeWindow | Fusing duration, unit: s | |
minRequestAmount | The minimum number of requests triggered by fusing. When the number of requests is less than this value, it will not fuse even if the abnormal ratio exceeds the threshold (introduced by 1.7.0) | 5 |
statIntervalMs | Statistical duration (unit: ms), for example, 60 * 1000 represents minute level (introduced in 1.8.0) | 1000 ms |
slowRatioThreshold | Slow call proportional threshold. Only slow call proportional mode is valid (introduced in 1.8.0) |
Sentinel's circuit breaker is not half open
In the half open state, the system automatically detects whether the request is abnormal,
If there is no abnormality, close the circuit breaker and resume use,
If there is any abnormality, continue to open the circuit breaker and it is unavailable. Refer to Hystrix for details
(1) Slow call ratio
Select the slow call proportion as the threshold. You need to set the allowed slow call RT (i.e. the maximum response time). If the response time of the request is greater than this value, it will be counted as slow call. When the number of requests in the unit statistical duration (statIntervalMs) is greater than the set minimum number of requests, and the proportion of slow calls is greater than the threshold, the next fusing duration requests will be automatically fused. After fusing for a long time, the fuse will enter the detection recovery state (HALF-OPEN state). If the response time of the next request is less than the set slow call RT, the fusing will be ended. If it is greater than the set slow call RT, it will be blown again.
- Add a test interface and sleep for 2 seconds when calling the interface, so that the response time of this interface is more than 1 second
@GetMapping("/testD") public String testD() { //Pause the thread for a few seconds try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } log.info("testD Test call ratio"); return "------testD"; }
- Add test interface rule to console
- Maximum RT: slow call critical RT, exceeding this value is counted as slow call. Unit: ms
- Proportional threshold: the threshold of slow request ratio in RT mode. Default 1.0d
- Fusing duration: recovery timeout (in seconds) when the circuit breaker is open. After the timeout, the circuit breaker will switch to the half open state to try some requests. The unit is second. The figure shows that after triggering the fusing, the request will be blown automatically in the next 10 seconds. After 10S, the fuse will enter the detection recovery state (HALF-OPEN state). If the response time of the next request is less than the set slow call RT, the fusing will be ended. If it is greater than the set slow call RT, it will be blown again.
- Minimum number of requests: the minimum number of requests that can trigger fuse interruption (within the effective statistical time range). The default value is 5
- StatIntervalMs: statistical duration (unit: ms). For example, 601000 represents minute level (introduced in 1.8.0). It defaults to 1000. There is no option on the console and needs to be implemented in code.
Test with jemeter
Use the pressure test tool to access the test interface and view the current limiting effect diagram. The specific current limiting process is roughly as follows:
(1) When the request enters the background, sentinel will count the total number of requests in the time period according to the set statistical duration (1S by default)
(2) First, judge whether the total number of requests counted is less than the minimum number of requests set by the user (5 by default). If it is less than, it will not be fused. Otherwise, go to the next step
(3) Then, according to the maximum RT set by the user, judge whether the request in the statistics is a slow call. If it is greater than the set value, it is a slow call request
(4) Calculate the proportion of slow call requests / total statistical requests again, and whether it exceeds the set proportion threshold.
(5) When the number of requests in the statistical time and the slow call proportion threshold exceed the set threshold, the requests in the next fusing time will be automatically fused
(6) After the fusing duration ends, the fuse will enter the detection recovery state (HALF-OPEN state). If the response time of the next request is less than the set slow call RT, the fusing will end. If it is greater than the set slow call RT, it will be blown again.
--------
Copyright notice: This is the original article of CSDN blogger "cloud smoke into rain CSDN", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this notice for reprint.
Original link: https://blog.csdn.net/qq_43437874/article/details/111475762
Conclusion:
Always call in 10 threads (more than 5) to call testD in one second. We hope to complete this task in 200 milliseconds,
If the process is not completed for more than 200 milliseconds, the circuit breaker opens (fuse trips), the microservice is unavailable and the fuse trips and de energizes within the next 1 second time window
Subsequently, I stopped jmeter and there was no such a large number of visits. The circuit breaker was closed (the fuse was restored) and the microservice was restored to OK
(2) Abnormal proportion
Error_ratio: when the number of requests in the unit statistical duration (statIntervalMs) is greater than the set minimum number of requests, and the proportion of exceptions is greater than the threshold, the requests in the next fusing duration will be blown automatically. After fusing for a long time, the fuse will enter the detection recovery state (HALF-OPEN state). If the next request is successfully completed (no error), the fusing will be ended, otherwise it will be blown again. The threshold range of abnormal ratio is [0.0, 1.0], representing 0% - 100%.
- Add the following methods in the controller
@GetMapping("/testE") public String testE() { log.info("testE Test exception ratio"); int age = 10/0; return "------testE"; }
- Add test interface rule to console
visit http://127.0.0.1:8401/testE
If an error is reported directly, refresh it directly.
Because many calls have reached our configured fuse degradation conditions, the circuit breaker is opened (fuse trips), the microservice is unavailable, no error is reported, but the service is degraded.
(3) Different constant
Error_count: when the number of exceptions in the unit statistical time exceeds the threshold, it will automatically fuse. After fusing for a long time, the fuse will enter the detection recovery state (HALF-OPEN state). If the next request is successfully completed (no error), the fusing will be ended, otherwise it will be blown again.
test
Or the testE path just now
- Console modification test interface fusing rules
visit http://127.0.0.1:8401/testE
Within 5s, visit 5 times first. When you visit the fifth time, visit once, that is, the sixth time.
Because the statistical duration we configured is 5s, when the number of exceptions in 5s reaches 5, the sixth fuse degradation will be carried out, and the degradation lasts for 2s.
Hot spot current limiting
What are hot spots?
Hot spots are frequently accessed data. Many times, we want to count or limit the TopN data with the highest access frequency in a hot spot data, and limit its access or other operations
Official description
- Add the following methods in the controller
@GetMapping("/testHotKey") @SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey") public String testHotKey(@RequestParam(value = "p1",required = false) String p1, @RequestParam(value = "p2",required = false) String p2){ return "------testHotKey"; } public String dealHandler_testHotKey(String p1,String p2,BlockException exception) { return "-----dealHandler_testHotKey"; }
Sentinel system default prompt: Blocked by Sentinel (flow limiting)
- Configuration description
Normal access http://127.0.0.1:8401/testHotKey
visit http://127.0.0.1:8401/testHotKey?p1=1 , and constantly refresh
visit http://127.0.0.1:8401/testHotKey?p2=1 , and constantly refresh
visit http://127.0.0.1:8401/testHotKey?p2=1&p1=1 , and constantly refresh
Conclusion: as long as the parameter p1 is used and the QPS exceeds 1 time per second, it will be degraded.
@SentinelResource(value = "testHotKey")//The exception hit the foreground user interface and was not friendly
//The first parameter in the testHotKey method will be degraded as soon as the QPS exceeds 1 time per second @SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")//With our own definition
The above case demonstrates that the first parameter p1 is current limited immediately after one click of QPS for more than 1 second, but we expect that when p1 parameter is a special value, its current limit value is different from that in normal times. For example, if the value of p1 is equal to 5, its threshold can reach 200
- Modify configuration
Configuration Description: when p1 is equal to 5, the threshold becomes 200. When p1 is not equal to 5, the threshold is the usual 1.
Note: the hotspot parameter must be a basic type or String
other:
@SentinelResource
It deals with violations of Sentinel console configuration, including the details of blockHandler method configuration;
RuntimeException
int age = 10/0, this is the runtime exception RunTimeException reported by java runtime, regardless of @ SentinelResource
summary
@SentinelResource supervisor has an error in configuration and operation. This is an exception
System rules
The system protection rule is to control the entrance flow at the application level, and monitor the application indicators from the dimensions of load, CPU utilization, average RT, entrance QPS and the number of concurrent threads of a single machine, so as to make the system run at the maximum throughput and ensure the overall stability of the system.
System protection rules apply the overall dimension, not the resource dimension, and are only effective for inlet traffic. For example, entrytype refers to the incoming traffic of the application (e.g. the incoming traffic of the application) or the incoming traffic of the application.
System rules support the following modes:
- Load adaptation (only valid for Linux / Unix like machines): load1 of the system is used as the heuristic index for adaptive system protection. When system load1 exceeds the set heuristic value and the current number of concurrent threads exceeds the estimated system capacity, system protection will be triggered (BBR stage). The system capacity is estimated from the maxQps * minRt of the system. The setting reference value is generally CPU cores * 2.5.
- CPU usage (version 1.5.0 +): when the system CPU utilization exceeds the threshold, the system protection is triggered (value range 0.0-1.0), which is sensitive.
- Average RT: when the average RT of all inlet flows on a single machine reaches the threshold, the system protection is triggered, and the unit is milliseconds.
- Number of concurrent threads: system protection is triggered when the number of concurrent threads of all inlet traffic on a single machine reaches the threshold.
- Inlet QPS: when the QPS of all inlet flows on a single machine reaches the threshold, the system protection is triggered.
Official documents
@Use of SentinelResource
1. Current limiting and subsequent processing by resource name
- Add a new RateLimitController
@RestController public class RateLimitController { @GetMapping("/byResource") @SentinelResource(value = "byResource",blockHandler = "handleException") public CommonResult byResource() { return new CommonResult(200,"Current limit test by resource name OK",new Payment(2020L,"serial001")); } public CommonResult handleException(BlockException exception) { return new CommonResult(444,exception.getClass().getCanonicalName()+"\t Service Unavailable"); } }
- Start nacos, start sentinel, and go to sentinel console to add flow control rules
Configuration Description:
It means that if the number of queries is greater than 1 in 1 second, it will run to our custom flow, and the current is limited
Click once a second, and no degradation can occur.
Beyond the above, click crazy and return the self-defined current limit processing information. The current limit occurs
2. Current limiting and subsequent processing according to Url address
Add the following methods to the newly created class RateLimitController
@GetMapping("/rateLimit/byUrl") @SentinelResource(value = "byUrl") public CommonResult byUrl() { return new CommonResult(200,"Press url Current limiting test OK",new Payment(2020L,"serial002")); }
Sentinel console configuration, add the following configuration
visit http://localhost:8401/rateLimit/byUrl
Very slow access
Crazy Click http://localhost:8401/rateLimit/byUrl
Current limiting was successfully carried out
3. Customer defined current limiting processing logic
Problems with the above code:
- By default, the system does not reflect our own business requirements.
- According to the existing conditions, our customized processing method is coupled with the business code, which is not intuitive.
- Each business method adds a bottom-up, which aggravates the code inflation.
- The globally unified processing method is not reflected.
Create a CustomerBlockHandler class to customize the flow limiting processing logic
public class CustomerBlockHandler { public static CommonResult handleException(BlockException exception){ return new CommonResult(2020,"Customized current limiting processing information......CustomerBlockHandler"); } }
Add a new method in RateLimitController
/** * Custom general current limiting processing logic blockHandlerClass = CustomerBlockHandler.class blockHandler = handleException The above configuration: find the handleException method in the CustomerBlockHandler class to handle it */ @GetMapping("/rateLimit/customerBlockHandler") @SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException") public CommonResult customerBlockHandler() { return new CommonResult(200,"Custom current limiting processing logic by customer"); }
Configuration further description
Access the microservice once after starting it http://localhost:8401/rateLimit/customerBlockHandler
Sentinel console configuration
Crazy access after starting the microservice http://localhost:8401/rateLimit/customerBlockHandler
More annotation attribute descriptions
The two main uses of @ SentinelResource annotation: current limiting control and fuse degradation are introduced. In addition, there are other more refined configurations in this annotation, such as ignoring some abnormal configurations, default degradation functions, etc. see the following description for details:
- value: resource name, required (cannot be empty)
- entryType: entry type, optional (EntryType.OUT by default)
- blockHandler / blockHandlerClass:blockHandler corresponds to the name of the function handling BlockException. Optional. The access scope of the blockHandler function needs to be public, the return type needs to match the original method, the parameter type needs to match the original method, and finally add an additional parameter with the type of BlockException. The blockHandler function needs to be in the same Class as the original method by default. If you want to use functions of other classes, you can specify blockHandlerClass as the Class object of the corresponding Class. Note that the corresponding function must be a static function, otherwise it cannot be parsed.
- Fallback: name of the fallback function, optional, used to provide fallback processing logic when throwing exceptions. The fallback function can handle all types of exceptions (except those excluded in exceptionsToIgnore). Fallback function signature and location requirements:
- The return value type must be consistent with the return value type of the original function;
- The method parameter list needs to be consistent with the original function, or an additional Throwable parameter can be used to receive the corresponding exception.
- The fallback function needs to be in the same Class as the original method by default. If you want to use functions of other classes, you can specify fallbackClass as the Class object of the corresponding Class. Note that the corresponding function must be a static function, otherwise it cannot be parsed.
- defaultFallback (since 1.6.0): the default fallback function name, which is optional. It is usually used for general fallback logic (that is, it can be used for many services or methods). The default fallback function can handle all types of exceptions (except those excluded in exceptionsToIgnore). If both fallback and defaultFallback are configured, only fallback will take effect. defaultFallback function signature requirements:
- The return value type must be consistent with the return value type of the original function;
- The method parameter list needs to be empty, or an additional Throwable parameter can be used to receive the corresponding exception.
- The defaultFallback function needs to be in the same Class as the original method by default. If you want to use functions of other classes, you can specify fallbackClass as the Class object of the corresponding Class. Note that the corresponding function must be a static function, otherwise it cannot be parsed.
- It is used to specify which exceptions will not be thrown in exception.0, but will not be included in exception.0
Note: the fallback function before 1.6.0 only handles DegradeException, not business exception.
In particular, if both blockHandler and fallback are configured, only blockHandler processing logic will be entered when BlockException is thrown due to current limiting degradation. If blockHandler, fallback and defaultFallback are not configured, BlockException will be thrown directly when current limiting is degraded
Service fuse function
- sentinel integration ribbon+openFeign+fallback
- Start nacos and sentinel
Create service provider cloudalibaba provider payment9003 / 9004
-
Create a new cloudalibaba provider payment9003
-
Modify the pom file and add the following dependencies
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency><!-- Introduce self defined api General package, you can use Payment payment Entity --> <groupId>com.zhubayi.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot integration Web assembly --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--Daily general jar Package configuration--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
- Add application YML profile
server: port: 9003 spring: application: name: nacos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 #Configure Nacos address management: endpoints: web: exposure: include: '*'
- Main startup class
@SpringBootApplication @EnableDiscoveryClient public class PaymentMain9003 { public static void main(String[] args) { SpringApplication.run(PaymentMain9003.class, args); } }
- controller
package com.zhubayi.springcloud.alibaba.controller; import com.zhubayi.springcloud.entities.CommonResult; import com.zhubayi.springcloud.entities.Payment; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; @RestController public class PaymentController { @Value("${server.port}") private String serverPort; public static HashMap<Long,Payment> hashMap = new HashMap<>(); static { hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181")); hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182")); hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183")); } @GetMapping(value = "/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) { Payment payment = hashMap.get(id); CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort: "+serverPort,payment); return result; } }
- 9004 module, too. Remember to change the port number and startup class
Start 9003 and 9004 and nacos
test http://127.0.0.1:9003/paymentSQL/1
test http://127.0.0.1:9004/paymentSQL/1
Create a new cloudalibaba consumer Nacos order84 service consumer module
- Modify the pom file and add the following dependencies
<dependencies> <!--SpringCloud openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.0.RELEASE</version> </dependency> <!--SpringCloud ailibaba sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.0.RELEASE</version> </dependency> <!-- Introduce self defined api General package, you can use Payment payment Entity --> <dependency> <groupId>com.zhubayi.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot integration Web assembly --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--Daily general jar Package configuration--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
- Create a new application YML profile
server: port: 8400 spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: #Configure Sentinel dashboard address dashboard: localhost:8080 #The default port is 8719. If it is occupied, it will automatically start + 1 scanning from 8719 until an unoccupied port is found port: 8719 #The name of the microservice that the consumer will access (the microservice provider successfully registered in nacos) service-url: nacos-user-service: http://nacos-payment-provider
- Start class OrderNacosMain84
@EnableDiscoveryClient @SpringBootApplication public class OrderNacosMain84 { public static void main(String[] args) { SpringApplication.run(OrderNacosMain84.class, args); } }
Ribbon collection
- Create a new configuration class ApplicationContextConfig and inject beans into the container
@Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
- controller
package com.zhubayi.springcloud.alibaba.controller; import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.zhubayi.springcloud.entities.CommonResult; import com.zhubayi.springcloud.entities.Payment; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; import java.sql.SQLException; import java.util.concurrent.Executors; @RestController @Slf4j public class CircleBreakerController { public static final String SERVICE_URL = "http://nacos-payment-provider"; @Resource private RestTemplate restTemplate; @RequestMapping("/consumer/fallback/{id}") @SentinelResource(value = "fallback") public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,Illegal parameter exception...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,Should ID No corresponding record,Null pointer exception"); } return result; } }
Start port 84, test http://192.168.0.159:8400/consumer/fallback/1
It's refreshing
No configuration
When visiting http://192.168.0.159:8400/consumer/fallback/4
Give the customer the error page, unfriendly
Configure fallback only
Modify the controller and add a method to cover the bottom
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) { Payment payment = new Payment(id,"null"); return new CommonResult<>(444,"Fundus abnormality handlerFallback,exception content "+e.getMessage(),payment); }
Complete CircleBreakerController class
@RestController @Slf4j public class CircleBreakerController { public static final String SERVICE_URL = "http://nacos-payment-provider"; @Resource private RestTemplate restTemplate; @RequestMapping("/consumer/fallback/{id}") @SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback is responsible for business exceptions public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,Illegal parameter exception...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,Should ID No corresponding record,Null pointer exception"); } return result; } public CommonResult handlerFallback(@PathVariable Long id,Throwable e) { Payment payment = new Payment(id,"null"); return new CommonResult<>(444,"Fundus abnormality handlerFallback,exception content "+e.getMessage(),payment); } }
test
Successfully implemented the bottom method
Configure blockHandler only
Modify controller code
@RestController @Slf4j public class CircleBreakerController { public static final String SERVICE_URL = "http://nacos-payment-provider"; @Resource private RestTemplate restTemplate; @RequestMapping("/consumer/fallback/{id}") //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback is only responsible for the business exception handlerFallback method @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler is responsible for the degraded current limit configured in sentinel public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("Illegal parameter exception...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,Should ID No corresponding record"); } return result; } public CommonResult handlerFallback(@PathVariable Long id,Throwable e) { Payment payment = new Payment(id,"null"); return new CommonResult<>(444,"fallback,No such flow,exception "+e.getMessage(),payment); } public CommonResult blockHandler(@PathVariable Long id,BlockException blockException) { Payment payment = new Payment(id,"null"); return new CommonResult<>(445,"blockHandler-sentinel Current limiting,No such flow: blockException "+blockException.getMessage(),payment); } }
Add flow control rule
Crazy visit http://192.168.0.159:8400/consumer/fallback/1
Both fallback and blockHandler are configured
- Modify @ SentinelResource annotation
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler")
If both blockHandler and fallback are configured, only blockHandler processing logic will be entered when BlockException is thrown due to current limiting degradation. Fallback is only responsible for the business exception handler fallback method, and blockHandler is responsible for the degraded current limit configured in sentinel
Ignore properties
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler", exceptionsToIgnore = {IllegalArgumentException.class}) //exceptionsToIgnore ignores this exception, that is, this exception is not handled
Feign series
- Remember to add openfeign dependency to pom file
<!--SpringCloud openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- Modify the configuration file to activate Sentinel's support for Feign
# Activate Sentinel support for Feign feign: sentinel: enabled: true
- Business class IPaymentService
/** * You cannot get exception information by using fallback, * If you want to get exception information, you can use the fallbackFactory parameter */ @FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//Close 9003 service provider in call public interface IPaymentService { @GetMapping(value = "/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id); }
PaymentFallbackService
@Component public class PaymentFallbackService implements IPaymentService{ /** * Remote call * * @param id * @return */ @Override public CommonResult<Payment> paymentSQL(Long id) { return new CommonResult<>(444,"Service degradation return",new Payment(id,"error")); } }
controller
//==================OpenFeign //terms of settlement https://blog.csdn.net/kongliand/article/details/108058831 @Resource private IPaymentService ipaymentService; @GetMapping(value = "/consumer/openfeign/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) { if(id == 4) { throw new RuntimeException("No this id"); } return ipaymentService.paymentSQL(id); }
- Add the EnableFeignClients annotation on the main startup class to start the remote call
Test: turn off 9003 and 9004, and then visit http://192.168.0.159:8400/consumer/openfeign/1
Downgrade succeeded.
Rule persistence
- Once we restart the application, sentinel rules will disappear, and the production environment needs to persist the configuration rules
- Persist the flow restriction configuration rules into Nacos and save them. Just refresh 8401 a rest address and the sentinel console
You can see that as long as the configuration in Nacos is not deleted, the flow control rules on sentinel on 8401 remain valid - Modify cloudalibaba-sentinel-service8401
- Add dependency
<!--SpringCloud ailibaba sentinel-datasource-nacos --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
- Modify profile
spring: cloud: sentinel: datasource: ds1: nacos: server-addr: localhost:8848 dataId: ${spring.application.name} groupId: DEFAULT_GROUP data-type: json rule-type: flow
Full profile
server: port: 8401 spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: server-addr: localhost:8848 #Nacos service registry address sentinel: transport: dashboard: localhost:8080 #Configure Sentinel dashboard address port: 8719 #sentinel persistence datasource: ds1: nacos: server-addr: localhost:8848 dataId: cloudalibaba-sentinel-service groupId: DEFAULT_GROUP data-type: json rule-type: flow management: endpoints: web: exposure: include: '*' feign: sentinel: enabled: true # Activate Sentinel support for Feign
- Add Nacos business rule configuration
Origin of configuration dataId, configuration group and configuration format
Configuration Description:
Resource: resource name;
limitApp: source application;
grade: threshold type, 0 indicates the number of threads, 1 indicates QPS;
count: single machine threshold;
strategy: flow control mode, 0 indicates direct, 1 indicates association, and 2 indicates link;
controlBehavior: flow control effect, 0 indicates rapid failure, 1 indicates Warm Up, and 2 indicates queuing;
clusterMode: whether to cluster.
After starting 8401, refresh sentinel and find that the business rules have changed
test
Quick access test interface http://192.168.0.159:8401/rateLimit/byUrl
Stop 8401 and look at sentinel
It is found that there are no flow control rules. Restart 8401 and see sentinel again
At the beginning, I still didn't see it. I went to visit it http://192.168.0.159:8401/rateLimit/byUrl perhaps http://127.0.0.1:8401/rateLimit/byUrl , the reconfiguration occurred and the persistence validation passed