sentinel integrates springcloud alibaba

Posted by mkubota on Sun, 02 Jan 2022 18:47:11 +0100

sentinel integrates springcloud alibaba

1. Introducing dependencies

<!--sentinel starter-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

2. Add yml configuration to set sentinel console address for microservices
After adding sentinel, you need to expose the / actuator / sentinel endpoint, which Springboot does not expose by default, so you need to set, test http://localhost:8800//actuator/sentinel

server:
  port: 8861
spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858

sentinel console flow control rules

1. Flow control rules
Flow control: The principle is to monitor the QPS or number of concurrent threads of the application traffic, and control the flow when the specified threshold is reached, so as to avoid being overwhelmed by the instantaneous traffic peak, thereby ensuring high availability of the application. === FlowRule RT (response time) 1/0.2s = 5


Multiple flow-limiting rules can be created for the same resource. FlowSlot iterates through all flow-limiting rules for the resource in turn until a rule triggers the flow-limiting or all rules are traversed. A flow restriction rule consists mainly of the following elements, which we can combine to achieve different flow restriction effects.

FieldExplainDefault value
resourceResource name, which is the object of the flow restriction rule
countCurrent Limiting Threshold
gradeThreshold type, QPS mode (1) or concurrent threading mode (0)QPS mode
limitAppCall Source for Flow Controldefault, which means call source is indistinguishable
strategyCall Relationship Limiting Policy: Direct, Link, AssociationAccording to the resource itself (directly)
controlBehaviorFlow control effect (direct rejection of WarmUp average + queued waiting) does not support flow limiting by call relationshipDirect Rejection
clusterModeIs Cluster Limitingno

Reference documents: https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

2. Limiting threshold type
QPS (Query Per Second): The number of requests per second is how many requests are processed by the persuader in one second.

QPS
Enter the cluster point link to select the specific access API, then click the flow control button.

Number of concurrent threads
Concurrency control is used to protect the business thread pool from being exhausted by slow calls. For example, when an application relies on a downstream application that for some reason causes service instability and response delays to increase, it means lower throughput and more thread consumption for callers, and in extreme cases, even exhaustion of the thread pool. To cope with too many threads, there are isolation schemes in the industry, such as using different thread pools for different business logic to isolate resource acquisition (thread pool isolation) between businesses themselves. This isolation scheme is better, but at the cost of too many threads and a larger overhead for thread context switching, especially for low-latency calls. Sentinel concurrency control is not responsible for creating and managing thread pools. Instead, it simply counts the number of threads in the current request context (the number of calls being executed). If the threshold is exceeded, new requests are rejected immediately, similar to semaphore isolation. Concurrency control is usually configured on the caller side.

3.sentinel console QPS flow control rules
1) Add QPS flow control rules

2) Code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/add")
    public String add(){
        log.info("Order successful!");
        return "Hello World !";
    }

    @RequestMapping("/flow")
    public String flow(){
        return "Normal access!!!";
    }

}

3) Test

4.sentinel console custom QPS flow control rules
1) Code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/flow")
    @SentinelResource(value = "flow", blockHandler = "flowBlockHandler")
    public String flow(){
        return "Normal access!!!";
    }

    public String flowBlockHandler(BlockException e){
        return "Custom Flow Control!!";
    }

}

2) Add Rules

3) Test

5.sentinel concurrent threads flow control rule
1) Code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    public String flowBlockHandler(BlockException e){
        return "Custom Flow Control!!";
    }

    @RequestMapping("/flowThread")
    @SentinelResource(value = "flowThread", blockHandler = "flowBlockHandler")
    public String flowThread() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        return "Normal access!!!";
    }

}

2) Add Rules

3) Test


6. BlockException Unified Exception Handling in sentinel
BlockException Exception Unified Handling
Springwebmvc Interface Resource Limiting Entry In the preHandle method of Handler Interceptor's implementation class AbstractSentinelInterceptor, exception handling is the implementation class of BlockExceptionHandler
sentinel 1.7.1 sentinel-spring-webmvc-adapter is introduced. Jar

1) Unified processing of BlockException by implementation classes of custom BlockExceptionHandler

@Component
@Slf4j
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        log.info("BlockExceptionHandler BlockException =======" + e.getRule());

        Result r = null;
        if(e instanceof FlowException){
            r = Result.error(100, "Interface Current Limited");
        }else if(e instanceof DegradeException){
            r = Result.error(101,"Service downgraded");
        }else if(e instanceof ParamFlowException){
            r = Result.error(102,"Hot spot parameter Limited");
        }else if(e instanceof SystemBlockException){
            r = Result.error(103,"Triggered system protection rules");
        }else if(e instanceof AuthorityException){
            r = Result.error(104,"Authorization Rule Not Passed");
        }

        //Return to json
        httpServletResponse.setStatus(500);
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(httpServletResponse.getWriter(),r);
    }
}

2) Result class

public class Result<T> {
    private Integer code;
    private String msg;
    private T data;

    public Result() {
    }

    public Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static Result error(Integer code, String msg){
        return new Result(code, msg);
    }

}

3) controller class

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/flow")
    public String flow(){
        return "Normal access!!!";
    }
}

4) Add Rules

5) Test

7. Flow control mode
Traffic control based on call relationships. Call relationships include caller and callee; One method may call another to form a hierarchical relationship of call links.

1) Direct
The resource call is directly thrown by the flow control after reaching the set threshold

2) Association
When there is a resource contention or dependency between two resources, they are related. For example, there is a contention between read and write operations on the same field in the database. If the speed of reading is too high, the speed of writing will be affected. If the speed of writing is too high, the speed of reading will be affected. If read and write operations are allowed to compete for resources, the overhead of the contention itself reduces overall throughput. You can use an associated limit to avoid excessive contention between resources with an associated relationship, for example, read_db and write_db These two resources represent the database read and write, so we can give read_db Sets flow-limiting rules to achieve write-first purposes: Set strategy to RuleConstant.STRATEGY_RELATE also sets refResource to write_db. This limits the flow of requests to read data when writing is too frequent.
(1) Add Rules

(2) controller code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/add")
    public String add(){
        log.info("Order successful!");
        return "Generate Order";
    }

    @RequestMapping("/get")
    public String get(){
        log.info("Query orders");
        return "Query orders";
    }  
}

(3) JMeter tools are needed here for reference: JMeter Download Installation
Send/order/add requests through the JMeter tool, and then send/order/get requests through the browser prompts for flow restriction.
JMeter tool sends/order/add requests:

Browser send/order/get request:

3) Link
Limit flow based on call link entry.
In NodeSelectorSlot, call links are recorded between resources that form a call tree through call relationships. The root node of this tree is a virtual node named machine-root, and the entry of the call chain is all the children of this virtual node.
A typical call tree is shown in the following figure:

Requests from entry/order/test1 and/order/test2 in the figure above both invoke the resource getUser, and Sentinel allows resource throttling based only on the statistics of an entry.

(1) Add Rules

The test will find that the link rule is not valid
Note: This function does not work directly in higher versions, how can I solve it?
From 1.6. Starting with version 3, Sentinel Web filter defaults to converge the entry context of all URL s, so link throttling does not take effect.
1.7. Beginning with version 0 (corresponding to SCA 2.1.1.RELEASE), the WEB CONTEXT UNIFY parameter was officially introduced in CommonFilter to control convergence context. Configuring it to false allows link throttling based on an inappropriate URL.
SCA 2.1. 1. After RELEASE, you can configure spring.cloud.sentinel.web-context-unify=false turns off convergence.

spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858
      web-context-unify: false  # Link convergence will be invoked by default

Test, this scenario cannot intercept BlockException, corresponding resources specified by @SentinelResource must specify blockHanler to handle BlockException in the @SentinelResource comment

(2) Controller code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @Autowired
    IOrderService orderService;

    /**
     * Associated Flow Control
     */
    @RequestMapping("/test1")
    public String test1(){
        return orderService.getUser();
    }

    /**
     * Associated Flow Control
     * @return
     */
    @RequestMapping("/test2")
    public String test2(){
        return orderService.getUser();
    }


}

(3) service class

public interface IOrderService {
    public String getUser();
}

(4) serviceImpl class

@Service
public class OrderServiceImpl implements IOrderService{

    @Override
    @SentinelResource(value = "getUser", blockHandler = "blockHandlerGetUser")
    public String getUser() {
        return "Query Users";
    }

    public String blockHandlerGetUser(BlockException e){
        return "Flow Control Users";
    }
}

(5) Testing

Flow control effect

Fast Failure
(RuleConstant.CONTROL_BEHAVIOR_DEFAULT) mode is the default mode of flow control. When QPS exceeds the threshold of any rule, a new request is rejected immediately and a FlowException is thrown. This method is useful when the processing capacity of the system is known, for example, when the exact water level of the system is determined by pressure measurement.

Warm Up
Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP) mode, that is, preheating/cold start mode. When the system is in low water level for a long time, when the flow rate suddenly increases, pulling the system up to high water level may instantly crush the system. By "cold start", let the flow through slowly increase, gradually increasing to the upper threshold within a certain period of time, giving the cooling system a preheating time to avoid the cold system being crushed.
Cold Load Factor: CodFactor defaults to 3, which means requesting QPS to start at threshold / 3 and gradually rise to the set QPS threshold after a long preheating period.
The QPS curve that normally permits a cold-start process system to pass is shown in the following figure:

Add Rules:

Test:

Uniform Queue
Uniform queuing (RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER) tightly controls the interval between requests, that is, lets requests pass at a uniform speed, corresponding to the leaky bucket algorithm.
This method works as follows:

This approach is primarily used to handle intermittent bursts of traffic, such as message queues. Imagine a scenario where a large number of requests arrive in one second and the next few seconds are idle, and we want the system to be able to process these requests gradually over the next idle period rather than rejecting them directly in the first second.
Note: Uniform queue mode does not support QPS > 1000 scenarios at this time.

1.JMeter Simulated Pulse Flow
Add Rules:





2. Queue for use
Add Rules:

JMeter, as set above, executes the result:

sentinel demotion rule

1. Fuse Downgrade Rules
In addition to flow control, downgrading the unstable resources in the call link by fusing is one of the important measures to ensure high availability. We need to melt down unstable weak dependency service calls, temporarily cut them off, and avoid an overall avalanche caused by local instability. Fuse demotion, as a means of protecting itself, is usually configured on the client side (the caller side).

Fuse demotion and isolation

Means of protecting oneself
1) Concurrency Control
2) Fuse based on slow call ratio
3) Fuse based on abnormal proportions

Configuration is usually combined on the consumer side

Example of processing logic after triggering a fuse
1) Provide fallback implementation (service downgrade)
2) Return error result
3) Read Cache (DB Access Degradation)

Explanation of Fuse Downgrade Rule
The DegradeRule contains the following important properties:

FieldExplainDefault value
resourceResource name, which is the role object of the rule
gradeFuse policy, supports slow call ratio/exception ratio/exception number policySlow Call Scale
countSlow call scaling mode is critical RT for slow call (exceeding this value counts as slow call); Threshold value in exception scale/number mode
timeWindowFuse duration in s
minRequestAmountMinimum number of requests triggered by a melt, which will not melt even if the exception ratio exceeds the threshold (1.7.0 introduced)5
statIntervalMsStatistical duration in ms, such as 60*1000 for minutes (introduced by 1.8.0)1000ms
slowRatioThresholdSlow call scale threshold, only slow call scale mode is valid (1.8.0 introduced)

2. Fuse strategy
1) Slow call ratio
Slow Call Ratio (SLOW_REQUEST_RATIO): Selecting the slow call ratio as the threshold requires setting the allowable slow call RT (i.e. the maximum response time), and requests that have a response time greater than this value are counted as slow calls. When the number of requests within the unit statistics duration (statIntervalMs) is greater than the minimum number of requests set, and the proportion of slow calls is greater than the threshold, subsequent requests for the melt duration are automatically melted. After a long time of fusing, the fuser will enter the detection recovery state (HALF-OPEN state), if the next request response time is less than the set slow call RT, the fuse will end, and if the set slow call RT is greater than the set slow call RT, it will be fused again.

2) Add demotion rules

3) JMeter Add Request


4) controller code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/flowThread")
    public String flowThread() throws InterruptedException {
        TimeUnit.SECONDS.sleep(2);
        System.out.println("Visit normally!");
        return "Normal access!!!";
    }
}

5) Test

3. Abnormal Scale
Exception ratio (ERROR_RATIO): When the number of requests within the unit statistics duration (statIntervalMs) is greater than the minimum number of requests set, and the proportion of exceptions is greater than the threshold, the requests will be automatically blown during the next blown-out period. After a long time of fusing, the fuse will enter the detection recovery state (HALT-OPEN state), and if the next request is completed successfully (without error), the fuse will end, otherwise it will be fused again. The threshold range for outlier ratios is [0.0,1.0], representing 0% - 100%.

1) Add Demotion Rule

2) JMeter Add Request


3) controller code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/err")
    public String err(){
        int a = 1/0;
        return "error";
    }
}

4) Test

4. Exceptions
Exception Number (ERROR_COUNT): The number of exceptions in the unit counting time period will automatically break when it exceeds the threshold value, after which the fuse will enter the detection recovery state (HALF-OPEN state), and if the next request completes successfully (without error), the fuse will end or it will be broken again.
Note: Exception demotion is only for business exceptions and is not valid for the exception of Sentinel flow limiting demotion itself (BlockException).

1) Add Demotion Rule

2) controller code

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/err")
    public String err(){
        int a = 1/0;
        return "error";
    }
}

3) Test

sentinel integrated openfeign demotion


1) Introducing Dependency

<dependencies>
  <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>

     <!--nacos Service Registration Discovery-->
     <dependency>
         <groupId>com.alibaba.cloud</groupId>
         <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
     </dependency>

     <!--1.Add to openfeign rely on-->
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-openfeign</artifactId>
     </dependency>

     <!--sentinel rely on-->
     <dependency>
         <groupId>com.alibaba.cloud</groupId>
         <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
     </dependency>
 </dependencies>

2>application.yml

server:
  port: 8041
# Apply name (nacos will use that name as the service name)
spring:
  application:
    name: order-service
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        username: nacos
        password: nacos
        namespace: public
feign:
  sentinel:
    # openfeign integration sentinel
    enabled: true

3) openfeign interface

/**
 * Add feign interfaces and methods
 * name  Specify the service name for the call to rest interface
 * path  Specify @RequestMapping specified by the StockController where the rest interface is called
 */
@FeignClient(name = "stock-service", path = "/stock", fallback = StockFeignServiceFallback.class)
public interface StockFeignService {

    /**
     * Declare the method corresponding to the rest interface that needs to be invoked
     * @return
     */
    @RequestMapping("/reduct2")
    String reduct2();

}

4) fallback implementation class of openfeign

@Component
public class StockFeignServiceFallback implements StockFeignService{

    @Override
    public String reduct2() {
        return "Downgraded~~~~~";
    }
}

5) OrderController class

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @Autowired
    StockFeignService stockFeignService;

    @RequestMapping("/add")
    public String add(){
        log.info("Order successful!");
        String result = stockFeignService.reduct2();
        return "Hello Feign !" + result;
    }
}

6) StockController class in stock-service service

@RestController
@RequestMapping("/stock")
@Slf4j
public class StockController {

    @Value("${server.port}")
    public String port;

    @RequestMapping("/reduct2")
    public String reduct2(){
        int a = 1/0;
        log.info("Deduct inventory!");
        return "Deduct inventory" + port;
    }
}

7) Test

sentinel hot spot parameter flow control (hot spot identification flow control)

What are hot spots? Hot spots are frequently visited data. Many times we want to count the most frequently accessed data in a hot spot and restrict its access, such as:

Hot Spot Parameter Limiting counts the hot spot parameters in the incoming parameters and restricts the flow of resource calls containing hot spot parameters based on the configured threshold and mode of flow restriction. Flow restriction with hot spot parameters can be viewed as a special kind of traffic control that only takes effect on resource calls that contain hot spot parameters.

Be careful:
1) Hot spot rules need to be annotated with @SentinelResource("resourceName") or they will not take effect
2) Parameters must be seven basic data types for them to take effect

Configure Hot Spot Parameter Rules
Note: The resource name must be the one configured in @SentinelResource(value="resource name"), and the hot spot rule depends on the comment

Specifically to parameter value limit, configuration parameter value is 3, current limit threshold is 2


controller code:

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    /**
     * Hot spot rule, must use @SentinelResource
     * @param id
     * @return
     */
    @RequestMapping("/get/{id}")
    @SentinelResource(value = "getById", blockHandler = "hotBlockHandler")
    public String getById(@PathVariable("id") Integer id){
        log.info("Normal Access");
        System.out.println("Normal Access");
        return "Normal Access";
    }

    public String hotBlockHandler(@PathVariable("id") Integer id, BlockException e){
        return "Hot spot exception handling";
    }

}

Test:

sentinel System Protection Rules


Sentinel System Adaptive Flow Limiting controls the application entrance flow from the overall dimension. Combining several dimensions of monitoring indicators such as Load, CPU usage, overall average RT, entrance QPS and number of concurrent threads, an adaptive flow control strategy balances the system entrance flow with the system load. Keep the system as stable as possible while maximizing throughput.
1) Load Adaptive (only works on Linux/Unix-like machines): Load 1 serves as a heuristic indicator for adaptive system protection. System protection (BBR phase) is triggered when system load1 times out and the current number of concurrent threads in the system exceeds the estimated system capacity. System capacity is estimated from the system's maxQps * minRt. Setting a reference value is typically CPU cores * 2.5.
https://www.cnblogs.com/gentlemanhai/p/8484839.html
2) CPU usage (version 1.5.0+): When the system CPU usage exceeds the threshold, triggering system protection (value range 0.0-1.0) is more sensitive.
3) Average RT: System protection is triggered when the average RT of all input traffic on a single machine reaches a threshold in milliseconds.
4) Number of concurrent threads: System protection is triggered when the number of concurrent threads for all incoming traffic on a single machine reaches a threshold.
5) Entry QPS: When the QPS of all the input traffic on a single machine reaches the threshold, the system protection is triggered.

Write system rules

Test:

sentinel rule persistence

1.Sentinel persistence mode
The Sentinel rule is pushed in three modes:

Push modeExplainAdvantageshortcoming
Original modeThe API pushes rules to the client and updates them directly into memory, extending the WritableDataSourceSimple, no dependencyNo consistency is guaranteed; Rules are saved in memory and restart disappears. Seriously not recommended for environment generation
Pull modeExtended Writable DataSource, where the client actively polls a rule management center for pull rules on a regular basis, which can be RDBMS, files, etc.Simple, no dependency; Rule PersistenceConsistency is not guaranteed; Real-time is not guaranteed, and pulling too often can also cause performance problems.
Push modeExtended Readable Data Source (ReadableDataSource), a unified push from the Rule Center, allows clients to monitor changes at all times by registering listeners, such as using configuration centers such as Nacos and Zookeeper, which provide better real-time and consistency assurance. A data source in the build environment that uses push mode.Rule persistence; Uniformity; fastIntroducing third-party dependency

1. Original mode
Without any modifications, Dashboard's push rules are pushed to the client through the API and updated directly into memory.

The advantage of this approach is that it is simple and independent; The disadvantage is that the restart rule disappears and is only used for simple testing, not for production environments.

2. Pull mode
Data sources in pull mode, such as local files, RDBMS, and so on, are generally writable. When using it, you need to register the data source on the client: register the corresponding data source with the corresponding RuleManager, and register the written data source with the WritableDataSourceRegistry of the transport.

3. Push mode
Data sources in the push mode are generally more commonly used in production environments. For data sources in push mode, such as Zookeeper, Nacos, Apollo, and so on, the push operation should not be performed by Sentinel clients, but should be managed by the console and pushed directly. The data source is only responsible for obtaining the configuration pushed by the configuration center and updating it locally. Therefore, the correct way to push rules is to configure the central console/Sentinel console --> Configuration Center --> Sentinel Data Source --> Sentinel, instead of pushing through Sentinel Data Source to the Configuration Center. This process is very clear.

1) Push based on Nacos Configuration Center Console
Official demo:sentinel-demo-nacos-datasource

Introducing dependencies

<dependency>
     <groupId>com.alibaba.csp</groupId>
     <artifactId>sentinel-datasource-nacos</artifactId>
 </dependency>

nacos configuration center configures flow control rules

application.yml configuration

server:
  port: 8861
spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858
      web-context-unify: false  # Link convergence will be invoked by default
      datasource:
        flow-rule:  # Can be customized
          nacos:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            dataId: order-sentinel-flow-rule
            rule-type: flow

controller code:

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/flow")
    public String flow(){
        return "Normal access!!!";
    }
}

Test:
Starting a project requesting an interface generates the following flow control rules

Topics: Java Spring Boot Spring Cloud Microservices