一、认识Sentinel
1.1 雪崩问题
- 解决方式
(1)超时时间:如果请求一定时间无响应就返回错误信息,不会一直等待。(当请求太多资源也会耗尽,只能缓解耗尽的情况)
(2)船舱模式:A服务依赖于B和C,但是只给B最大10线程进入,C也是10个。有效的避免Tomcat资源耗尽。将线程进行隔离。(如果C挂了,但是C仍然占用着10个线程,造成资源浪费)
(3)熔断降级:由断路器统计执行的异常比例,当达到一定的阈值,就会熔断该业务,拦截该业务的一切请求。
(4)流量控制:限制业务访问的QPS(每秒能处理的请求),避免流量突增发生故障。
1.2 服务保护的区别(Sentinel和Hystrix)
1.3 安装使用Sentinel
下载Sentinel
https://github.com/alibaba/Sentinel/releases/tag/1.8.1
启动命令(因为Sentinel默认端口为8080,可能会冲突)
java -Dserver.port=8092 -jar sentinel-dashboard-1.8.1.jar
二、使用Sentinel
2.1 准备cloud-demo文件
https://pan.baidu.com/s/169SFtYEvel44hRJhmFTRTQ?pwd=1234
2.2 引入Sentinel的依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.3 yaml进行Sentinel控制台的地址的配置
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8092
2.4 访问微服务任意断点触发Sentinel监控
三、限流规则
1.1 簇点链路
簇点链路:就是项目内的调用链路,链路中被监控的每个接口就是一个资源。默认情况下sentinel会监控SpringMVC的每一个端点(Endpoint),因此SpringMVC的每一个端点(Endpoint)就是调用链路中的一个资源。(每一个Controoler的接口都是一个断点)
1.2 流控模式
- 直接:统计当前资源的请求,触发阈值直接限流,为默认模式。
- 关联:统计与当前资源相关联的资源,触发阈值对当前资源限流。
- 链路:统计从指定链路访问到当前资源的请求,触发阈值对指定链路限流。
Sentinel会将Controller做context整合,会导致链路模式的流控失效,需要做以下配置
spring:
cloud:
sentinel:
web-context-unify: false
1.3 流控模式效果
- 快速失败
新的请求会立即拒绝并且抛出FlowException异常,为默认处理。- warm_up
预热模式的阈值不是一直不变的,会从一个较小的值逐渐增大为最大阈值。初始阈值为最大阈值/冷启动因子(默认为3)- 排队等待
让所有的请求按先后次序排队执行,两个请求的间隔不能小于指定时长,超过就会被拒绝。
1.4 热点参数限流
1秒钟最多5个请求,即QPS=5。
热点参数限流默认对接口无效,需要添加 @SentinelResource(“queryOrder”)注解。
四、 隔离(线程隔离)和熔断降级
4.1 FeginClient整合Sentinel
因为微服务都是通过FeginClient进行调用的,所有需要通过feign客户端做保护。
4.1.1 配置yaml文件
feign:
sentinel:
enabled: true # 开启feign对sentinel的支持
4.1.2 编写失败的降级逻辑并注册为Bean,最后在对应的Clent(继承FallbackFactory )
@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable throwable) {
return new UserClient() {
@Override
public User findById(Long id) {
log.error("查询用户异常", throwable);
return new User();
}
};
}
}
@Configuration
public class DefaultFeignConfiguration {
@Bean
public Logger.Level logLevel(){
return Logger.Level.BASIC;
}
@Bean
public UserClientFallbackFactory userClientFallbackFactory(){
return new UserClientFallbackFactory();
}
}
4.2 线程隔离的实现方式
4.3 熔断降级
当超出了失败阈值,断路器会打开,所有请求在一段时间内无法进入,当熔断时间结束后,会处于一个hafl_open状态,会尝试放行一次请求,如果成功,就会关闭断路器,否则继续熔断一段时间。
4.4 熔断策略
在一段时间内,如果一部分请求超过慢调用时间阈值,这部分超出比例阈值,将会熔断降级。RT为时间阈值。
异常统计超过比例阈值就熔断
统计异常次数进行熔断
五、 授权规则以及规则持久化
5.1 授权规则
授权可以对调用的来源进行控制,有白名单和黑名单两种。
授权规则主要针对那些绕过网关直接访问微服务的请求。
Sentinel使用RequestOriginParser接口的parseOrigin来获取请求的资源。但是默认返回资源为default,所以需要改写。对于浏览器和网关来说,这两个来源的请求都是没有orgin的,我们可以在网关的默认过滤上添加请求头origin,即可以区分请求是从浏览器还是网关发送过来的。
授权规则的值是根据该返回值进行判断。
@Component
public class HeaderOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
String origin = request.getHeader("origin");
if(origin.isEmpty()){
origin = "blank";
}
return origin;
}
}
5.2 自定义异常
由于流控或者是熔断给用户返回的都是默认异常,所以我们需要去指定自定义异常。我们可以实现BlockExceptionHandler接口来实现自定义异常。
5.3 规则的持久化
Sentinel规则有默认的三种管理模式。
- 原始模式:Sentinel的默认模式,将规则保存到内存里,重启就会丢失。
- pull模式:控制台将配置的规则推送到Sentinel客户端,Sentinel客户端首先会在内存里更新规则,然后将规则持久化到本地文件数据库。其他Sentinel客户端会定时询问数据库文件是否更改,更改的话进行同步数据。(数据容易不一致)
- push模式:控制台将规则推送到nacos,Sentinel微服务监听nacos,一旦发现nacos的规则数据发生变化,就对规则进行更新。(推荐)
5.4 push模式实现规则的持久化
5.4.1 引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
5.4.2 Sentinel配置nacos地址
spring:
cloud:
sentinel:
datasource:
flow:
nacos:
server-addr: localhost:8848
dataId: orderservice-flow-rules
groupId: SENTINEL_GROUP
rule-type: flow #还可以是degrade、authority、param-flow如果还要做这些限流规则持久化,可以在datasource下加这些持久化规则。
5.4.4 修改nacos下的NacosConfig的nacos地址