雪崩问题
在微服务调用链路中的某个服务故障,引起整个链路中的所有服务都不可用
例如服务A调用服务D,D出现故障,不会返回响应信息,tomcat一直等待响应,不会断开AD的连接,导致A的Tomcat资源耗尽,导致整个链路上的服务都不可用
解决方式
- 超时处理:请求超过一定时间没有响应就返回错误信息,不会无休止等待;只能缓解,如果进入该服务的请求大于释放的速度,还是会出现问题
- 舱壁模式:限定每个业务能使用的线程数,避免整个tomcat资源耗尽,因此也叫线程隔离;资源仍会损耗,一个服务挂了还分配线程给他
- 熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求
- 流量控制:限制业务访问的QPS,避免服务因流量突增而故障(预防)
搭建
安装sentinel
https://github.com/alibaba/Sentinel/releases/tag/1.8.1 下载sentinel-dashboard-1.8.1.jar - 控制台
cd Program Files java -jar sentinel-dashboard-1.8.1.jar - 访问
localhost:8080 账号密码:sentinel
如果需要可改配置:
微服务整合sentinel
-
在子pom引入sentinel依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
-
配置服务地址 spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
-
向服务发起请求,sentinel实施监控
限流规则
添加限流
流控模式
直接
对当前资源限流
关联
写优先级大于读,当写操作达到一定阈值时,对读限流
链路
针对从指定链路访问到本地资源的请求限流
比如 查询订单 和 创建订单 都要查商品,此时就是两个链路访问同一资源,就可以对其中一条链路(查询订单)限流
流控效果
快速失败
超出阈值的请求会被立即拒绝并抛出异常
预热模式
超出阈值的请求立即拒绝抛异常,但是阈值会动态变化、不断增加
针对服务器冷启动。初始阈值为最大三分之一,可设置预热时长,逐渐增加到最大
排队等待
让所有的请求按先后顺序排队执行,可设置两个请求间最大时长,超过这个最大时间就直接拒绝;实现流量整形
热点参数限流
隔离和降级
隔离和降级都是保护服务调用者的安全,不被调用的服务拖垮,所以应当在feign调用时采取措施
Feign整合Sentinel
-
开启feign对sentinel的支持 feign:
sentinel:
enabled: true
-
在feign-api下新建UserClientFallbackFactory下写失败逻辑
@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();
}
};
}
}
-
将UserClientFallbackFactory注入bean public class DefaultFeignConfiguration {
@Bean
public UserClientFallbackFactory userClientFallbackFactory(){
return new UserClientFallbackFactory();
}
}
-
在UserClient注解加入fallbackFactory @FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
线程隔离
也就是仓壁模式
- 信号量隔离:基于计数器模式;轻量级;不支持主动超时和异步调用;用于高频调用、高扇出场景(网关默认)
- 线程池隔离:有额外开销小,隔离控制性强,支持主动超时和异步调用;低扇出场景;使用:在限流中选择线程
熔断降级
使用断路器统计服务调用时的异常比例,超出阈值就熔断该服务
三种状态
熔断策略
慢调用、异常比例、异常数
慢调用
业务响应时长>指定请求时长,一定比例就出发熔断
异常比例&异常数
- 异常比例:一段时间内的异常比例达到阈值,出发熔断
- 异常数:异常数达到一定值,出发熔断
授权规则
问题:虽然设置了网关,但是从浏览器发出的请求可以绕过网关调用服内部务
于是我们就要保证调用的请求是从网关来的,可以给从网关出来的请求加上一个标记(RequestHeader);就可以对请求来源判断
给orderservice加上判断
@Component
public class HeaderOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
String origin = httpServletRequest.getHeader("origin");
if (StringUtil.isEmpty(origin)){
origin="blank";
}
return origin;
}
}
|