SpringCloud 使用sentinel

一、添加依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

二、配置文件配置地址

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080

 三、流控模式介绍

直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式

关联:统计与当前资源相关的另一个资源触发阈值时,对当前资源限流

        使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。业务需求是有限支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。

链路:统计从指定链路访问到本资源的请求触发阈值时,对指定链路限流

例如有两条请求链路:

/test1→ /common
/test2→/common

如果只希望统计从/test2进入到/common的请求,则可以这样配置:

注意:

1、Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application.yml,添加配置:

spring:
 
cloud:
    sentinel:
     
web-context-unify: false # 关闭context整合

2、Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法(如service方法),需要利用@SentinelResource注解,示例:

@SentinelResource("goods")
public void queryGoods() {
    System.
err.println("查询商品");
}

 四、流控效果

快速失败:QPS超过阈值时,拒绝新的请求。

warm up: QPS超过阈值时,拒绝新的请求;但QPS阈值是逐渐提升的,可以避免冷启动时高并发导致服务宕机。

排队等待:请求会进入队列,按照阈值允许的时间间隔依次执行请求;如果请求预期等待时长大于超时时间,直接拒绝。

五、热点参数限流

热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值。并且可以对部分参数设置例外配置:

注意:热点参数限流对默认的SpringMVC资源无效,必须手动添加@SentinelResource注解

 六、FeignClient整合Sentinel

Sentinel支持的雪崩解决方案:1、线程隔离(仓壁模式)2、降级熔断

(1)在application.yml中配置:feign.sentienl.enable=true

feign:
  sentinel:
   
enabled: true # 开启FeignSentinel功能

(2)给FeignClient编写FallbackFactory并注册为Bean

public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable throwable) {
        // 创建UserClient接口实现类,实现其中的方法,编写失败降级的处理逻辑
        return new UserClient() {
            @Override
            public User findById(Long id) {
                // 记录异常信息
                log.error("查询用户失败", throwable);
                // 根据业务需求返回默认的数据,这里是空用户
                return new User();
            }
        };
    }
}

@Bean
public UserClientFallbackFactory userClientFallback(){
    return new UserClientFallbackFactory();
}

(3)将FallbackFactory配置到FeignClient

@FeignClient(value = "userservice", fallbackFactory =UserClientFallbackFactory.class)
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

 七、熔断降级策略

1、慢调用比例:超过指定时长的调用为慢调用,统计单位时长内慢调用的比例,超过阈值则熔断

2、异常比例:统计单位时长内异常调用的比例,超过阈值则熔断

3、异常数:统计单位时长内异常调用的次数,超过阈值则熔断

八、授权规则

授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。

 Sentinel是通过RequestOriginParser这个接口的parseOrigin来获取请求的来源的。

public interface RequestOriginParser {
    /**
     * 从请求request对象中获取origin,获取方式自定义
     */
    String parseOrigin(HttpServletRequest request);
}

所以在填写流控应用的时候,是根据自定义的RequestOriginParser来填写(比如在请求header上添加值来区分是网关过来的请求还是直接访问的服务的请求)

@Component
public class HeaderOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        String origin = request.getHeader("origin");
        if(StringUtils.isEmpty(origin)){
            return "blank";
        }
        return origin;
    }
}

九、自定义返回方法

只需实现BlockExceptionHandler接口即可

@Component
public class SentinelBlockHandler implements BlockExceptionHandler {
    @Override
    public void handle(
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        String msg = "未知异常";
        int status = 429;
        if (e instanceof FlowException) {
            msg = "请求被限流了!";
        } else if (e instanceof DegradeException) {
            msg = "请求被降级了!"; 
        } else if (e instanceof ParamFlowException) {
            msg = "热点参数限流!";
        } else if (e instanceof AuthorityException) {
            msg = "请求没有权限!";
            status = 401;
        }
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.setStatus(status);
        httpServletResponse.getWriter().println("{\"message\": \"" + msg + "\", \"status\": " + status + "}");
    }
}

 十、配置规则持久化三种模式

1、原始模式:保存在内存

2、pull模式:保存在本地文件或数据库,定时去读取

3、push模式:保存在nacos,监听变更实时更新

通常生产环境采用push模式,需要修改Sentinel-dashboard的源码

猜你喜欢

转载自blog.csdn.net/u012758488/article/details/129860795