一.sentinel介绍
1.sentinel笔记
2.sentinel基本概念
sentinel官方网站
如何使用
Sentinel 控制台
release 页面 下载最新版本的控制台 jar 包。
二.sentinel整合springboot
1.sentinel流控
Sentinel Spring Cloud Starter
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。Sentinel 与 Spring Boot/Spring Cloud 的整合见 Sentinel Spring Cloud Starter
如何使用 Sentinel
1).Sentinel依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
Sentinel 的例子
见 Sentinel Spring Cloud Starter
2).Sentinel 控制台
release 页面 下载 控制台 jar 包。
解压、启动jar包
java -jar sentinel-dashboard-1.6.3.jar --server.port=8333
或者
java -jar sentinel-dashboard-1.7.1.jar --server.port=8333
访问sentinel控制台
http://localhost:8333/
用户名、密码为sentinel
3).配置sentinel控制台地址信息
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8333
4).在sentinel控制台调整参数
启动秒杀服务、访问某请求
http://localhost:25000/currentSeckillSkus
a.添加流控规则
QPS:1
流控模式:直接
流控效果:快速失败
结果:没能耐有一个请求,否则请求失败
默认所有的流控设置保存在内存中,重启项目失效
5).sentinel自定义流控响应
需要sentinel的Endpoint 支持
sentinel的Endpoint 支持
a.导入spring-boot-starter-actuator 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
b.配置web暴露
Spring Boot 2.x 中添加配置 management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.include=*
c.自定义阻塞返回方法
@Configuration
public class GulimallSeckillSentinelConfig {
public GulimallSeckillSentinelConfig() {
WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().write(JSON.toJSONString(error));
}
});
}
}
d.测试
添加流控
启动服务、发送请求
http://localhost:25000/currentSeckillSkus
结果
6).全服务引入sentinel保护
a.给所有服务添加actuator依赖、配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
spring.cloud.sentinel.transport.dashboard=localhost:8333
management.endpoints.web.exposure.include=*
b. order服务问题
修改MyRabbitConfig
注释自动注入RabbitTemplate,自己创建方法获得RabbitTemplate
// @Autowired
RabbitTemplate rabbitTemplate;
@Bean
@Primary
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setMessageConverter(messageConverter());
initRabbitTemplate();
return rabbitTemplate;
}
7).流控模式、效果
ops、线程数
直接、关联、链路
快速失败、warm up 、排队等待
2.sentinel熔断、降级
A调用B服务,如果B服务宕机了,怎么办?熔断保护机制,对B进行服务降级
2.1 使用sentinel来保护feign远程调用:熔断
1).feign支持
a.依赖、配置
sentinel的feign支持
引入 spring-cloud-starter-alibaba-sentinel 的依赖外还需要 2 个步骤:
配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true
加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
b.修改feign,添加fallback
@FeignClient(value = "gulimall-seckill",fallback = SeckillFeignServiceFallBack.class)
public interface SecKillFeignService {
//查询秒杀的商品sku信息
@GetMapping("/sku/seckill/{skuId}")
R getSkuSeckillInfo(@PathVariable("skuId") Long skuId);
}
c.写fallback类、方法
@Component
public class SeckillFeignServiceFallBack implements SecKillFeignService {
@Override
public R getSkuSeckillInfo(Long skuId) {
return R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(),BizCodeEnume.TO_MANY_REQUEST.getMsg());
}
}
d.测试
关闭seckill秒杀服务、查看秒杀的商品详情页
order.gulimall.,com/1.html.
2).熔断降级
熔断降级
每个服务都应该feign支持
feign.sentinel.enabled=true
a.降级在调用方
提供方宕机,进行熔断、降级
b.降级在提供方
某请求的 超大流量,进行降级服务。主要做全局处理
3).sentinel自定义受保护资源
a.方式一:代码的方式
抛出异常的方式定义资源
使用规则
try {
AsyncEntry entry = SphU.asyncEntry(resourceName);
// 异步调用.
doAsync(userId, result -> {
try {
// 在此处处理异步调用的结果.
} finally {
// 在回调结束后 exit.
entry.exit();
}
});
} catch (BlockException ex) {
// Request blocked.
// Handle the exception (e.g. retry or fallback).
}
代码修改-添加自定义受保护资源
将受保护的资源放入try中,需要jdk.9
添加流控规则
测试:ok
重复执行http://localhost:25000/currentSeckillSkus
IDEA控制台:
b.方式二:注解的方式
注解方式定义资源
使用规则:
Sentinel 支持通过 @SentinelResource 注解定义资源,并配置 blockHandler 和 fallback 函数来进行限流之后的处理。示例:
// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {
throw new RuntimeException("getUserById command failed");
}
// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {
return new User("admin");
}
注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,
而 fallback 函数会针对所有类型的异常。请注意 blockHandler 和 fallback 函数的形式要求,Sentinel 注解支持文档
方法添加注解、block方法
添加getCurrentSeckillSkusResourse流控规则
测试,ok
重复执行 http://localhost:25000/currentSeckillSkus
结果:IDEA控制台
c.总结注解的方式
有blockHander与fallback
前者,后者
注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,
而 fallback 函数会针对所有类型的异常。请注意 blockHandler 和 fallback 函数的形式要求,Sentinel 注解支持文档
添加fallback
方式1:fallbakc的异常方法(与注解在相同的类中)
方式2:fallbakc的异常类(与注解不在相同类中)
3.sentinel-网关流控
如果在网关层进行限流,回避在服务的效果更明显
3.1.添加sentinel与gateway整合的依赖
<!--sentinel与gateway整合, https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-alibaba-sentinel-gateway -->
<!--版本与common的版本一致-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
网关限流
Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。
使用1.7.1的sentinel
1).网关层添加流控规则
对秒杀seckill 项目进行网关流控
结果
http://seckill.gulimall.com/currentSeckillSkus
2)根据属性添加规则
根据请求头,添加流控规则。
请求头必须有hello world。postman测试
3).自定义API管理 -路由分组
假如添加hello组
添加网关流控可以使用路由分组
被网关控制的请求数据,就不用转发到微服务了
4).网关降级规则
5).定制网关返回的数据
a.配置文件配置
#自定义管理-路由分组
#spring.cloud.sentinel.scg.fallback.content-type=application/json
spring.cloud.sentinel.scg.fallback.response-status=400
b.配置类
网关项目的配置类
@Configuration
public class SentinelGatewayConfig {
//TODO 响应式编程
//GatewayCallbackManager
public SentinelGatewayConfig() {
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
//网关限流了请求,就会调用此回调 Mono flux
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {
R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
String errorJson = JSON.toJSONString(error);
Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
return body;
}
});
}
}
c.添加网关流控规则
d.测试、结果
测试
多次执行 http://seckill.gulimall.com/currentSeckillSkus
结果: