1. Sentinel Overview

What is Sentinel?

With the popularity of microservices, stability between services becomes increasingly important. Sentinel is a lightweight flow control component for distributed service architecture. It mainly focuses on traffic and helps you ensure the stability of micro services from multiple dimensions such as traffic limiting, traffic shaping, fuse downgrading and system load protection.

Sentinel has the following characteristics:

  • Rich application scenarios: Sentinel has undertaken the core scenarios of Alibaba’s double Eleven traffic drive in the past 10 years, such as SEC killing (i.e. burst traffic control within the range of system capacity), message peaking and valley filling, cluster flow control, real-time fusing of unavailable downstream applications, etc.
  • Complete real-time monitoring: Sentinel also provides real-time monitoring capabilities. From the console, you can see a summary of the performance of a single machine-by-second data, or even a cluster of less than 500 machines, for accessing the application.
  • Extensive Open source ecosystem: Sentinel provides out-of-the-box integration modules with other open source frameworks/libraries, such as Spring Cloud, Dubbo, and gRPC. You can quickly access Sentinel by introducing the appropriate dependencies and simple configuration.
  • Sophisticated SPI extension points: Sentinel provides an easy-to-use, sophisticated SPI extension interface. You can quickly customize the logic by implementing an extension interface. For example, customize rule management and adapt dynamic data sources.

Key features of Sentinel:

Sentinel GitHub: github.com/alibaba/Sen…

Sentinel V1.8 Chinese Documentation Manual

2. Sentinel download, install and run

1. Download and install

Download: github.com/alibaba/Sen…

2, run,

Sentinel is divided into two parts:

  • The core library (Java client) is independent of any framework/library, can run in all Java runtime environments, and has good support for frameworks such as Dubbo/Spring Cloud.
  • The Console (Dashboard) is based on Spring Boot and can be packaged to run directly without the need for additional application containers such as Tomcat.

Jar package: java-jar sentinel-dashboard-1.8.0.jar

Access request: http://localhost:8080

Both user name and password are sentinel, click login

Sentinel was successfully downloaded and installed.

3. Initialize the demo project

1. Start NACOS

2. Create a module

  1. Create the CloudAlibaba-Sentinel-Service8401 module

  2. Import POM dependencies

    <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <! -- Persistent -->
            <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-datasource-nacos</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
    
            <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>
    
        </dependencies>
    Copy the code
  3. Write the YML configuration file

    server:
      port: 8401
    
    spring:
      application:
        name: cloudalibaba-sentinel-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848  # nacOS service center address
        sentinel:
          transport:
            dashboard: localhost:8080  # configure Sentinel Dashboard address to monitor 8401 via 8080
            port: 8719 The default port is 8719. If the port is occupied, the system will automatically scan from 8719 until the port is not occupied
    
    management:
      endpoints:
        web:
          exposure:
            include: The '*'
    Copy the code
  4. Create the main startup class

    @SpringBootApplication
    @EnableDiscoveryClient
    public class MainApp8401 {
        public static void main(String[] args) { SpringApplication.run(MainApp8401.class,args); }}Copy the code
  5. Writing business

    @RestController
    public class FlowLimitController {
    
        @GetMapping(value = "/testA")
        public String testA(a){
            return "------testA";
        }
    
        @GetMapping(value = "/testB")
        public String testB(a){
            return "------testB"; }}Copy the code
  6. Start the sentinel – dashboard

    Java jar sentinel - dashboard - 1.8.0 comes with. The jarCopy the code
  7. Start the CloudBaba-Sentinel-Service8401 module

  8. Because Sentinel uses lazy loading, we need to access a request for Sentinel-Dashboard to monitor the 8401 service

    http://localhost:8401/testA

    http://localhost:8401/testA

  9. Refresh the Sentinel-Dashboard screen

4. Flow control rules

4.1 Introduction to flow control rules

Flow control monitors application traffic indicators, such as QPS or concurrent threads, and controls the traffic when it reaches a specified threshold to avoid being overwhelmed by instantaneous traffic peaks and ensure high availability of applications.

A traffic limiting rule mainly consists of the following factors, which can be combined to achieve different traffic limiting effects:

  • Resource name: unique name, default request path
  • For source: Sentinel can limit traffic for the caller. Enter the microservice name and default(regardless of source) Threshold type/single-machine threshold:
    • QPS(Number of requests per second) : When the NUMBER of QPS calling the API reaches the threshold, traffic limiting is performed.
    • Number of threads: When the number of threads calling the API reaches the threshold, traffic limiting is performed
  • Cluster or not: No cluster is required
  • Flow control mode:
    • Direct: When the API meets the traffic limiting condition, the API directly limits traffic
    • Association: When the associated resource reaches the threshold, traffic limits itself
    • Link: Only records the traffic on the specified link (the traffic of the specified resource from the inlet resource reaches the threshold, the traffic is restricted)
  • Flow control effect:
    • Fast failure: Fail directly and throw an exception
    • Warm Up: according to the codeFactor (cold loading factor, default 3) value, from the threshold /codeFactor, after the warm-up time, to reach the set QPS threshold
    • Queued waiting: Queued at a constant speed, allowing requests to pass at a constant speed. The threshold type must be set to QPS, otherwise it is invalid

4.2 Flow control mode

2, direct

QPS fails directly

Sentinel flow control mode represents the flow control mode, default [direct]; For the flow control of the above /testA interface, the single QPS threshold is 1, which means that requests per second cannot exceed 1. Otherwise, the flow control process will be performed, and the processing mode will fail directly. Call /testA, slow down the request, return normal; Request several times quickly, exceeding the threshold; The interface returns Blocked by Sentinel (flow Limiting), which indicates that the traffic is limited.

Configuration and Description:

Testing:

Number of threads failed directly

Sentinel concurrent thread limiting does not create and manage a thread pool, but simply counts the number of threads in the current request context. If the threshold is exceeded, new requests are immediately rejected, similar to semaphore isolation.

If more than one thread accesses within 1s, it will fail directly.

Testing:

To http://localhost:8401/testA request to add a second delay, and then open two pages to access:

@GetMapping(value = "/testA")
public String testA(a){

    try {
        TimeUnit.MILLISECONDS.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "------testA";
}
Copy the code

4.2.2, associated

When resource B associated with resource A reaches the threshold, resource A limits itself. For example, in a distributed system, the payment service is associated with the order service, so that when the payment service becomes too frequent, the order service’s requests are limited and the order is not submitted.

Configuration and Description:

Test: jmeter high concurrent voltage /testB interface

The above setting means 5 requests per second, or QPS=5. The flow control threshold was exceeded. Procedure

Jmeter start-up pressure measurement, the browser to http://localhost:8401/testB, find resources/testA is current limit:

Holdings, link

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

Flow control is performed on only one entry of a service.

4.3 Flow control effect

4.3.1 Quick Failure

The direct fast failure mode is == the default flow control mode is ==. When QPS exceeds the threshold of any rule, new requests are immediately rejected by throwing a FlowException. This method is suitable for situations where the processing capacity of the system is clearly known, such as when the exact water level of the system is determined by pressure measurement.

4.2.2, WarmUp

Warm Up (ruleconstant. CONTROL_BEHAVIOR_WARM_UP) : indicates the warmup/cold startup mode. When the system has been at a low water level for a long time, when the flow suddenly increases, directly pulling the system to a high water level can suddenly overwhelm the system. Through the “cold start”, the flow slowly increases to the upper limit of the threshold in a certain period of time, giving the cold system a time to warm up, preventing the cold system from being overwhelmed.

== According to the codeFactor (default 3) value, from (threshold /codeFactor) as the initial threshold, after the preheating time, the set QPS threshold ==

What does that mean? For an example, the threshold is 10 and the warm-up time is set to 5 seconds.

I want testA to eventually be able to withstand 10 QPS per second, with a single threshold of 10, but I only want testA to withstand 10/3 QPS at the beginning, with an initial threshold of about 3. After 5 seconds, the threshold slowly rises to 10.

Testing:

Access request: http://localhost:8401/testA, fast refresh, error will appear at the beginning, but after 5 seconds, even if fast refresh is not an error.

Application Scenarios:

For example: second kill system at the moment of opening, there will be a lot of flow, it is likely to kill the system, preheating is to put in order to protect the system, you can slowly put the flow in, slowly increase the threshold value to the set threshold value.

4.2.3 Uniform queuing

Queue at a uniform speed so that requests pass at a uniform speed. The threshold type must be set to QPS, otherwise it will not work.

This approach is mainly used to deal with intermittent bursts of traffic, such as message queues. Imagine a scenario where a large number of requests arrive in one second and then sit idle for a few seconds. We want the system to process these requests gradually during the rest of the idle period, rather than simply rejecting the extra requests in the first second.

Note: Uniform queuing mode does not support QPS > 1000 scenarios.

Configuration and Description:

The background generates a log for each access to /testA

@GetMapping(value = "/testA")
public String testA(a){
    log.info(Thread.currentThread().getName()+"....testB");
    return "------testA";
}
Copy the code

Test: again using jmeter pressure test was carried out on the http://localhost:8401/testA: set up 20 thread, once per second, infinite loop

Start JMeter and view the background output:

We can see that testA is executed every 1 second, so many requests are not rejected and queued up.

What are the application scenarios of queuing?

For example, sometimes the system will appear in a certain moment of heavy traffic, and then the flow will be restored to stability. You can use this queuing mode. When the heavy traffic comes, you can let the traffic requests queue up first, and then slowly process them after the recovery

5. Demotion rules

5.1 Introduction to downgrade rules

In addition to flow control, fusing downgrading of unstable resources in call links is also one of the important measures to ensure high availability. Because of the complexity of the invocation relationship, if a resource in the invocation link is unstable, requests will eventually pile up. Sentinel fuse degradation limits the invocation of a resource when unstable status (such as call timeout or abnormal proportion increases) occurs in the invocation link, so that the request fails quickly and avoids cascading errors caused by affecting other resources. When a resource is degraded, all calls to the resource are automatically fuses within the next downgrade window (the default behavior is thrown)

Sentinel has made major changes to fuse downgrades in version 1.8.0, allowing the definition of any duration of fuse downgrades and introducing half-open recovery support.

Demotion strategy

Sentinel offers the following circuit breaker strategies:

  • Slow call ratio (SLOW_REQUEST_RATIO) : Select the ratio of slow calls as the threshold. You need to set the allowed RT of slow calls (that is, the maximum response time). If the response time of a request is greater than this value, the request is counted as slow calls. == When unit statistical time (statIntervalMs) if the number of requests is greater than the set minimum number of requests and the ratio of calls is greater than the threshold, the requests will be fused automatically in the following fusing period. == After the fuse duration, the fuse will enter the half-open state. If the response time of the next request is less than the set slow-call RT, the fuse will be terminated. If the response time is longer than the set slow-call RT, the fuse will be disconnected again. RT to 4900.
  • Abnormal ratio (ERROR_RATIO) : == When the unit statistics duration (statIntervalMs) if the number of requests is greater than the set minimum number of requests and the proportion of exceptions is greater than the threshold, the requests will be fused automatically in the following fusing period. == After the fuse duration, the fuse will enter the probe half-open state. If the next request is successfully completed (without error), the fuse will end. Otherwise, the fuse will be fused again. The threshold range for abnormal ratio is[0.0, 1.0], represents 0-100%.
  • Abnormal number (ERROR_COUNT) : == When the number of anomalies in a unit statistics period exceeds the threshold, the system automatically switches off. == After the fuse period, the fuse enters the probe half-open state, terminating the fuse if the next request completes successfully (without error), otherwise it will be fused again.

5.2. De-escalation strategy

5.2.1 Slow call ratio

Slow call: The request whose time is greater than the threshold RT is called slow call. The threshold RT is set by users

Minimum number of requests: specifies the minimum number of requests allowed to pass. Within the minimum number of requests, no circuit breaker occurs

Configuration and Description:

The above configuration description:

When the number of requests is greater than the minimum number of requests (5) and the ratio of delayed calls is greater than the ratio threshold (0.6), a fusing occurs. The fusing duration is 1s.

When the fuse duration exceeds the defined fuse duration, the state changes from fuse (OPEN) to Probe (HALFOPEN).

If the maximum response time of the next request is less than the maximum RT200ms, the slow call has been recovered, the fuse is ended, and the status changes from Probe (HALF_OPEN) to CLOSED.

If the maximum response time of the next request is greater than the maximum RT200ms, it indicates that the slow call is not recovered and the fusing continues. The fusing duration remains the same

test

Add a method: the response time of this method is 1s, greater than 200ms, so calling this method is slow

@GetMapping(value = "/testD")
public String testD(a){
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    log.info("=====testD=====");
    return "------testD";
}
Copy the code

Using Jmeter pressure: configure 10 threads per second to access localhost:8401/testD, greater than the minimum number of requests

Localhost :8401/testD has been fused:

5.2.2 Abnormal proportion

A strategy that compares the percentage of exceptions by setting a threshold.

When the number of requests per second of a resource is greater than or equal to the minimum number of requests, and the proportion of the total number of exceptions to the passed traffic exceeds the proportion threshold, the resource enters the degraded state.

Configuration and Description

Description:

When the number of requests is greater than 5 and the abnormal ratio is greater than 0.2, fusing occurs and the fusing duration is small

Seconds: the service is unavailable for the next 2 seconds.

When the fusing duration exceeds, switch from fusing (OPEN) to probing (HALFOPEN)

If no error occurs on the next request, restore is applied, the fusing ends, and the status changes from probing (HALF_OPEN) to CLOSED.

If an error occurs in the next request, the application is not recovered and the circuit breaker continues for the same duration

test

Add a method that has a runtime exception,

@GetMapping(value = "/testC")
public String testC(a){
    log.info("=====testC=====");
    int age = 10/0;
    return "------testC";
}
Copy the code

Jmeter pressure: configure 10 threads per second to access localhost:8401/testC

Localhost :8401/testC has been fused:

When we shut down JMeter and access this request alone, we will not use the degrade policy because the degradation condition is not met (the number of requests is not met) and will directly jump to the Error Page.

5.2.3 Number of exceptions

A strategy that compares the number of requests for exceptions by setting a threshold

When the number of resource exceptions in the last one minute exceeds the threshold, the service is degraded. Notice The statistical time window is minute. If the circuit breaker duration is less than 60 seconds, the circuit breaker may enter the circuit breaker state again after the circuit breaker state ends.

Configuration and Description:

Description:

Within nearly one minute, a fuse is triggered when the number of requests is greater than 5 and the number of exceptions is greater than 5. The fuse duration is 70s.

When the fusing duration exceeds, switch from fusing (OPEN) to probing (HALFOPEN)

If no error occurs on the next request, restore is applied, the fusing ends, and the status changes from probing (HALF_OPEN) to CLOSED.

If an error occurs in the next request, the application is not recovered and the circuit breaker continues for the same duration

test

Access request localhost:8401/testC 5 times, the first five times are error page, when the sixth time, trigger fuse.

6. Hotspot rules

What is a hot spot? Hot spots are frequently accessed data. Most of the time, we want to collect the Top K data with the highest access frequency in a certain hotspot data and restrict its access. Such as:

  • Item ID is used as parameter. The ID of the most commonly purchased item in a period of time is counted and restricted
  • The user ID is a parameter that limits the user IDS that are frequently accessed within a period of time

Hotspot parameter traffic limiting Collects statistics on hotspot parameters in the incoming parameters and implements traffic limiting for resource invocation containing hotspot parameters based on the configured traffic limiting threshold and mode. Hotspot parameter traffic limiting is a special kind of traffic control that only applies to resource calls containing hotspot parameters.

Sentinel uses LRU strategy to count the most frequently accessed hotspot parameters and combines with token bucket algorithm to control the flow at parameter level. Hotspot parameter traffic limiting Supports cluster mode.

Add method:

For resources defined by the @SentinelResource annotation method, Sentinel passes them in as parameters if there are parameters on the annotation method

@GetMapping(value = "/testE")

@SentinelResource(value = "testE",blockHandler = "deal_hotKey") // Set the backpocket method, when does not comply with the hotspot configuration rules, use the backpocket method, when the program has a runtime exception, or lucky line exception
public String hotKey(@RequestParam(value = "p1",required = false) String p1,
                     @RequestParam(value = "p2",required = false) String p2){

    return "=====testE=====";

}

public String deal_hotKey(String p1, String p2, BlockException exception){
    return "===== implements a bottom-of-the-line approach; deal_hotKey=====";
}
Copy the code

Configuration and Description:

Note: If p1 is accessed for more than three times per second, traffic limiting is performed for resources containing p1 for 1s

Testing:

Carry only P1 parameters for testing

Normal access to the resource: http://localhost:8401/testE? p1=abc

When accessing a resource more than three times in one second:

Carry P1 and P2 tests

Normal access to the resource: http://localhost:8401/testE? p1=abc&p2=def

When the resource is accessed more than three times in one second: the bottom-pocket method is still executed

The test carries only p2. Because p2 is not configured in the hotspot configuration rule, there is no restriction on P2 access.

Parameter exception

Parameter Exception: You can set a traffic limiting threshold for the specified parameter value independently of the count threshold. Only basic and string types are supported

Rules and Instructions:

Note: When the access rate of parameter P1 is greater than 3 per second, traffic limiting is performed for the resources containing parameter P1 for 1s. However, when the value of parameter P1 is 9537, its QPS threshold can be 1000, and the single-machine threshold 3 previously set is invalid.

Test: access request: http://localhost:8401/testE? P1 =9527&p2=def Resources can be accessed normally as long as QPS is less than 1000.

7. System rules

The system ADAPTS to current limiting

The adaptive flow limiting of Sentinel system controls the flow at the entrance of the application from the whole dimension. Combining the monitoring indicators from several dimensions such as the Load of the application, CPU usage, overall average RT, QPS at the entrance and number of concurrent threads, the adaptive flow control strategy achieves a balance between the flow at the entrance of the system and the Load of the system. Let the system run as far as possible in the maximum throughput at the same time to ensure the overall stability of the system.

System Protection Rules

System protection rules control the incoming flow at the application level, and monitor application indicators from several dimensions, such as load of a single machine, CPU usage, average RT, incoming QPS and number of concurrent threads, so that the system can run as fast as possible in the maximum throughput and ensure the overall stability of the system.

System protection rules apply to the global dimension, not the resource dimension, and only apply to incoming traffic. Inbound traffic refers to the traffic entering the application (entrytype. IN), such as the requests received by the Web service or the Dubbo server.

System rules support the following modes:

  • The Load adaptive(Only for Linux/ UNIX-like machines) : Load1 of the system is used as an inspiration indicator for adaptive system protection. System protection (BBR phase) is triggered when system load1 exceeds the set heuristics value and the current number of concurrent threads in the system exceeds the estimated system capacity. System capacity is determined by the systemmaxQps * minRtEstimated. The setting reference value is generallyCPU cores * 2.5.
  • CPU Usage (version 1.5.0+) : When the CPU usage exceeds the threshold, system protection is triggered (value range: 0.0 to 1.0).
  • Average RT: System protection is triggered when the average RT of all inlet traffic on a single machine reaches a threshold, in milliseconds.
  • 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.
  • Inlet QPS: System protection is triggered when the QPS of all inlet flows on a single machine reaches the threshold.

8. @SentinelSource Configuration

@SentinelResource is used to define resources and provides optional exception handling and Fallback configuration items. The @sentinelResource annotation contains the following properties:

  • Value: resource name, required (cannot be empty)

  • EntryType: Entry type, optional (default entrytype.out)

  • ==blockHandler/blockHandlerClass==: blockHandler Specifies the name of the function that processes BlockException. This parameter is optional. The blockHandler function must have a public access scope, a return type that matches the original method, a parameter type that matches the original method and an extra parameter of type BlockException at the end. The blockHandler function needs to be in the same class as the original method by default. If you want to use a function of another Class, you can specify blockHandlerClass as the Class object of the corresponding Class. Note that the corresponding function must be static; otherwise, it cannot be parsed.

  • Fallback/fallbackClass: Optional fallback function name that provides fallback handling logic when an exception is thrown. The fallback function handles all types of exceptions except those excluded from exceptionsToIgnore. Fallback function signature and position requirements:

    • The return value type must be the same as that of the original function;
    • The method argument list needs to be the same as the original function, or an additional argument of type Throwable 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 a function of another Class, you can specify fallbackClass as the corresponding Class object. Note that the corresponding function must be static; otherwise, it cannot be parsed.
  • defaultFallback

    (since 1.6.0) : Default fallback function name, optional, usually used for generic fallback logic (that is, can be used for many services or methods). The default fallback function handles all types of exceptions except those excluded from exceptionsToIgnore. If both fallback and defaultFallback are configured, only fallback takes effect. DefaultFallback signature requirements:

    • The return value type must be the same as that of the original function;
    • The method parameter list needs to be empty, or an additional parameter of type Throwable can be used to receive the corresponding exception.
    • DefaultFallback needs to be in the same class as the original method by default. If you want to use a function of another Class, you can specify fallbackClass as the corresponding Class object. Note that the corresponding function must be static; otherwise, it cannot be parsed.
  • ExceptionsToIgnore (since 1.6.0) : Specifies which exceptions are excluded and are not counted in the exception statistics or fallback logic. Instead, it is thrown as is.

Note: Annotation methods do not support private methods.

8.1. Traffic Limiting by Resource Name

1. Add POM dependency to CloudBaba-Sentinel-Service8401 module:

<dependency>
    <groupId>com.cheng.springcloud</groupId>
    <artifactId>cloud-api-commons</artifactId>
    <version>1.0 the SNAPSHOT</version>
</dependency>
Copy the code

2. Add a controller

@RestController
public class RateLimitController {

    @GetMapping(value = "/byResource")
    @SentinelResource(value = "byResource",blockHandler = "handleException")
    public CommonResult byResource(a){
        return new CommonResult(200."Flow limiting test by resource name OK".new Payment(12L."serial001"));
    }
    public CommonResult handleException(BlockException exception){
        return new CommonResult(444,exception.getClass().getCanonicalName()+"Traffic restricted, service unavailable."); }}Copy the code

3, test,

Use the default flow control mode

Access request: http://localhost:8401/byResource, a second visit

Multiple access in one second: service traffic limiting, returns custom traffic limiting information

8.2. Traffic Limiting by URL Address

Add a method:

@GetMapping(value = "/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl(a){
    return new CommonResult(200."Test by URL limit flow ok".new Payment(2021L."serial002"));
}
Copy the code

Configure flow control rules:

test

Access request: http://localhost:8401/rateLimit/byUrl, a second visit

If the service traffic is restricted for multiple accesses within one second, the system traffic limiting information is displayed

8.3 Customer custom flow limiting processing logic

Create the CustomerBlockHandler class to customize the flow limiting logic

public class CustomerBlockHandler {

    public static CommonResult handlerException1(BlockException exception){
        return new CommonResult(444."According to customer's custom plan 1");
    }

    public static CommonResult handlerException2(BlockException exception){
        return new CommonResult(444."According to customer custom Plan 2"); }}Copy the code

Increase method:

@GetMapping(value = "/rateLimit/customerBH")
@SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerException2") // Select the handlerException2 method in the CustomerBlockHandler class to limit traffic
public CommonResult customerBlockHandler(a){
    return new CommonResult(200."Customer custom tests ok".new Payment(2021L."serial003"));
}
Copy the code

Add flow control rules:

test

Access request: http://localhost:8401//rateLimit/customerBH, a second visit

Multiple access in one second, service limiting, return custom and self-selected traffic limiting information

9. Service fusing function

1. Integrate Ribbon

Service providers 9003 and 9004

1. Create two service provider modules:

cloudalibaba-provide-payment9003

cloudalibaba-provide-payment9004

The two modules are the same except for the port number.

2. Import POM dependencies

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

    <dependency>
        <groupId>com.cheng.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0 the SNAPSHOT</version>
    </dependency>

    <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>
    
</dependencies>
Copy the code

3. Write the YML configuration file

server:
  port: 9003 // Or 9004

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 Configure the address of Nacos
# expose endpoints
management:
  endpoints:
    web:
      exposure:
        include: The '*'
Copy the code

4. Main startup class

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003 {
    public static void main(String[] args) { SpringApplication.run(PaymentMain9003.class,args); }}Copy the code
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9004 {
    public static void main(String[] args) { SpringApplication.run(PaymentMain9004.class,args); }}Copy the code

5. Write business classes

@RestController
public class PaymentController {

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

    // Simulate data
    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> getPayment(@PathVariable("id") Integer id){
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200."from mysql serverport= " + serverPort, payment);
        returnresult; }}Copy the code

6, test,

Start the Cloudalibaba-provid-Payment9003 and Cloudalibaba-provid-Payment9004 modules

Access request: http://localhost:9003/paymentSQL/3

Access request: http://localhost:9004/paymentSQL/1

Service Consumers 84

1. Create cloudBaba-consumer-nacos-Order84 module

2. Import POM dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>

    <dependency>
        <groupId>com.cheng.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0 the SNAPSHOT</version>
    </dependency>
    <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>
    <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>
Copy the code

3. Write the YML configuration file

server:
  port: 84
spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  # NACOS Registry address
    sentinel:
      transport:
        dashboard: localhost:8080  #sentinel address, monitor 84
        port: 8719 The default port is 8719. If the port is occupied, the system will automatically scan from 8719 until the port is not occupied
Copy the code

4. Main startup class

@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain84{

    public static void main(String[] args) { SpringApplication.run(OrderNacosMain84.class, args); }}Copy the code

5. Write configuration classes to enable ribbon load balancing

@Configuration
public class ApplicationContextConfig{

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(a)
    {
        return newRestTemplate(); }}Copy the code

@sentinelResource Has no attributes

6. Write business classes

@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") // No configuration
    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 parameters abnormality...");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException, no record for this ID, NullPointerException");
        }

        return result;
}
Copy the code

Testing:

Access request: http://localhost:84/consumer/fallback/1, access is 9003

I’m going to do it again. I’m going to do 9004

After that, the ribbon will rotate between 9003 and 9004, implementing the ribbon polling load mechanism.

When we request to carry parameters other than 1,2,3, the corresponding Error page will appear,

@sentinelResource only adds the Fallback attribute

Add the fallback attribute to @SentinelResource and add methods to handle exceptions:

@RestController
@Slf4j
public class CircleBreakerController {
    public static final String SERVICE_URL = "http://nacos-payment-provider";
    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
     // Fallback only handles business exceptions
    @SentinelResource(value = "fallback",fallback = "handlerFallback") 
    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 parameters abnormality...");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException, no record for this ID, NullPointerException");
        }

        return result;
    }
    //fallback
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444."The exception content out abnormal handlerFallback,"+e.getMessage(),payment); }}Copy the code

To test whether the fallback method works:

Access request: http://localhost:84/consumer/fallback/4,

Access request: http://localhost:84/consumer/fallback/6

At this time, there is no Error Page, returned our custom exception information

@sentinelResource adds only the blockHandler attribute

@sentinelResource adds only the blockHandler property and adds the blockHandler method:

@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",blockHandler = "blockHandler") //blockHandler is only responsible for sentinel console configuration violations
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 parameters abnormality...");
    }else if (result.getData() == null) {
        throw new NullPointerException ("NullPointerException, no record for this ID, NullPointerException");
    }

    return result;
}
    //blockHandler
    public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445."Blockhander-sentinel Limiting flow, without this flow: blockException"+blockException.getMessage(),payment); }}Copy the code

Configure reversion rules on the Sentinel console:

Within one minute, if the number of requests is greater than 5 and the number of exceptions is greater than 3, service degradation is triggered.

test

Access request: http://localhost:84/consumer/fallback/4 and http://localhost:84/consumer/fallback/6 each one:

Abnormal page

Continued access request: http://localhost:84/consumer/fallback/4 and http://localhost:84/consumer/fallback/6, after more than three times:

Trigger degradation rules, service fuses, and return custom processing information.

@sentinelResource adds both blockHandler and Fallback properties

@sentinelResource adds the blockHandler and Fallback attributes, and the corresponding handling methods:

@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",blockHandler = "blockHandler")
    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 parameters abnormality...");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException, no record for this ID, NullPointerException");
        }

        return result;
    }
    //fallback
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444."The exception content out abnormal handlerFallback,"+e.getMessage(),payment);
    }
    //blockHandler
    public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445."Blockhander-sentinel Limiting flow, without this flow: blockException"+blockException.getMessage(),payment); }}Copy the code

Configure the Sentinel flow control rule:

test

A second visit a request: http://localhost:84/consumer/fallback/4, because the QPS not greater than 1, so there is no damage sentinel current-limiting rules, so it is returned to fallback exception information.

However, if the number of accesses in a second is greater than 1, the traffic limiting rule of Sentinel is broken and the exception information processed by blockHandler is returned

Conclusion: If blockHandler and Fallback are configured, only the blockHandler processing logic is entered when a BlockException is thrown due to traffic limiting demotion.

ExceptionsToIgnore properties

Use the exceptionsToIgnore attribute in the @SentinelResource annotation:

exceptionsToIgnore = {IllegalArgumentException.class} // Multiple configurations can be configured
Copy the code

With exceptionsToIgnore, IllegalArgumentException will not be handled by the Fallback method and will return an Error Page.

2. Integrate OpenFeign

1. Add openFeign dependency to cloudBaba-consumer-nacos-Order84 module:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Copy the code

2. Add the following configuration to the yML configuration file of module 84:

feign:
  sentinel:
    enabled: true  # Activate Sentinel support for Feign
Copy the code

3. Add the @enableFeignClients annotation to the main startup class

4. Write feIGN interface

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);

}
Copy the code

5. Write global degradation methods

@Component
public class PaymentFallbackService implements PaymentService{

    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(444."Abnormal service degraded by PaymentFallbackService".new Payment(id,"error")); }}Copy the code

Fallback needs to be configured in @feignClient.

6. Call the service with OpenFeign in Controller

@Resource
private PaymentService paymentService;

@GetMapping(value = "/consumer/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
    return paymentService.paymentSQL(id);
}
Copy the code

7, test,

Access request: http://localhost:84/consumer/paymentSQL/1

Visit again

Close service, 9003 and 9004 access request again: http://localhost:84/consumer/paymentSQL/1

Handled by the global degrade method.

3. Comparison of fuse breaker frames

10. Rule persistence

In the above case, if the service is shut down, the flow control rules corresponding to the service will also disappear. Each time the service is restarted, the rules need to be reconfigured, which is clearly not true to development needs. So I need to persist the configuration rules.

Persisting scheme: The flow limiting configuration rules are persisted in Nacos. As long as a REST address of module 8401 is refreshed, the flow control rules of Sentinel console can be seen. As long as the configuration in Nacos is not deleted, the flow control rules for Sentinel on 8401 continue to be valid.

1. Add POM dependency to module 8401:

<! -- Persistent -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
Copy the code

2. Add the NACOS data source configuration to the YML configuration file

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848  # nacOS service center address
    sentinel:
      transport:
        dashboard: localhost:8080  # configure Sentinel Dashboard address to monitor 8401 via 8080
        port: 8719 The default port is 8719. If the port is occupied, the system will automatically scan from 8719 until the port is not occupied
      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: The '*'
Copy the code

3. Add the business rule configuration in NACOS

Configuration description:

Resource: indicates the name of the resource.

LimitApp: Source app;

Grade: indicates the threshold type. 0 indicates the number of threads and 1 indicates QPS.

Count: single-node threshold.

Strategy: Flow control mode, o 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: Indicates whether to cluster.

4, test,

Disable the 8401 service to see if there are any flow control rules in Sentinel:

The flow control rules are gone.

Then restart the 8401 service. There is no flow control rule in Sebtinel.

When we visit a http://localhost:8401/rateLimit/byUrl request, sentinel surveillance to/rateLimit/byUrl, flow control rules automatically: