SpringCloud-Sentinel

1. Introduction

(1) Provide interface configuration to configure service current limiting, service degradation, and service circuit breaker
(2) The blockHandler of @SentinelResource only handles exceptions configured in the background. Runtime exception fallBack processing takes effect only when the resource name is value. Take a thorough approach.

2. Install and start sentinel

(1) Official website
(2) Run java -jar sentinel-dashboard-1.8.6.jar
(3) Visit http://localhost:8080/

Note: sentinel is lazy loaded and will only be displayed after accessing the interface.

3. Building the project

(1) Write pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo20220821</artifactId>
        <groupId>com.wsh.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloudalibaba-sentinel-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.wsh.springcloud</groupId>
            <artifactId>cloud-api-common</artifactId>
            <version>1.0-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.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

(2)Write application.yml

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719


management:
  endpoints:
    web:
      exposure:
        include: "*"

(3) Write startup class

package com.wsh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @ClassName SentinelService8401
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelService8401 {<!-- -->
    public static void main(String[] args) {<!-- -->
        SpringApplication.run(SentinelService8401.class, args);
    }
}

(4)Write Controller

package com.wsh.springcloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName TestController
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
@RestController
public class TestController {<!-- -->

    @GetMapping("/test")
    public String test(){<!-- -->
        return "test";
    }
}

4. Service current limit

(1) Open the interface

(2) Threshold
QPS: requests per second
Number of concurrent threads: the number of threads processing requests

(3) Association

/test exploded, /test1 also exploded

(4) Preheating, the threshold starts from threshold/3 and gradually increases within the preheating time (unit: seconds)

(5) Waiting in queue, the threshold type must be set to QPS, requests exceeding the threshold will be queued, and the waiting timeout is set to 20 seconds

5. Service downgrade

(1) After meeting the conditions, the service will be disconnected within the specified time
(2) Slow call ratio

(3) Abnormal proportion

(4) Number of exceptions

6. Hotspot parameter current limiting

(1) Use @SentinelResource to define resource names and cover-up methods

 @GetMapping("/test2")
    @SentinelResource(value = "test2", blockHandler = "test2_solve")
    public String test2(@RequestParam("name") String name) {<!-- -->
        log.info("test2");
        return "test2";
    }
    public String test2_solve(String name, BlockException blockException){<!-- -->
        return "block";
    }

(2)

(3) Specify the value of the parameter when defining the rule

7. Optimization of the writing method of the bottom-up method

(1)

 @GetMapping("/test3")
    @SentinelResource(value = "test3", blockHandlerClass = BlockHandler.class, blockHandler = "test3_solve")
    public String test3() {<!-- -->
        log.info("test3");
        return "test3";
    }

(2) Write BlockHandler class

package com.wsh.springcloud.handler;

import com.alibaba.csp.sentinel.slots.block.BlockException;

/**
 * @ClassName BlockHandler
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
public class BlockHandler {<!-- -->

    public static String test3_solve(BlockException blockException){<!-- -->
        return "block";
    }
}

(3)

8. Configure fallback and blockHandler

(1) exceptionsToIgnore is used to ignore exceptions without using fallback

 @GetMapping("/test3")
    @SentinelResource(value = "test3", blockHandlerClass = BlockHandler.class, blockHandler = "test3_solve",
    fallbackClass = FallBackHandler.class, fallback = "test3_solve1",
    exceptionsToIgnore = NullPointerException.class)
    public String test3(@RequestParam("name") String name) {<!-- -->
        if (name.equals("wsh")){<!-- -->
            throw new IllegalArgumentException();
        }
        return "test3";
    }

(2)

public class BlockHandler {<!-- -->

    public static String test3_solve(String name, BlockException blockException){<!-- -->
        return "block";
    }
}
public class FallBackHandler {<!-- -->

    public static String test3_solve1(String name, Throwable throwable){<!-- -->
        return "block1";
    }
}

9. Configure openFeign

(1) Write pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>demo20220821</artifactId>
        <groupId>com.wsh.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloudalibaba-consumer-order84</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.wsh.springcloud</groupId>
            <artifactId>cloud-api-common</artifactId>
            <version>1.0-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.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

(2)Write application.yml

server:
  port: 84

spring:
  application:
    name: cloudalibaba-consumer-order
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: "*"

server-url: http://cloudalibaba-provider-payment

Feign:
  sentinel:
    enabled: true

(3) Write startup class

package com.wsh.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @ClassName ConsumerOrder84
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class ConsumerOrder84 {<!-- -->
    public static void main(String[] args) {<!-- -->
        SpringApplication.run(ConsumerOrder84.class, args);
    }
}

(4)Write PaymentService

package com.wsh.springcloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @ClassName PaymentService
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
@FeignClient(value = "cloudalibaba-provider-payment", fallback = PaymentServiceHandler.class)
public interface PaymentService {<!-- -->

    @GetMapping("/payment/test")
    public String test();
}

(5) Write fallback class

package com.wsh.springcloud.service;

import org.springframework.stereotype.Component;

/**
 * @ClassName PaymentServiceHandler
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
@Component
public class PaymentServiceHandler implements PaymentService{<!-- -->
    @Override
    public String test() {<!-- -->
        return "fallback";
    }
}

(6)Write Controller

package com.wsh.springcloud.controller;

import com.wsh.springcloud.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName TestController
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/19
 * @Version V1.0
 **/
@RestController
public class TestController {<!-- -->

    @Autowired
    private PaymentService paymentService;

    @GetMapping("/consumer/test")
    public String test(){<!-- -->
        return paymentService.test();
    }
}

(7) Write service provider Controller

package com.wsh.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName TestController
 * @Description: TODO
 * @Author wshaha
 * @Date 2023/10/18
 * @Version V1.0
 **/
@RestController
public class TestController {<!-- -->

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

    @GetMapping("/payment/test")
    public String test(){<!-- -->
        int i = 1 / 0;
        return "test: " + port;
    }
}

(8) Run

10. Configuration persistence

(1) Persisting the rules to nacos will only be effective if they are written in nacos first.
(2) Add dependencies to pom.xml

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

(3) Modify application.yml

 sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719
      datasource:
        dsl:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

(4) Create configuration in nacos

[
    {<!-- -->
        "resource": "/consumer/test",
        "limitApp": "default",
        "grade": "1",
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]