# 从浅入深 学习 SpringCloud 微服务架构(八)Sentinel(2)

从浅入深 学习 SpringCloud 微服务架构(八)Sentinel(2)

一、sentinel:通用资源保护

1、Rest 实现熔断

Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,

在构造 RestTemplate bean 的时候需要加上 @sentinelRestTemplate 注解。

2、修改 order_service_rest 子工程(子模块)的 Controller 方法,添加降级方法:

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_rest\src\main\java\djh\it\order\controller\OrderController.java
 *
 *  2024-5-5 订单的 controller 类 OrderController.java
 */
package djh.it.order.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import djh.it.order.domain.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

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

    @Autowired  //注入 restTemplate 对象
    private RestTemplate restTemplate;

    @SentinelResource(blockHandler = "orderBlockHandler", fallback = "orderFallback")
    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        if(id != 1){
            throw new RuntimeException("错误");
        }
        Product product = null;
        product = restTemplate.getForObject("http://service-product/product/1", Product.class);
        return product;
    }

    /**
     *  定义降级逻辑:sentinel 不同于 hystrix
     *      需要分别定义 熔断执行的降级方法和抛出异常执行的降级方法。
     */
    public Product orderBlockHandler(Long id){
        Product product = new Product();
        product.setProductName("触发熔断--的降级方法");
        return product;
    }
    public Product orderFallback(Long id){
        Product product = new Product();
        product.setProductName("抛出异常执行--的降级方法");
        return product;
    }
}

3、重新运行 order_service_rest 子工程(子模块)的启动类,进行测试:

浏览器地址栏输入:localhost:8086 登录 Sevtinel 控制台,进行设置

注意:需要 浏览器地址栏输入:localhost:9003/order/buy/1 访问请求, Sevtinel 控制台才会有服务名

(因为 Sentinel 默认是懒加载)

1)点击右侧 【service-order-rest】 服务名,再点击【簇点链路】,

会显示出 请求的方法名,

2)点击方法名(如:djh.it.order.controller.OrderController:findById(java.lang.Long))后面的【降级】

新增【降级】规则

降级策略:如:勾选【异常数】

异常数:如:(1) 时间窗口:如:(5)

点击【新增】。

3)浏览器地址栏输入正确请求:localhost:9003/order/buy/1

错误请求:localhost:9003/order/buy/2 多刷新几次,测试熔断方法执行情况。



4)等待 5 秒,输入正确请求访问又正常了 localhost:9003/order/buy/1

二、sentinel:加载本地配置

1、@SentinelResource 注解,可以用 value 属性,指定资源名称。

2、修改 order_service_rest 子工程(子模块)的 Controller 方法,添加 @SentinelResource 注解的 value 属性,指定资源名称。

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_rest\src\main\java\djh\it\order\controller\OrderController.java
 *
 *  2024-5-5 订单的 controller 类 OrderController.java
 */
package djh.it.order.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import djh.it.order.domain.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

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

    @Autowired  //注入 restTemplate 对象
    private RestTemplate restTemplate;

    /**
     * @SentinelResource 注解属性
     *      blockHandler : 声明熔断时调用的降级方法。
     *      fallback : 抛出异常执行的降级方法。
     *      value : 自定义的资源名称,如果不设置,默认为当前全类名.方法名。
     */
    @SentinelResource(value = "orderFindByid", blockHandler = "orderBlockHandler", fallback = "orderFallback")
    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        if(id != 1){
            throw new RuntimeException("错误");
        }
        Product product = null;
        product = restTemplate.getForObject("http://service-product/product/1", Product.class);
        return product;
    }

    /**
     *  定义降级逻辑:sentinel 不同于 hystrix
     *      需要分别定义 熔断执行的降级方法和抛出异常执行的降级方法。
     */
    public Product orderBlockHandler(Long id){
        Product product = new Product();
        product.setProductName("触发熔断--的降级方法");
        return product;
    }
    public Product orderFallback(Long id){
        Product product = new Product();
        product.setProductName("抛出异常执行--的降级方法");
        return product;
    }
}

3、一条限流规则主要由下面几个因素组成:

resource: 资源名,即限流规则的作用对象

count: 限流阈值

grade: 限流阈值类型( QPs或并发线程数 )

limitapp: 流控针对的调用来源,若为 default 则不区分调用来源。

strategy: 调用关系限流策略

controlBehavior: 流量控制效果( 直接拒绝、warm up、匀速排队 )。

4、可以在项目的 application.yml 配置文件中,添加如下配置,来读取本地配置资源文件。

#通过文件读取限流规则

spring.cloud.sentinel.datasource.dsl.file.file=classpath:flowrule.json

spring.cloud.sentinel.datasource.dsl.file.data-type=json

spring.cloud.sentinel.datasource.dsl.file.rule-type=flow

5、修改 order_service_rest 子工程(子模块)的 application.yml 配置,添加读取本地资源配置文件的配置。

复制代码
##  spring_cloud_sentinel_demo\order_service_rest\src\main\resources\application.yml

server:
  port: 9003  # 启动端口 命令行注入。
#  port: ${port:9003}  # 启动端口设置为动态传参,如果未传参数,默认端口为 9003

spring:
  application:
    name: service-order_rest  #spring应用名, # 注意 FeignClient 不支持名字带下划线
#  main:
#    allow-bean-definition-overriding: true # SpringBoot2.1 需要设定。
  datasource:
    driver-class-name: com.mysql.jdbc.Driver  # mysql 驱动
    url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    # MySQL8.0 可以写成  root, 012311 或  'root', '012311'   # MySQL5.7 只能写成 'root', '012311'  # 注意用户名和密码后一定不能有空格。
    username: 'root'
    password: '12311'
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
  cloud:   # 配置 sentinel 服务熔断
    sentinel:
      transport:
        dashboard: localhost:8086  # sentienl 控制台的请求地址。
      datasource:
        ds1:
          file:
            file: classpath:flowrule.json
            data-type: json
            rule-type: flow

eureka:  # 配置 Eureka
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/  # 多个 eurekaserver 用 , 隔开。
  instance:
    prefer-ip-address: true  # 使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

6、在 order_service_rest 子工程(子模块)的 Resource 资源根目录下,创建 加载本地 Sentinel 设置的文件 flowrule.json 。

复制代码
[
	{
		"resource": "orderFindById",
		"controlBehavior": 0,
		"count": 1,
		"grade": 1,
		"limitApp": "default",
		"strategy": 0
	}
]

7、重新运行 order_service_rest 子工程(子模块)的启动类,进行测试:

1)浏览器地址栏输入:localhost:8086 登录 Sevtinel 控制台

2)览器地址栏输入:localhost:9003/order/buy/1 访问请求, Sevtinel 控制台

3)localhost:8086 登录 Sevtinel 控制台

点击右侧 【service-order-rest】 服务名,再点击【簇点链路】,会发现已经加载到配置的资源名称了。

三、sentinel:对 resttemplate 的支持

1、修改 order_service_rest 子工程(子模块)的 Controller 方法,注销掉服务降级的方法。

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_rest\src\main\java\djh\it\order\controller\OrderController.java
 *
 *  2024-5-5 订单的 controller 类 OrderController.java
 */
package djh.it.order.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import djh.it.order.domain.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

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

    @Autowired  //注入 restTemplate 对象
    private RestTemplate restTemplate;

    /**
     *  @SentinelResource 注解属性
     *      blockHandler : 声明熔断时调用的降级方法。
     *      fallback : 抛出异常执行的降级方法。
     *      value : 自定义的资源名称,如果不设置,默认为当前全类名.方法名。
     *
     *   启动类,添加 @SentinelRestTemplate 注解时(sentinel:对 resttemplate 的支持):
     *      就不需要添加 @SentinelResource 注解和降级方法了。
     */
//    @SentinelResource(value = "orderFindByid", blockHandler = "orderBlockHandler", fallback = "orderFallback")
    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        if(id != 1){
            throw new RuntimeException("错误");
        }
        Product product = null;
        product = restTemplate.getForObject("http://service-product/product/1", Product.class);
        return product;
    }

//    /**
//     *  定义降级逻辑:sentinel 不同于 hystrix
//     *      需要分别定义 熔断执行的降级方法和抛出异常执行的降级方法。
//     */
//    public Product orderBlockHandler(Long id){
//        Product product = new Product();
//        product.setProductName("触发熔断--的降级方法");
//        return product;
//    }
//    public Product orderFallback(Long id){
//        Product product = new Product();
//        product.setProductName("抛出异常执行--的降级方法");
//        return product;
//    }
}

2、修改 order_service_rest 子工程(子模块)的 启动类,添加 @SentinelRestTemplate 注解。

复制代码
/**
 *    spring_cloud_sentinel_demo\order_service_rest\src\main\java\djh\it\order\OrderApplication.java
 *
 *   2024-5-5  启动类 OrderApplication.java
 */
package djh.it.order;

import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
//import org.apache.tomcat.util.ExceptionUtils;
import djh.it.order.exception.ExceptionUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
//import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EntityScan("djh.it.order.domain")
@EnableEurekaClient  //激活 EurekaClient,同 @EnableDiscoveryClient 注解相同。
//@EnableFeignClients  //激活 Feign
@EnableCircuitBreaker  // 2)激活 hystrix,  Hystrix 组件 对 RestTemplate 的支持4步:
@EnableHystrixDashboard  // 激活 Hystrix 基于图形化的 DashBoard(仪表板)监控平台
public class OrderApplication {
    /**
     *  启动类,添加 @SentinelRestTemplate 注解时(sentinel:对 resttemplate 的支持):
     *      Controller 类 就不需要添加 @SentinelResource 注解和降级方法了。
     *
     *   资源名:
     *      httpmethod:schema://host:port/path : 协议、主机、端口和路径。
     *      httpmethod:schema://host:port : 协议、主机和端口。
     *
     *   @SentinelRestTemplate 注解:
     *      异常降级:
     *          fallback      : 降级方法
     *          fallbackClass : 降级配置类。
     *      限流熔断:
     *          blockHandler
     *          blockHandlerClass
     */

    @LoadBalanced
    @Bean
    @SentinelRestTemplate(fallbackClass = ExceptionUtils.class, fallback = "handlerFallback",
            blockHandler = "handleBlock", blockHandlerClass = ExceptionUtils.class)
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

3、在 order_service_rest 子工程(子模块)创建 定义一个类和静态方法 ExceptionUtils.java

复制代码
/**
 *  spring_cloud_sentinel_demo\order_service_rest\src\main\java\djh\it\order\exception\ExceptionUtils.java
 *
 *   定义一个类和静态方法 ExceptionUtils.java
 */

package djh.it.order.exception;

import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import djh.it.order.domain.Product;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;

public class ExceptionUtils {
    /**
     *  静态方法
     *      返回值: SentinelClientHttpResponse
     *      参数: request,byte[],clientRquestExcetion,blockException
     */

    //限流熔断业务逻辑
    public static SentinelClientHttpResponse handleBlock ( HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex){
//        System.err.println("0ops: " + ex.getClass().getCanonicalName());
//        return new SentinelClientHttpResponse( "限流熔断降级");

        Product product = new Product();
        product.setProductName("block");
        return new SentinelClientHttpResponse(JSON.toJSONString(product));
    }

    //异常降级业务逻辑
    public static SentinelClientHttpResponse handlerFallback(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex){
//        System.err.println("fallback: " + ex.getClass().getCanonicalName());
//        return new SentinelClientHttpResponse( "异常熔断降级");

        Product product = new Product();
        product.setProductName("Fallback");
        return new SentinelClientHttpResponse(JSON.toJSONString(product));
    }

}

4、修改 order_service_rest 子工程(子模块)的 application.yml 文件,添加 sentinel 立即加载。

复制代码
##  spring_cloud_sentinel_demo\order_service_rest\src\main\resources\application.yml

server:
  port: 9003  # 启动端口 命令行注入。
#  port: ${port:9003}  # 启动端口设置为动态传参,如果未传参数,默认端口为 9003

spring:
  application:
    name: service-order_rest  #spring应用名, # 注意 FeignClient 不支持名字带下划线
#  main:
#    allow-bean-definition-overriding: true # SpringBoot2.1 需要设定。
  datasource:
    driver-class-name: com.mysql.jdbc.Driver  # mysql 驱动
    url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    # MySQL8.0 可以写成  root, 012311 或  'root', '012311'   # MySQL5.7 只能写成 'root', '012311'  # 注意用户名和密码后一定不能有空格。
    username: 'root'
    password: '12311'
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
  cloud:   # 配置 sentinel 服务熔断
    sentinel:
      transport:
        dashboard: localhost:8086  # sentienl 控制台的请求地址。
      datasource:
        ds1:
          file:
            file: classpath:flowrule.json
            data-type: json
            rule-type: flow
      eager: true  # 立即加载

eureka:  # 配置 Eureka
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/  # 多个 eurekaserver 用 , 隔开。
  instance:
    prefer-ip-address: true  # 使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

# 配置 feign 日志的输出。
# 日志配置:NONE:GI 不输出日志,BASIC:适用于生产环境追踪问题,HEADERS:在BASIC基础上,记录请求和响应头信息,FULL:记录所有。
logging:
  level:
    djh.it.order.feign.ProductFeignClient: debug

#feign:
#  client:
#    config:
#      default:
#        connectTimeout: 5000   #服务之间建立连接所用的时间  #不设置 connectTimeout 会导致 readTimeout 设置不生效
#        readTimeout: 5000   #建立连接后从服务端读取到数据用的时间
#      service-product:  # 需要调用的服务名称
#        loggerLevel: FULL
#  hystrix:  # 开启对 hystrix 的支持。
#    enabled: true

#hystrix:  # 配置 hystrix 熔断(Hystrix:基于 RestTemplate 的统一降级配置)
#  command:
#    default:
#      execution:
#        isolation:
#          thread:
#            timeoutInMilliseconds: 5000  # 默认的熔断超时时间为1 秒,若1秒没有返回数据,会自动触发降级逻辑。
#      circuitBreaker:
#        requestVolumeThreshold: 5  # 触发熔断的最小请求次数,默认 20 次/秒。
#        sleepWindbwInMilliseconds: 10000  # 熔断多少秒后去尝试请求。默认打开状态的时间是 5秒
#        errorThresholdPercentage: 50  # 触发熔断的失败请求最小占比,默认 50%
#management:   # 配置 Actuator 获取 hystrix 的监控数据 暴躁端点。
#  endpoints:
#    web:
#      exposure:
#        include: '*'   # 暴露所有端点。

5、重新运行 order_service_rest 子工程(子模块)的启动类,进行测试:

1)浏览器地址栏输入:localhost:8086 登录 Sevtinel 控制台

2)览器地址栏输入:localhost:9003/order/buy/1 访问请求, Sevtinel 控制台

3)localhost:8086 登录 Sevtinel 控制台

点击右侧 【service-order-rest】 服务名,再点击【簇点链路】,会发现已经加载到配置的资源名称了。

4)设置【流量控制】

如:点击一个资源名称( GET:http://service-product/product/1

点击后面的【+流控】

阀值类型:勾选 (QPS)

单机阀值:(1)

点击 【新增】。

5)配置好【流量控制】后,再次刷新请求页面 localhost:9003/order/buy/1

发现点击刷新页面慢时,正常显示,点击快时,就会触发熔断保护方法。

四、sentinel:对 feign 的支持

1、修改 order_service_feign 子工程(子模块)的 pom.xml 文件,添加 sentinel 依赖坐标。

复制代码
<?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_sentinel_demo</artifactId>
        <groupId>djh.it</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order_service_feign</artifactId>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!--            <version>5.1.32</version>-->
            <version>8.0.26</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- 导入 eureka 注册中心 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- springcloud 整合 openFeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- Hystrix 组件 对 RestTemplate 的支持4步:1)引入 Hystrix 依赖坐标 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!-- 引入 hystrix 的监控信息 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <!-- 引入 sentinel 熔断 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<!--            <version>2.0.0.RELEASES</version>-->
        </dependency>
    </dependencies>
</project>
<!--  idea2019\spring_cloud_sentinel_demo\order_service_feign\pom.xml -->

2、修改 order_service_feign 子工程(子模块)的 application.yml 文件,添加 开启 sentinel 支持。

复制代码
##  spring_cloud_sentinel_demo\order_service_feign\src\main\resources\application.yml

server:
  port: 9002  # 启动端口 命令行注入。
#  port: ${port:9002}  # 启动端口设置为动态传参,如果未传参数,默认端口为 9002

spring:
  application:
    name: service-order_feign  #spring应用名, # 注意 FeignClient 不支持名字带下划线
#  main:
#    allow-bean-definition-overriding: true # SpringBoot2.1 需要设定。
  datasource:
    driver-class-name: com.mysql.jdbc.Driver  # mysql 驱动
    url: jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    # MySQL8.0 可以写成  root, 012311 或  'root', '012311'   # MySQL5.7 只能写成 'root', '012311'  # 注意用户名和密码后一定不能有空格。
    username: 'root'
    password: '12311'
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
  cloud:   # 配置 sentinel 服务熔断
    sentinel:
      transport:
        dashboard: localhost:8086  # sentienl 控制台的请求地址。

feign:   # 激活 sentinel 的支持
  sentinel:
    enabled: true

eureka:  # 配置 Eureka
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/  # 多个 eurekaserver 用 , 隔开。
  instance:
    prefer-ip-address: true  # 使用 ip 地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

3、修改 order_service_feign 子工程(子模块)的 接口类,配置 FeignClient。

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_feign\src\main\java\djh\it\order\feign\ProductFeignClient.java
 *
 *   2024-5-5  创建 调用 feign 组件的接口类 ProductFeignClient.java
 *   声明需要调用的微服务名称 @FeignClient, name: 服务提供者的名称, fallback:配置熔断发生的降级方法。
 */

package djh.it.order.feign;

import djh.it.order.domain.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name="service-product", fallback = ProductFeignClientCallBack.class)  //调用 FeignClient 并添加降级方法的支持
public interface ProductFeignClient {
    //配置需要调用的微服务接口
    @RequestMapping(value = "/product/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable("id") Long id);
}

4、在 order_service_feign 子工程(子模块)创建 接口的 实现类,配置熔断方法。

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_feign\src\main\java\djh\it\order\feign\ProductFeignClientCallBack.java
 *
 *   2024-5-5  创建 feign 组件的接口类 ProductFeignClient 的实现类 ProductFeignClientCallBack.java
 *   配置熔断触发的降级逻辑。
 */

package djh.it.order.feign;

import djh.it.order.domain.Product;
import org.springframework.stereotype.Component;

@Component
public class ProductFeignClientCallBack implements ProductFeignClient{
    // 熔断降级的方法
    public Product findById(Long id) {
        Product product = new Product();
        product.setProductName("hystrix:基于 feign 调用的熔断配置 -- feign 调用触发熔断降级的方法。");
        return product;
    }
}

5、order_service_feign 子工程(子模块)的 商品 类。

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_feign\src\main\java\djh\it\order\domain\Product.java
 *
 *  2024-5-5  商品实体类 Product.java
 */
package djh.it.order.domain;

import lombok.Data;
import java.math.BigDecimal;

@Data
public class Product {

    private Long id;
    private String productName;
    private Integer status;
    private BigDecimal price;
    private String productDesc;
    private String caption;
    private Integer inventory;
}

6、order_service_feign 子工程(子模块)的 Controller 类。

复制代码
/**
 *   spring_cloud_sentinel_demo\order_service_feign\src\main\java\djh\it\order\controller\OrderFeignController.java
 *
 *  2024-5-5 订单的 controller 类 OrderFeignController.java
 */
package djh.it.order.controller;

import djh.it.order.domain.Product;
import djh.it.order.feign.ProductFeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@RequestMapping("/order")
public class OrderFeignController {

    @Resource    //按类型名称注入 调用 feign 组件的接口类 ProductFeignClient
    //@Autowired   //自动注入 调用 feign 组件的接口类 ProductFeignClient //有时变量名报红,可替换为 @Resource 注解
    private ProductFeignClient productFeignClient;

    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        Product product = null;
       //调用 feign 组件的接口类 的方法
        product = productFeignClient.findById(id);
        return product;
    }
}

7、order_service_feign 子工程(子模块)的 启动 类。

复制代码
/**
 *    spring_cloud_sentinel_demo\order_service_feign\src\main\java\djh\it\order\OrderFeignApplication.java
 *
 *   2024-5-5  启动类 OrderFeignApplication.java
 */
package djh.it.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EntityScan("djh.it.order.domain")
@EnableEurekaClient  //激活 EurekaClient,同 @EnableDiscoveryClient 注解相同。
@EnableFeignClients  //激活 Feign
public class OrderFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignApplication.class, args);
    }
}

8、重新运行 order_service_feign 子工程(子模块)的启动类,进行测试:

1)浏览器地址栏输入:localhost:8086 登录 Sevtinel 控制台

2)览器地址栏输入:localhost:9002/order/buy/1 访问请求, Sevtinel 控制台

3)localhost:8086 登录 Sevtinel 控制台

点击右侧 【service-order-feign】 服务名,再点击【簇点链路】,会发现已经加载到配置的资源名称了。

4)设置【流量控制】

如:点击一个资源名称( GET:http://service-product/product/1

点击后面的【+流控】

阀值类型:勾选 (QPS)

单机阀值:(1)

点击 【新增】。

5)配置好【流量控制】后,再次刷新请求页面 localhost:9002/order/buy/1

发现点击刷新页面慢时,正常显示,点击快时,就会触发熔断保护方法。

上一节链接请点击 :

# 从浅入深 学习 SpringCloud 微服务架构(八)Sentinel(1)

相关推荐
MacroZheng2 分钟前
还在用WebSocket实现即时通讯?试试MQTT吧,真香!
java·spring boot·后端
midsummer_woo25 分钟前
基于springboot的IT技术交流和分享平台的设计与实现(源码+论文)
java·spring boot·后端
别惹CC2 小时前
Spring AI 进阶之路01:三步将 AI 整合进 Spring Boot
人工智能·spring boot·spring
柯南二号3 小时前
【Java后端】Spring Boot 集成 MyBatis-Plus 全攻略
java·spring boot·mybatis
javachen__4 小时前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
IT毕设实战小研10 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
一只爱撸猫的程序猿11 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋12 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
武昌库里写JAVA14 小时前
JAVA面试汇总(四)JVM(一)
java·vue.js·spring boot·sql·学习
Pitayafruit15 小时前
Spring AI 进阶之路03:集成RAG构建高效知识库
spring boot·后端·llm