从浅入深 学习 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)