Microservice SpringCloud Alibaba ------Sentinel

1. Service avalanche

The unavailability of service providers leads to the unavailability of service callers and gradually enlarges the unavailability, which is called service avalanche effect.
When the service provider is unavailable, there will be a large number of retries: user retries and code logic retries. These retries will eventually lead to further increase the request traffic. Therefore, in the final analysis, the most fundamental reason for the avalanche effect is the resource depletion caused by a large number of request threads waiting synchronously. When service callers use synchronous calls, a large number of waiting threads will be generated and occupy system resources. Once the thread resources are exhausted, the services provided by the service caller will also be unavailable, so the service avalanche effect occurs.

1.1. Solution

Improve service stability and resilience

1.1.1. Common fault tolerance mechanisms

  1. Timeout mechanism
    Without any processing, the unavailability of the service provider will lead to the forced waiting of the consumer request thread, resulting in the depletion of system resources. Add a timeout mechanism to release resources once timeout occurs. Due to the rapid release of resources, the problem of resource depletion can be restrained to a certain extent.

  2. Service current limiting
    Limit only a specified number of requests to the background server in a certain period of time. In case of peak traffic or sudden increase of traffic, limit the traffic rate to a reasonable range acceptable to the system, so as not to make the system collapse by high traffic.

  3. quarantine
    Principle: the user's request will no longer directly access the service, but through the idle thread in the thread pool. If the thread pool is full, it will be degraded. The user's request will not be blocked. At least one execution result (such as returning friendly prompt information) can be seen, rather than endless waiting or system crash.

    3.1. Thread isolation
    A separate thread pool is opened for each service interface to maintain isolation from other service interface threads and improve the independence and high availability of the service interface.

    3.2. Signal isolation
    Each time a thread is called, the current request is limited by counting semaphores. When the signal is greater than the maximum number of requests, it is limited.

  4. Service fuse
    When the remote service is temporarily shut down due to instability or network jitter, it is called service fusing.
    Everyone in the real world must know the circuit breaker very well. The circuit breaker monitors the circuit in real time. If the circuit current is abnormal, it will trip, so as to prevent the circuit from being burned.
    The circuit breaker in the software world can be understood in this way: for real-time monitoring applications, if it is found that the number of failures / failure rate reaches a certain threshold within a certain period of time, it will "trip", and the circuit breaker will open - at this time, the request will return directly without calling the original logic. Trip for a period of time
    After (for example, 10 seconds), the circuit breaker will enter the half open state, which is a transient state. At this time, it is allowed to request to call the logic of the call once. If it is successful, the circuit breaker will be closed and the application will call normally: if the call is still unsuccessful, the circuit breaker will continue to return to the open state after a period of time
    Try to enter the half open state again - through "tripping", the application can protect itself and avoid wasting resources; through the half open design, the application can realize "self repair".
    Therefore, for the same reason, when the dependent service has a large number of timeouts, it is meaningless to allow new requests to access, and it will only fearlessly consume existing resources. For example, we set the timeout to 1s. If a large number of requests fail to respond within 1s in a short time, it means that the service has an exception. At this time, it is not necessary to allow other requests to access It is a dependency. At this time, the circuit breaker should be used to avoid resource waste.

  5. service degradation
    If there is a service fuse, there must be service degradation.
    The so-called degradation means that when a service is blown out, the service will no longer be called. At this time, the client can prepare a local allback callback and return a default value. For example: (standby interface / cache / mock data). Although the service is flat
    Decline, but it's better to be available at any rate than to hang up directly. Of course, it also depends on the appropriate business scenario.

2. Sentinel initial experience

Sentinel is Alibaba's open source high availability protection component for distributed service architecture.
With the popularity of microservices, the stability between services and services has become more and more important. Sentinel is a flow control component for distributed service architecture. It mainly takes flow as the starting point to help developers ensure the stability of microservices from multiple dimensions, such as flow restriction, flow shaping, fuse degradation, system load protection, hotspot protection and so on.
Click to view official documents

2.1. Add dependency

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

<!-- sentinel Core library -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.0</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.18</version>
</dependency>

<!-- If you want to use@SentinelResource -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.0</version>
</dependency>

2.2. Add startup class

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

/**
 * @Author Xxx
 * @Date 2021/11/24 18:49
 * @Version 1.0
 */
@SpringBootApplication
public class SentinelDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SentinelDemoApplication.class, args);
    }

    // Annotation supported configuration Bean
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
        return new SentinelResourceAspect();
    }
}

2.3. Add pojo and controller

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

/**
 * @Author Xxx
 * @Date 2021/11/25 14:45
 * @Version 1.0
 */
@Data
@ToString
@AllArgsConstructor
public class User {

    private String username;

}
/**
 * @Author Xxx
 * @Date 2021/11/24 18:26
 * @Version 1.0
 */

@RestController
@Slf4j
public class HelloController {
    private static final String RESOURCE_NAME = "hello";
    private static final String USER_RESOURCE_NAME = "user";
    private static final String DEGRADE_RESOURCE_NAME = "degrade";
}

2.4. Current limiting through code

Add in controller

// sentinel flow control
@RequestMapping("/hello")
public String hello(){

    Entry entry = null;
    try {
        // sentinel limits resources
        entry = SphU.entry(RESOURCE_NAME);
        // Protected business logic
        String str = "hello world";
        log.info("==={}===", str);
        return str;
    } catch (BlockException e) {
        // Resource access is blocked, restricted or degraded
        // Carry out corresponding processing operations
        log.info("block!");
        return "Flow control!";
    } catch (Exception ex){
        // If you need to configure flow restriction rules, you need to record business exceptions in this way
        Tracer.traceEntry(ex, entry);
    }finally {
        if(entry != null){
            entry.exit();
        }
    }
    return null;

}

/**
 * Define rules
 */
@PostConstruct
private static void initFlowRules(){

    // Flow control rules
    List<FlowRule> rules = new ArrayList<>();

    // Flow control
    FlowRule rule = new FlowRule();
    // Set protected resources
    rule.setResource(RESOURCE_NAME);
    // Set flow control rule type QPS
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // Set protected resource threshold
    // set limit QPS 1 to 20
    rule.setCount(1);
    rules.add(rule);

    // Load configured rules
    FlowRuleManager.loadRules(rules);
}

2.5. Current limiting by annotation

Add in controller

/**
 * Define rules
 */
@PostConstruct
private static void initFlowRules(){

    // Flow control rules
    List<FlowRule> rules = new ArrayList<>();

    // Define resources through @ SentinelResource and configure the processing methods of degradation and flow control
    FlowRule rule2 = new FlowRule();
    // Set protected resources
    rule2.setResource(USER_RESOURCE_NAME);
    // Set flow control rule type QPS
    rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // Set protected resource threshold
    // set limit QPS 1 to 20
    rule2.setCount(1);
    rules.add(rule2);

    // Load configured rules
    FlowRuleManager.loadRules(rules);
}

/**
 * @SentinelResource Improve the resource definition in the interface and the processing method after being degraded by flow control
 * 1. Add dependency < artifactid > sentinel annotation AspectJ < / artifactid >
 * 2. Configure Bean - SentinelResourceAspect
 * value = Define resources
 * blockHandler = Processing method of flow control degradation (this method must be declared in the same class by default)
 * clockHandlerClass = The class of blockHandler is specified through this attribute, but the method must be static decorated
 * fallback = When an interface exception occurs, it can be handled by the method specified by fallback
 * exceptionsToIgnore = Which exceptions are not handled
 * If both blockHandler and fallback are specified, blockHandler has higher priority when exceptions and current limit are triggered at the same time
 * @param id
 * @return
 */
@RequestMapping("/user")
@SentinelResource(value = USER_RESOURCE_NAME, exceptionsToIgnore = {ArithmeticException.class}, fallback = "fallbackForGetUser",blockHandler = "blockHandlerForGetUser")
public User getUser(String id){
	// You can release the test fallback
    // int a = 1 / 0;

    return new User("zhangsan");
}

public User fallbackForGetUser(String id, Throwable ex){
    ex.printStackTrace();
    return new User("abnormal");
}

/**
 * 1. Method must be public decorated
 * 2. The return value must be consistent with the original method, including the parameters of the original method
 * 3. You can add a BlockException class at the end of the parameter to distinguish the processing methods of the rules
 * @param id
 * @param ex
 * @return
 */
public User blockHandlerForGetUser(String id, BlockException ex){
    ex.printStackTrace();
    return new User("Flow control!");
}

2.6. Realize fuse degradation

Add in controller

@PostConstruct
public void initDegradeRule(){
    // Degradation rule
    List<DegradeRule> degradeRules = new ArrayList<>();
    DegradeRule degradeRule = new DegradeRule();
    degradeRule.setResource(DEGRADE_RESOURCE_NAME);
    // Set fusing rule: different constant
    degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
    // Number of abnormal triggering fusions
    degradeRule.setCount(2);
    // Minimum number of requests triggered
    degradeRule.setMinRequestAmount(2);
    // Statistics (MS)
    degradeRule.setStatIntervalMs(60 * 1000);
    // Setstatintervalms = 60 * 1000, setminrequestamount = 2, setcount = 2, it means that it has been executed twice within 1 minute, and it will fuse if there are two exceptions
    // Fusing duration (s)
    // Once the fuse is triggered, requesting the corresponding interface again will call the degraded method (blockHandler)
    // The setTimeWindow will turn to half open after the time has passed. If the first request is abnormal, it will continue to fuse and will not be determined according to the set conditions
    degradeRule.setTimeWindow(10);
    degradeRules.add(degradeRule);
    DegradeRuleManager.loadRules(degradeRules);

}

@RequestMapping("/degrade")
@SentinelResource(value = DEGRADE_RESOURCE_NAME, entryType = EntryType.IN, blockHandler = "blockHandlerForFb")
public User degrade(String id) throws InterruptedException {
    // Different constants \ proportions
    throw new RuntimeException("abnormal");

    /* Slow call ratio
    TimeUnit.SECONDS.sleep(1);
    return new User("Normal ");
             */
}

public User blockHandlerForFb(String id, BlockException ex)  {
    ex.printStackTrace();
    return new User("Downgrade!");
}

3. Console deployment

jar package download address: https://github.com/alibaba/Sentinel/releases

For version relationship, see

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

Start console command

java -jar sentinel-dashboard-1.8.1.jar

You can configure through the following parameters:
-Dsentinel.dashboard.auth.username=sentinel is used to specify that the login user name of the console is sentinel;
-Dsentinel.dashboard.auth.password=123456 specifies that the login password of the console is 123456. If these two parameters are omitted, the default user and password are sentinel;
-Dserver.servlet.session.timeout=7200 is used to specify the expiration time of the Spring Boot server session. For example, 7200 means 7200 seconds; 60m means 60 minutes, which is 30 minutes by default;
-Dserver.port=8858 specifies the sentinel console port

java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=xushu Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.8.1.jar

To facilitate quick startup, you can create a bat file on the desktop

java -Dserver.port=8858 -Dsentinel.dashboard.auth.username=xushu -Dsentinel.dashboard.auth.password=123456 -jar D:\server\sentinel-dashboard-1.8.1.jar
pause

visit http://127.0.0.1:8080/#/login , default user password: sentinel/sentinel

3.1. Client integration

3.1.1. Add dependency

<!-- integration Sentinel Console -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.1</version>
</dependency>

When starting, add the JVM parameter - Dcsp.sentinel.dashboard.server=consoleIp:port to specify the console address and port.

If multiple applications are started, you need to specify the port of the client monitoring API through - Dcsp.sentinel.api.port=xxxx (8719 by default).
Starting from version 1.6.3, the console supports gateway flow control rule management. You need to add - Dcsp.sentinel.app.type=1 startup parameter at the access end to mark your service as API Gateway. When accessing the console, your service will be automatically registered as gateway type, and then you can configure gateway rules and API grouping on the console.
In addition to modifying JVM parameters, you can also achieve the same effect through the configuration file. For more details, please refer to Start configuration item.

4. Spring Cloud Alibaba integrates Sentinel

4.1. Add dependency

<!-- sentinel Starter, spring-cloud-starter-alibaba-nacos-discovery Version already managed -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

4.2. Add profile

application.yml

spring:
  application:
    name: Service name
  cloud:
    sentinel:
      transport:
        dashboard: Console IP:port

4.3. Flow control rules

  • The principle of flow control is to monitor the QPS of application traffic or the number of concurrent threads. When the specified threshold is reached, the flow is controlled to avoid being overwhelmed by the instantaneous traffic peak, so as to ensure the high availability of the application. = = = = flowrule RT (response time) 1/0.2s =5
    The most pervasive scenario:

    • The Provider controls the pulse flow
    • Flow control for different call sources
    • Web interface flow control

    How to configure rules:

    • Sort out the core interface
    • Evaluate the core interface capacity through pre pressure test and configure QPS threshold

4.4. QPS flow control

When the QPS exceeds the threshold, measures will be taken for flow control. The strategies include direct rejection, Warm Up and uniform queuing.

  1. Quick failure: the default flow control mode: direct reject (RuleConstant.CONTROL_BEHAVIOR_DEFAULT), and throw a FlowException after rejection. It is applicable to the system with known processing capacity (the water level of the system processing capacity is known)
  2. Warm Up (surge flow), i.e. warm-up / cold start mode. Through cold start, let the flow through slowly increase and gradually increase to the threshold line (give the system a warm-up time) to prevent the cold start system from being crushed.
    Cold load factor: codeFactor is 3 by default, that is, QPS is requested to start from threshold/3 and gradually rise to the set threshold after preheating the market.
  3. Uniform queuing (pulse traffic): let the request pass at a uniform speed, corresponding to the token bucket algorithm (Note: the uniform queuing mode does not support the scenario of QPS > 1000 for the time being.)

When the flow control effect is the pulse flow in case of rapid failure (type = QPS, threshold = 5), you can see some success and some failure

The flow control effect is the pulse flow when queuing at a constant speed (type = QPS, threshold = 5, timeout time 5000 ms). You can see that all requests are successful

4.4.1. New interface

/**
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
public class OrderController {
    @RequestMapping("/flow")
    @SentinelResource(value = "flow", blockHandler = "flowBlockHandler")
    public String flow(){
        return "Normal access";
    }

    public String flowBlockHandler(BlockException e){
        e.printStackTrace();
        return "Flow control";
    }
}

4.4.2. Add flow control rule



After adding, it can be viewed in the flow control rules on the left

4.5. Thread flow control

Concurrency control is used to protect the business thread pool from being exhausted by slow calls. The isolation scheme of thread pool isolation can be adopted (different businesses use different thread pools). The disadvantages and costs of this method are that there are too many threads and the overhead of thread context switching is relatively large.

4.5.1. New interface

/**
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
public class OrderController {

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

    public String flowBlockHandler(BlockException e){
        e.printStackTrace();
        return "Flow control";
    }

}

4.5.2. Add flow control rule

4.5.3. Test precautions

Access through two browsers http://127.0.0.1:8060/order/flowThread

4.6. Unified handling of blockexception exceptions

The resource flow limiting entry of the springwebmvc interface is in the preHandle method of the implementation class AbstractSentinelInterceptor of the HandlerInterceptor. The exception handling is the implementation class of BlockExceptionHandle

code

/**
 * @Author Xxx
 * @Date 2021/11/26 18:12
 * @Version 1.0
 */
@Data
public class Result<T> {

    private Integer code;

    private String msg;

    private T data;

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

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

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





/**
 * @Author Xxx
 * @Date 2021/11/26 18:07
 * @Version 1.0
 */
@Component
@Slf4j
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        // getRule() details of resource rule
        log.info("MyBlockExceptionHandler => {}",e.getRule());

        Result r = null;

        if(e instanceof FlowException){
            r = Result.error(100, "The interface is current limited");

        }else if(e instanceof DegradeException){
            r = Result.error(101, "The service has been downgraded");

        }else if(e instanceof ParamFlowException){
            r = Result.error(102, "Hot spot parameter current limiting");

        }else if(e instanceof SystemBlockException){
            r = Result.error(103, "The system protection rules have been triggered");

        }else if(e instanceof AuthorityException){
            r = Result.error(104, "Authorization rule failed");

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

}


/**
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @RequestMapping("/add")
    public String add(){
        log.debug("Order successfully!");
        return "Order successfully!" ;
    }

}

Test after adding flow control rule
Resource BlockExceptionHandler with @ SentinelResource annotation cannot be intercepted

4.7. Flow control mode

Flow control based on call relationship. Call relationship includes caller and callee; a method may call other methods to form a hierarchical relationship of call link.

4.7.1. Direct

When the resource call reaches the set threshold, the flow control will throw an exception directly

4.7.2. Association

When there is a resource contention or dependency relationship between two resources, the two resources are associated. For example, there is a contention between read and write operations on the same field in the database. Too high reading speed will affect the writing speed, and too high writing speed will affect the reading speed. If you allow read and write operations to compete for resources, the cost of contention will reduce the overall cost Throughput. You can use association throttling to avoid excessive contention between resources with association relationship. For example, read_db and write_db represent database read and write respectively. We can set throttling rules for read_db to achieve the purpose of write priority: set strategy to ruleconstant.strategy_relax, and set refResource to write_db. In this way, when the write library is operated When frequent, the request to read data will be limited.

Add code

/**
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @RequestMapping("/add")
    public String add(){
        log.debug("Order successfully!");
        return "Order successfully!" ;
    }

    @RequestMapping("/get")
    public String get(){
        log.debug("Query order!");
        return "Query order!" ;
    }
}

4.7.3. Link

Limit the current according to the call link entry.
NodeSelectorSlot records the call links between resources. These resources form a call tree through the call relationship. The root node of this tree is a virtual node named machine root, and the entry of the call chain is the child node of this virtual node.

Add code

public interface IOrderService {

    String getUser();
}



/**
 * @Author Xxx
 * @Date 2021/11/26 21:13
 * @Version 1.0
 */
@Service
public class OrderServiceImpl implements IOrderService {

    @SentinelResource(value = "getUser")
    public String getUser() {
        return "Query user!";
    }

}



/**
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @Autowired
    private IOrderService orderService;

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

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


The test will find that the link rule does not take effect

Note that this function does not take effect when used directly in higher versions. How to solve it?
Since version 1.6.3, Sentinel Web filter converges the entry context of all URL s by default, so the link current limit does not take effect.
Since version 1.7.0 (corresponding to 2.1.1.release of SCA), the official cited the web in CommonFilter_ CONTEXT_ The unify parameter is used to control whether the context is convergent. Configure it to false to limit the link current according to different URL s.
For the version after SCA 2.1.1.RELEASE, you can turn off convergence by configuring spring.cloud.sentinel.web-context-unify=false. Our current version is SpringCloud Alibaba 2.1.0.RELEASE, which cannot realize link flow restriction.
At present, 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 code
present

spring:
	cloud:
		sentinel:
			web-context-unify: false #The default value is true. Link convergence will be called

Test: only in this scenario, the global exception handler cannot intercept BlockException. The corresponding resource specified by @ SentinelResource must specify blockHandler in @ SentinelResource annotation to handle BlockException
Summary: in order to solve the problem of introducing ComonFilter into link rules, it will cause more problems. It is not recommended to use ComonFilter. The problem of flow control link mode is waiting for the official follow-up repair, or AHAS is used.

4.8. Fusing strategy

4.8.1. Slow call ratio

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.

// Simulate slow call interface
@RequestMapping("/flowThread")
public String flowThread() throws InterruptedException {
    TimeUnit.SECONDS.sleep(2);
    return "Normal access";
}

4.8.2. Abnormal proportion

Exception ratio (ERROR RTIO): when the number of requests in the unit statistical duration (statIntervalMs) is greater than the set minimum number of requests, and the exception ratio 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%.

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

4.8.3. Different constants

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: exception degradation is only for business exceptions, and does not take effect for the exception (BlockException) of Sentinel current limiting degradation itself.

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

4.9. Hot spot parameter flow control

What are hot spots? Hot spots are frequently accessed data. Many times, we want to count the Top K data with the highest access frequency in a hot data and restrict its access. For example:

Commodity ID is a parameter that counts and limits the most frequently purchased commodity ID in a period of time
User ID is a parameter, which limits the user ID frequently accessed over a period of time

4.9.1. Configure a hotspot flow control interface

/**
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    // Test the hotspot parameter flow control interface, which can only be implemented by @ SentinelResource
    @RequestMapping("/get/{id}")
    @SentinelResource(value = "getById", blockHandler = "HotBlockHandle")
    public String getById(@PathVariable("id") int id){
        return "Normal access";
    }

    public String HotBlockHandle(@PathVariable("id") int id, BlockException ex){
        return "Hot spot parameter flow control!";
    }

}

4.10. System protection rules

Sentinel system's adaptive flow restriction controls the application inlet flow from the overall dimension. Combined with the monitoring indicators of application Load, CPU utilization, overall average RT, inlet QPS and the number of concurrent threads, the system inlet flow and system Load are balanced through adaptive flow control strategy, Let the system run at the maximum throughput as much as possible while ensuring the overall stability of the system.

  • 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.
    https://www.cnblogs.com/gentlemanhai/p/8484839.html
  • 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.

5. Openfeign integrates Sentinel

5.1. Step 1

Add dependency

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

5.2. Step 2

application.yml add configuration item

spring:
  cloud:
    # reference resources https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc#%E5%85%B3%E4%BA%8E-nacos-discovery-starter-%E6%9B%B4%E5%A4%9A%E7%9A%84%E9%85%8D%E7%BD%AE%E9%A1%B9%E4%BF%A1%E6%81%AF
    nacos:
      discovery:
        # The ip address and port on which the Nacos Server starts listening
        server-addr: 127.0.0.1:8848
        # Registered service name
        service: order-openfeign-sentinel
        # Namespace ID, Nacos uses different namespaces to distinguish different environments and isolate data. When consuming services, they can only consume services under the corresponding namespace.
        namespace: public
        # Account number of nacos service
        username: nacos
        # Password for the nacos service
        password: nacos
feign:
  sentinel:
    # feign integrates sentinel. The default value is false
    enabled: true

5.3. Step 3

Add code

/**
 * spring Startup class
 * @Author Xxx
 * @Date 2021/11/18 17:17
 * @Version 1.0
 */
@SpringBootApplication
//@EnableDiscoveryClient
@EnableFeignClients
public class OrderOpenfeignSentinelApplication {

    public static void main(String[] args) {
        SpringApplication.run( OrderOpenfeignSentinelApplication.class, args );
    }

}





// OpenFeign interface fallback is used for fusing
// Name = service name / path = Controller class ReqeustMapper
@FeignClient(name = "stock-service", path = "/stock", fallback = StockFeignServiceFallback.class)
public interface StockFeignService {

  // Declare the method corresponding to the rest interface to be called
  @RequestMapping("/reduct2")
  public String reduct2();

}





/**
 * The class specified by fallback must implement the interface marked by @ FeignClient
 * @Author Xxx
 * @Date 2021/11/29 15:49
 * @Version 1.0
 */
@Component
public class StockFeignServiceFallback implements StockFeignService {

    public String reduct2() {
        return "Demoted!";
    }

}





/**
 * Interface
 * @Author Xxx
 * @Date 2021/11/18 17:10
 * @Version 1.0
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    // Step 3: inject feign interface and call method
    @Resource
    private StockFeignService stockFeignService;

    @RequestMapping("/add")
    public String add(){
        log.debug("Order successfully!");

        String result = stockFeignService.reduct2();
        return "hello feign!" + result ;
    }
}

Stock service controller code

/**
 * @Author Xxx
 * @Date 2021/11/18 17:14
 * @Version 1.0
 */
@RestController
@RequestMapping("/stock")
@Slf4j
public class StockController {

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

    @RequestMapping("/reduct2")
    // Sentinel for testing Openfeign integration
    public String reduct2(){
        int a = 1 / 0;
        return "Inventory deduction succeeded! Port:" + port;
    }

}

6. Rule persistence

6.1. Step 1

Add dependency

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

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

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

6.2. Step 2

Add application.yml

spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858
      web-context-unify: true #The default value is true. Link convergence will be called
      # Persistence rule configuration reference https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
      datasource:
        flow-rule: #Can customize
          nacos:
            server-addr: 127.0.0.1:8848
            # Account number of nacos service
            username: nacos
            # Password for the nacos service
            password: nacos
            data-id: order-sentinel-flow-rule
            rule-type: flow
    # reference resources https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-discovery.adoc#%E5%85%B3%E4%BA%8E-nacos-discovery-starter-%E6%9B%B4%E5%A4%9A%E7%9A%84%E9%85%8D%E7%BD%AE%E9%A1%B9%E4%BF%A1%E6%81%AF
    nacos:
      discovery:
        # The ip address and port on which the Nacos Server starts listening
        server-addr: 127.0.0.1:8848
        # Account number of nacos service
        username: nacos
        # Password for the nacos service
        password: nacos

7. Code download

https://download.csdn.net/download/qq_42017523/52033780

Tags: Java Spring Cloud Microservices

Posted on Mon, 29 Nov 2021 13:27:40 -0500 by GinsBabu