08.Sentinel整合Spring Cloud

一、项目配置

1.父亲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 https://maven.apache.org/xsd/maven-4.0.0.xsd">


    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.luoruiyuan</groupId>
    <artifactId>Spring-Cloud-Lry</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Spring-Cloud-Lry</name>
    <description>Spring-Cloud-Lry</description>
    <packaging>pom</packaging>

    <modules>
        <module>stock</module>
        <module>order</module>
        <module>nacos-config</module>
        <module>sentinel-java</module>
        <module>order-sentinel</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <spring.boot.version>2.3.12.RELEASE</spring.boot.version>
        <spring.cloud.version>Hoxton.SR12</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.8.RELEASE</spring.cloud.alibaba.version>
    </properties>

    <!-- 版本管理(子工程引入了才会导jar包) -->
    <dependencyManagement>
        <dependencies>

            <dependency>
                <!--Spring Boot 版本管理-->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


            <!--Spring Cloud 版本管理-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--Spring Cloud Alibaba 版本管理-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>



    <!-- 直接导入jar包 -->
    <dependencies>
        <!--  Spring Boot启动器  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!--  测试  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--  WEB场景  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--  开发工具  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

</project>

2.子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>Spring-Cloud-Lry</artifactId>
        <groupId>cn.luoruiyuan</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-sentinel</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>


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

    </dependencies>

</project>

2.配置文件

server:
  port: 8001


spring:
  #应用名
  application:
    name: OrderSentinel
  #热部署
  devtools:
    restart:
      enabled: true
  #sentinel服务端IP,端口
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:9908

3.controller

package cn.luoruiyuan.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author LRY
 * @date 2022/8/6
 */
@RestController
public class OrderSentinelController {

    @RequestMapping("/order")
    public String order(){
        return "订单访问";
    }
}

4.控制台添加规则



5.一秒内访问两次以上就会被流控


二、异常处理

1.默认异常


2.通过@SentinelResource注解给单方法添加异常内容

/**
 * @author LRY
 * @date 2022/8/6
 */
@RestController
public class OrderSentinelController {

    @RequestMapping("/order")
    @SentinelResource(value = "order",blockHandler = "blockHandlerForOrder")
    public String order(){
        return "订单访问";
    }

    @RequestMapping("/orderA")
    @SentinelResource(value = "orderA",blockHandler = "blockHandlerForOrder")
    public String orderA(){
        return "订单访问A";
    }

    public String blockHandlerForOrder(BlockException e){
        return "访问被流控";
    }

}

给资源名添加规则


访问就会显示自定义的错误信息了


3.统一异常处理

异常处理类

package cn.luoruiyuan.exception;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author LRY
 * @date 2022/8/6
 */
@Component
@Slf4j
public class MyBlockExceptionHandler implements BlockExceptionHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        log.info("=====================规则详细信息:"+e.getRule().toString());

        //在 BlockException 类上面按 F4 可以看到所有实现类
        //返回类型
        String str="";
        if(e instanceof FlowException){
            str="流控了";
        }else if(e instanceof DegradeException){
            str="降级了";
        }else if(e instanceof ParamFlowException){
            str="热点参数限流";
        }else if(e instanceof AuthorityException){
            str="授权规则不通过";
        }else if(e instanceof SystemBlockException){
            str="触发系统保护规则";
        }

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

}

controller

package cn.luoruiyuan.controller;

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

/**
 * @author LRY
 * @date 2022/8/6
 */
@RestController
@RequestMapping("order")
public class OrderSentinelController {

    @RequestMapping("/add")
    public String add(){
        return "添加订单";
    }

    @RequestMapping("/get")
    public String get(){
        return "查询订单";
    }

}

规则设置,并访问



三、规则说明

1.流控

【流控模式】

1)关联


说明:/order/add 一秒访问1次以上,/order/get就会被流控

20220806_143130

2)链路

说明:多个地址去访问一个资源,只限制其中一个。

修改配置文件“web-context-unify: false”

server:
  port: 8001


spring:
  #应用名
  application:
    name: OrderSentinel
  #热部署
  devtools:
    restart:
      enabled: true
  #sentinel服务端IP,端口
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:9908
      #默认为true没有维护链路
      web-context-unify: falseb

controllern

package cn.luoruiyuan.controller;

import cn.luoruiyuan.service.OrderSentinelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author LRY
 * @date 2022/8/6
 */
@RestController
@RequestMapping("order")
public class OrderSentinelController {

    @Autowired
    private OrderSentinelService service;

    @RequestMapping("/list1")
    public String list1(){
        return service.getList("1");
    }

    @RequestMapping("/list2")
    public String list2(){
        return service.getList("2");
    }

}

service

package cn.luoruiyuan.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;

/**
 * @author LRY
 * @date 2022/8/6
 */
@Service
public class OrderSentinelService {

    @SentinelResource(value = "list",blockHandler ="blockHandlerForGetList" )
    public String getList(String str){
        return "List:"+str;
    }

    public String blockHandlerForGetList(String str, BlockException e){
        return "List:"+str+". 被流控了.";
    }

}

访问


【流控效果】

1)预热


说明:阈值为30,并不是一下就能接受30个请求,而是在10秒后接受30个请求,10秒内接受的请求是递增的效果进行接受,如下图:


2)等待


说明:比较适合洪峰流量(如下图),一秒超过10下一秒没有流量,就可以让超过的流动等待2000毫秒,然后进行处理。


2.熔断

1)慢调用比例  

让服务休眠1秒


降级规则


说明:在1000毫秒内,10个请求调用时长大于200毫秒的数量占比为1%就进行熔断10秒,10秒后进入半开状态,如果接下来的第一次请求再慢于200毫秒就直接熔断,不会按照条件进行判断。


2)异常比例 


说明:在10000毫秒内,10个请求有1%报错就熔断10秒,10后进入半开状态。

3)异常数


说明:10000毫秒内,10个请求有1个请求报错就熔断10秒,10秒后进入半开状态,如果在调用失败一次就直接熔断,不会按照设定的条件进行判断。

3.热点

热点异常使用@SentinelResource方式

@RestController
@RequestMapping("order")
public class OrderSentinelController {

    @Autowired
    private OrderSentinelService service;

    @RequestMapping("/list/{id}")
    public String list(@PathVariable("id") String id){
        return service.getList(id);
    }


}
@Service
public class OrderSentinelService {

    @SentinelResource(value = "list",blockHandler ="blockHandlerForGetList" )
    public String getList(String str){
        return "List:"+str;
    }


    public String blockHandlerForGetList(String str, BlockException e){
        return "List:"+str+". 热点异常处理.";
    }

}

要在资源上面添加热点


要先新增然后去修改,才有高级部分


说明:普通限流是一秒5次,第0个参数为1(字符串类型)的资源限流一秒2次。

4.系统


说明:CPU占用率到达20%就进行处理



(1)