Sentinel——服务降级
简介
服务降级是一种增强用户体验的方式。当用户的请求由于各种原因被拒后,系统返回-一个事先设定好的、用户可以接受的,但又令用户并不满意的结果。这种请求处理方式称为服务降级。
Sentinel方法级降级
- 导入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- contreller层写法
/**
* 根据id查询部门
*/
@SentinelResource(fallback = "getFallBack")
@GetMapping("/get/{id}")
public Depart get(@PathVariable Long id) {
return restTemplate.getForObject(PROVIDER_URL + "/get/" + id, Depart.class);
}
/**
* 服务降级使用的方法
*/
public Depart getFallBack(Long id, Throwable t) {
log.info("id = " + id);
log.info("throwable = " + t.getMessage());
Depart depart = new Depart();
depart.setId(id);
depart.setName("no this depart");
return depart;
}
在调用get(@PathVariable Long id) 出错的情况下会调用降级的getFallBack(Long id) 方法。
3.验证
get(@PathVariable Long id)不能被访问。
日志
2023-12-01T19:50:26.401+08:00 INFO 17500 --- [nio-8080-exec-2] com.zjw.controller.DepartController : id = 1
2023-12-01T19:50:26.401+08:00 INFO 17500 --- [nio-8080-exec-2] com.zjw.controller.DepartController : throwable = No instances available for depart-provider
Sentinel类级降级
- 定义降级使用的类
方法需要是static声明
package com.zjw.controller.fallback;
import com.zjw.domain.Depart;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* DepartControllerFallBack
* @since 2023/12/01 19:56
*/
@Slf4j
public class DepartControllerFallBack {
/**
* 服务降级使用的方法
*/
public static Depart getFallBack(Long id, Throwable t) {
log.info("id = " + id);
log.info("throwable = " + t.getMessage());
Depart depart = new Depart();
depart.setId(id);
depart.setName("no this depart");
return depart;
}
/**
* 服务降级使用的方法
*/
public static List<Depart> listFallBack(Throwable t) {
log.info("listFallBack");
log.info("throwable = " + t.getMessage());
Depart depart = new Depart();
depart.setName("no this depart");
return List.of(depart);
}
}
- Controller层
在需要降级的方法上标注上降级使用的方法和类
package com.zjw.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.zjw.controller.fallback.DepartControllerFallBack;
import com.zjw.domain.Depart;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* <p>
* 部门表 前端控制器
* </p>
*
* @since 2023-11-20
*/
@RestController
@RequestMapping("/depart")
@Slf4j
public class DepartController {
@Resource
private RestTemplate restTemplate;
private static final String PROVIDER_URL = "http://depart-provider/depart";
/**
* 根据id查询部门
*/
@SentinelResource(fallback = "getFallBack" , fallbackClass = DepartControllerFallBack.class)
@GetMapping("/get/{id}")
public Depart get(@PathVariable Long id) {
return restTemplate.getForObject(PROVIDER_URL + "/get/" + id, Depart.class);
}
/**
* 查询所有部门
*/
@SuppressWarnings("unchecked")
@SentinelResource(fallback = "listFallBack" , fallbackClass = DepartControllerFallBack.class)
@GetMapping("/list")
public List<Depart> list() {
return (List<Depart>)restTemplate.getForObject(PROVIDER_URL + "/list", List.class);
}
}
- 验证
OpenFeign类级降级
导入依赖
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zjw</groupId>
<artifactId>sc-06-consumer-sentinel-degrade-openfeign-8080</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sc-06-consumer-sentinel-degrade-openfeign-8080</name>
<description>sc-06-consumer-sentinel-degrade-openfeign-8080</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<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>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
开打sentinel对openfeign支持
server:
port: 8080
spring:
application:
name: depart-consumer # 微服务名称
cloud:
nacos:
discovery:
server-addr: nacos-local:8848 # nacos注册中心地址
username: nacos # 用户名密码
password: nacos
openfeign:
client:
config:
default: # 这是一个map,设置默认配置
connect-timeout: 5000 # 连接超时时间
read-timeout: 5000 # 响应超时时间
depart-provider: # 指定服务的设置
connect-timeout: 4000 # 连接超时时间
read-timeout: 4000 # 响应超时时间
feign: # 打开 sentinel 对 feign 的支持
sentinel:
enabled: true
编写sentinel类
注意
@RequestMapping("/fallback/depart")
package com.zjw.service;
import com.zjw.domain.Depart;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
/**
* @since 2023/12/01 21:11
*/
@Component
@Slf4j
@RequestMapping("/fallback/depart")
public class DepartServiceFallBack implements IDepartService{
@Override
public boolean save(Depart depart) {
log.info("save..fallback");
return false;
}
@Override
public boolean remove(Long id) {
log.info("remove..fallback");
return false;
}
@Override
public boolean update(Depart depart) {
log.info("update..fallback");
return false;
}
@Override
public Depart get(Long id) {
log.info("get..fallback");
return null;
}
@Override
public List<Depart> list() {
log.info("list..fallback");
return null;
}
@Override
public List<String> discovery() {
log.info("discovery..fallback");
return null;
}
}
在接口上标注使用的fallback类
@FeignClient(value = "depart-provider", path = "/depart", fallback = DepartServiceFallBack.class)
public interface IDepartService {
....
}
---------------
我每一次回头,都感觉自己不够努力,所以我不再回头。
---------------