雪崩问题以及解决方案
限流设置
达到阈值的效果
隔离和降级
熔断
授权规则
设置规则持久化
雪崩问题以及解决方案
- 雪崩
- 微服务调用链路中的某个服务出现故障,引起链路上其他服务都不可用,这就是雪崩
- 解决方案
- 超时处理,设定超时时间,请求超过设定时间,就返回错误信息
- 舱壁模式,设定每个业务使用的线程数,避免消耗服务器的全部资源,也叫线程隔离
- 熔断降级,由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求
- 预防方案
- 流量控制,限制业务的访问量,避免服务因流量突增,出现故障
Sentinel
- 步骤
- 依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 配置Sentinel 信息
- 这样就可以监控到服务
设置限流
限流
-
直接:对当前资源限流
-
关联模式:关联另一个请求,如果这个请求超过了阈值,关联者就会被限流
-
两个资源有竞争关系,一个优先级高,一个优先级低
-
链路模式
-
只统计从指定资源进入当前资源的请求,对请求来源进行限流
达到阈值的效果
- 快速失败:QPS超过阈值,拒绝新的请求
- warm up :QPS超过阈值时,拒绝新的请求,QPS的阈值是逐渐提高的
- 排队等待:请求进入队列,按## 照阈值时间依次执行,如果预期等待时间大于超时时间,直接拒绝
参数限流
隔离和降级
- 线程隔离 保护调用者
-
- application.yml中配置
- application.yml中配置
- 2.编写异常处理并配置bean
- 3.接口上声明
线程池隔离
设定每个业务使用的线程数,避免消耗服务器的全部资源,也叫线程隔离
熔断
服务熔断交由状态机实现
请求进入closed,当请求到达阈值时,进入open,快速失败请求,熔断时间结束后,进入half-opne
尝试一次请求,查看请求是否正确,正确关闭路云强,错误打开断路器
- 慢调用:每次请求时间多次超过比例阈值,触发熔断
- 异常比例:出现异常的比例超出阈值时,操作失败
授权规则: 对授权者的规则做判断
授权规则就是对请求来源的判断,通过来源名称,判断是否可以访问
- 网关定义请求头
- 服务修改请求头信息
- 配置授权的白名单/黑名单
全局异常的错误提示
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
String msg = "未知异常";
int status = 429;
if (e instanceof FlowException) {
msg = "请求被限流了";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被降级了";
} else if (e instanceof AuthorityException) {
msg = "没有权限访问";
status = 401;
}
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");
}
}
规则持久化