目录
1.初识sentinel
1.雪崩问题及解决方案
2.安装sentinel控制台
3.引入demo-cloud
4.微服务整合sentinel
2.限流规则
1.给 /order/{orderId}这个资源设置流控规则,QPS不能超过 5
2.流控模式
3.流控效果
3.热点参数限流
3.隔离和降级
1.Feign整合Sentinel
2.线程隔离
4.授权规则
1.授权规则
2.自定义异常结果
5.规则持久化
微服务调用链路中的某个服务故障,引起整个链路中的所有微服务都不可用,这就是雪崩。
解决雪崩问题的常见方式有四种:
•超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待
•舱壁模式:限定每个业务能使用的线程数,避免耗尽整个tomcat的资源,因此也叫线程隔离。
•熔断降级:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求
•流量控制:限制业务访问的QPS,避免服务因流量的突增而故障。
Sentinel是阿里巴巴开源的一款微服务流量控制组件。官网地址:home
sentinel入门
sentinel官方提供了UI控制台,方便我们对系统做限流设置。大家可以在GitHub下载
java -jar sentinel-dashboard-1.8.1.jar
https://gitee.com/hsmymk/cloud-demo
要使用Sentinel肯定要结合微服务,这里我们使用SpringCloud实用篇中的cloud-demo工程。
在添加限流规则时,点击高级选项,可以选择三种流控模式:
流控效果是指请求达到流控阈值时应该采取的措施,包括三种:
流控效果-warm up
流控效果-排队等待
虽然限流可以尽量避免因高并发而引起的服务故障,但服务还会因为其它原因而故障。而要将这些故障控制在一定范围,避免雪崩,就要靠线程隔离(舱壁模式)和熔断降级手段了。
不管是线程隔离还是熔断降级,都是对客户端(调用方)的保护。
SpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合Feign和Sentinel。
1.修改OrderService的application.yml文件,开启Feign的Sentinel功能
feign:
sentinel:
enabled: true #开启feign对sentinel支持
2.给FeignClient编写失败后的降级逻辑
在feing-api项目中定义类,实现FallbackFactory:
@Slf4j
public class UserClientFallbackFactory implements FallbackFactory {
@Override
public UserClient create(Throwable throwable) {
return new UserClient() {
@Override
public User findById(Long id) {
log.error("查询用户异常",throwable);
return new User();
}
};
}
}
3.在feing-api项目中的DefaultFeignConfiguration类(配置类)中将UserClientFallbackFactory注册为一个Bean:
@Bean
public UserClientFallbackFactory userClientFallbackFactory(){
return new UserClientFallbackFactory();
}
4.在feing-api项目中的UserClient接口中使用UserClientFallbackFactory:
@FeignClient(value = "userservice",
fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
线程隔离有两种方式实现:
1.线程隔离(舱壁模式)
2.熔断降级
3.熔断策略-慢调用
4.熔断策略-异常比例、异常数
例如,我们尝试从request中获取一个名为origin的请求头,作为origin的值:
@Component
public class HeaderOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
//1.获取请求头
String origin = request.getHeader("origin");
//2.非空判断
if (StringUtils.isEmpty(origin)){
origin="blank";
}
return origin;
}
}
我们还需要在gateway服务中,利用网关的过滤器添加名为gateway的origin头
spring:
application:
name: gateway
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes:
- id: user-service # 路由标示,必须唯一
uri: lb://userservice # 路由的目标地址
predicates: # 路由断言,判断请求是否符合规则
- Path=/user/** # 路径断言,判断路径是否是以/user开头,如果是则符合
- id: order-service
uri: lb://orderservice
predicates:
- Path=/order/**
default-filters:
- AddRequestHeader=Truth,Itcast is freaking awesome!
- AddRequestHeader=orign,gateway
默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。如果要自定义异常时的返回结果,需要实现BlockExceptionHandler接口:
我们在order-service中定义类,实现BlockExceptionHandler接口:
@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 + "}");
}
}
https://blog.csdn.net/m0_61107050/article/details/122590486