环境搭建
可以查看文档:官网 | 快速开始
- 官方提供了UI控制台,以方便我们对系统做限流设置。
- 下载好后,放在任意非中文目录下,在cmd中执行
java -jar sentinel-dashboard-1.8.1.jar,就可以启动了。
- 访问http://localhost:8080页面,就可以看到sentinel的控制台了:需要输入账号和密码,默认都是:sentinel
基础使用
- 引入依赖:
1 2 3 4 5
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
|
- yaml配置文件
修改application.yaml文件,添加下面内容:
1 2 3 4 5 6 7 8
| server: port: 8088 spring: cloud: sentinel: eager: true transport: dashboard: localhost:8080
|
- 访问任意接口
打开浏览器,访问任意接口 如:http://localhost:8088/order/101,这样才能触发sentinel的监控。然后再访问sentinel的控制台,查看效果。
FeignClient整合Sentinel
整合后编写失败降级逻辑:就是请求失败后不是直接返回一个异常而是返回一个空对象(保证用户体验)
- 修改配置文件:
1 2 3
| feign: sentinel: enabled: true
|
保证已经有了Feign和sentinel依赖
- 编写请求失败降级逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @FeignClient(value = "service-product", fallback = ProductFeignClientFallback.class) public interface ProductFeignClient { @GetMapping(value = "/productId/{id}") public Product getProductById(@PathVariable("id") Long productId); }
@Component public class ProductFeignClientFallback implements ProductFeignClient { @Override public Product getProductById(Long productId) { System.out.println("兜底回调...."); Product product = new Product(); product.setId(productId); product.setPrice(new BigDecimal("0")); product.setProductName("未知商品"); product.setNum(0); return product; } }
|
- 测试,要注意关掉Retryer的重试
簇点链路中的链路来自于几种资源:
- 主流框架自动适配(例如:web请求)
- 声明式:@SentinelResource
- 声明式 Sphu API(不常用)
异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| 异常处理(Sentinel) │ ├── 异常抛出(BlockException) │ ├── 触发场景 │ │ ├── Web 接口(由 SentinelWebInterceptor 拦截) │ │ ├── @SentinelResource(由 SentinelResourceAspect 切面拦截) │ │ ├── OpenFeign 调用(由 SentinelFeign.Builder 增强) │ │ └── SphU 硬编码(手动调用) │ └── 抛出类型:BlockException(流控、降级、系统保护等异常) │ └── 异常处理策略(捕获 & 回调) ├── 原生捕获 │ └── try-catch 手动捕获 BlockException │ ├── 全局统一处理 │ ├── 默认 BlockExceptionHandler(Sentinel 提供) │ ├── 自定义 BlockExceptionHandler(自定义 BEH) │ └── Spring Boot 全局异常处理(@ControllerAdvice) │ └── 注解/回调机制 ├── @SentinelResource 的 blockHandler(针对 BlockException) ├── @SentinelResource 的 fallback(业务异常或 BlockException 的兜底) ├── OpenFeign 的 fallback(集成 Sentinel 时的服务降级) └── 兜底回调(泛指 fallback 机制)
|
web接口异常
实现BlockExceptionHandler接口,写一个BlockExceptionHandler的实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Component public class MyBlockExceptionHandler implements BlockExceptionHandler { private ObjectMapper objectMapper = new ObjectMapper(); @Override public void handle(HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) throws Exception { response.setStatus(429); response.setContentType("application/json;charset=utf-8"); PrintWriter writer = response.getWriter(); R error = R.error(500, resourceName + " 被Sentinel限制了,原因:" + e.getClass()); String json = objectMapper.writeValueAsString(error); writer.write(json); writer.flush(); writer.close(); } }
|
然后再UI控制台中配置流控规则,比如select接口的QPS设置每秒只允许1个请求,然后1s内多次访问就会触发MyBlockExceptionHandler。
@SentinelResource出现异常
在目标方法加@SentinelResource注解,编写blockHandler方法或者fallback方法处理异常,和feign整合sentinel一样的。
规则-流量控制
在application-feign.yml中加配置sentinel.web-context-unify: false,其意思是在sentinel中不共用同一个上下文
新增流控规则中的专有名词:
- 阈值类型:
- QPS:统计每秒请求数
- 并发线程数:统计并发线程数
- 集群
- 流控模式:
- 直接策略:只对一个资源进行控制,之前的测试一直用这个
- 关联策略:情况有两种;有接口read和write类型的,单独多少次都可以成功。但是当write并发过大,突然访问read,就会走自定义的BlockExceptionHandler的实现类。
- 链路策略:两个请求A和B访问一个资源(随便选一个资源C,即加了@SentinelResource的资源),但只限制配置了入口资源这个请求
- 流控效果:
- 快速失败:处理不了的请求直接丢弃。交给Web接口异常处理MyBlockExceptionHandler。
- Warm Up:慢慢将每秒的请求达到峰值,有个预热机制
- 排队等待:超过阈值,放入队列,以固定间隔匀速处理
注意:只有快速失败支持流控模式(直接、关联、链路)的设置
参考
https://www.cnblogs.com/sexintercourse/p/18646562