Sentinel 限流熔断与降级
6.1 Sentinel 是什么?
Sentinel 是面向分布式服务架构的流量治理组件。
它可以做:
text
接口限流
熔断降级
热点参数限流
系统保护
授权规则
实时监控简单理解:
text
Sentinel 是微服务的流量防卫兵。6.2 Sentinel 核心概念
6.2.1 资源 Resource
资源就是 Sentinel 要保护的对象。
常见资源:
text
一个 Controller 接口
一个 Feign 调用
一个方法
一个网关路由例如:
text
/order/create
/stock/reduce
GET:http://stock-service/stock/info6.2.2 规则 Rule
规则就是如何保护资源。
常见规则:
text
流控规则
熔断规则
热点规则
系统规则
授权规则6.2.3 QPS
QPS 是每秒请求数。
例如:
text
QPS = 1表示:
text
每秒最多允许 1 个请求通过。
超过的请求会被限流。6.2.4 并发线程数
线程数限流不是按每秒多少请求,而是按当前正在处理的请求数量限制。
例如:
text
线程数 = 10表示:
text
同一时刻最多允许 10 个请求正在处理。6.2.5 熔断降级
当下游服务异常比例过高、慢调用过多时,Sentinel 可以暂时熔断。
流程:
text
正常调用
↓
下游异常增多
↓
达到熔断规则
↓
进入熔断状态
↓
请求快速失败或走 fallback
↓
过一段时间进入半开
↓
尝试恢复调用
↓
成功则关闭熔断,失败则继续熔断6.3 Sentinel 依赖
在需要保护的服务中引入:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>如果要结合 Feign,需要同时有:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>6.4 配置 Sentinel Dashboard
yaml
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080如果 Sentinel Dashboard 是 8858 端口:
yaml
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:88586.5 Sentinel 懒加载机制
Sentinel 默认是懒加载。
意思是:
text
服务刚启动时,Sentinel 控制台可能看不到该服务。
必须有接口被访问过,Sentinel 才会上报资源。操作流程:
text
1. 启动 sentinel-dashboard
2. 启动微服务
3. 访问一次接口
4. 打开 Sentinel 控制台
5. 刷新页面
6. 左侧出现服务名6.6 接口限流实战
假设接口:
text
http://localhost:8081/order/create?productId=1001&count=2访问一次后,进入 Sentinel 控制台:
text
order-service -> 簇点链路找到资源:
text
/order/create点击:
text
+ 流控配置:
text
阈值类型:QPS
单机阈值:1
流控模式:直接
流控效果:快速失败保存后快速刷新接口。
如果出现:
text
Blocked by Sentinel (flow limiting)说明限流生效。
6.7 自定义限流返回
默认限流返回不友好:
text
Blocked by Sentinel (flow limiting)可以自定义 BlockExceptionHandler。
java
package com.demo.order.sentinel;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Component
public class CustomBlockExceptionHandler implements BlockExceptionHandler {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
String resourceName,
BlockException e) throws Exception {
response.setStatus(429);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType("application/json;charset=UTF-8");
Map<String, Object> body = new HashMap<>();
body.put("code", 429);
body.put("message", "请求过于频繁,请稍后再试");
body.put("resource", resourceName);
response.getWriter().write(objectMapper.writeValueAsString(body));
}
}6.8 Feign 结合 Sentinel 降级
开启 Sentinel 对 Feign 的支持:
yaml
spring:
cloud:
openfeign:
sentinel:
enabled: trueFeign 接口:
java
package com.demo.order.client;
import com.demo.order.client.fallback.StockClientFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(
name = "stock-service",
fallback = StockClientFallback.class
)
public interface StockClient {
@PostMapping("/stock/reduce")
String reduce(@RequestParam("productId") Long productId,
@RequestParam("count") Integer count);
}Fallback:
java
package com.demo.order.client.fallback;
import com.demo.order.client.StockClient;
import org.springframework.stereotype.Component;
@Component
public class StockClientFallback implements StockClient {
@Override
public String info() {
return "库存服务暂时不可用,返回默认库存信息";
}
@Override
public String reduce(Long productId, Integer count) {
return "库存服务暂时不可用,扣减库存失败,已进入降级逻辑";
}
}当 stock-service 挂掉或超时后,order-service 可以返回兜底结果。
6.9 fallbackFactory 获取异常原因
如果想知道异常原因,可以使用 FallbackFactory。
Feign:
java
package com.demo.order.client;
import com.demo.order.client.fallback.StockClientFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@FeignClient(
name = "stock-service",
fallbackFactory = StockClientFallbackFactory.class
)
public interface StockClient {
@PostMapping("/stock/reduce")
String reduce(@RequestParam("productId") Long productId,
@RequestParam("count") Integer count);
}FallbackFactory:
java
package com.demo.order.client.fallback;
import com.demo.order.client.StockClient;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class StockClientFallbackFactory implements FallbackFactory<StockClient> {
@Override
public StockClient create(Throwable cause) {
return new StockClient() {
@Override
public String reduce(Long productId, Integer count) {
return "库存服务异常,降级处理,原因:" + cause.getMessage();
}
};
}
}6.10 Sentinel 熔断规则理解
常见熔断策略:
text
慢调用比例
异常比例
异常数慢调用比例
例如:
text
最大 RT:1000ms
比例阈值:0.5
熔断时长:10s
最小请求数:5
统计时长:10000ms意思:
text
在统计窗口内,至少有 5 个请求。
如果超过 50% 的请求响应时间大于 1000ms,则触发熔断。
熔断持续 10 秒。异常比例
例如:
text
异常比例:0.5
最小请求数:5
熔断时长:10s意思:
text
统计窗口内至少 5 个请求。
如果异常比例超过 50%,触发熔断。异常数
例如:
text
异常数:5
统计时长:10000ms
熔断时长:10s意思:
text
10 秒内异常数量达到 5 次,触发熔断。6.11 Sentinel 规则持久化
注意:
text
Sentinel Dashboard 手动配置的规则默认保存在内存中。
服务重启后规则可能会丢失。生产环境一般需要规则持久化:
text
Sentinel Dashboard
↓
Nacos Config
↓
微服务监听规则配置常见规则类型:
text
流控规则
降级规则
热点参数规则
系统保护规则
授权规则