6.Sentinel应用实践2

目录

核心知识点

Sentinel降级概念

基于Sentinel实现服务降级(主动熔断)

慢调用比列

异常比列

Sentinel系统规则实践

Sentinel热点规则实践

热点规则产生背景

实现原理

快速入门

特定参数设置

Sentinel授权限流实践

概述

快速入门

授权异常处理

我们该可以通过设置请求头内容进行授权限流

我们还可以通过获取调用者的ip来进行授权限流

请求的底层实现原理

常见问题

何为熔断

为什么要使用熔断

Sentinel限流异常的顶底父类

Sentinel降级抛出的异常是哪个类

Sentinel出现异常的处理接口是哪个

Sentinel降级策略都有哪些

底层基于什么对热点数据进行限流

假如你去设计Sentinel,你将如何判定哪些数据是热点数据

java中是否有直接封装了LRU算法的类

你了解的系统限流规则都有哪些

如何理解Sentinel中的授权规则

Sentinel中解析黑白名单的接口是谁


核心知识点

Sentinel降级概念

当访问量过大,大量的线程堆积会造成服务器宕机,我们可以通过降级来熔断这个请求来保证服务的稳定性,还在这里的熔断属于主动熔断

基于Sentinel实现服务降级(主动熔断)

慢调用比列

第一步:写测试方法

/**
 * 演示降级操作,通过如下代码创造降级条件:
 * 服务响应速度慢或服务不稳定,经常出现异常
 * */
//自增API,线程是安全的,对象内的1为初始值
private AtomicLong atomicLong = new AtomicLong(1);
@GetMapping("/sentinel05")
public String doSentinel05() throws InterruptedException {
    //先获取,再自增
    long count = atomicLong.getAndIncrement();
    if (count%2==0){//判断,偶数让线程休眠
        Thread.sleep(200);//偶数线程休眠200ms,模拟线程阻塞情景
    }
    return "sentinel05 test ...";
}

第二步:在蔟点链路给资源配置降级信息(难点)

解释:在统计时长(2s)内发送请求数大于最小请求(5)个时,慢调用比例生效,假设这些请求的比例阈值(30%)超过最大RT(200ms)时,也就是这些请求响应时间过长或者不响应时,就将这这服务断开20s,也就是熔断时长,在这20s内该服务处于不可用状态,20s后重新进行一轮的计算

第三步:测试降级

控制台报错,显示的内容是我们自定义的实现BlockExceptionHandler接口的异常处理类,但这是限流的异常信息,用在降级后的错误显示内容显然有些不合适,我们可以通过debug检查一下降级所报的异常实现什么类型,对降级所报的异常进行处理

第四步:debug

 Sntinue的所有异常都是通过实现BlockException接口进行处理的,我们通过debug发现,此时BlockException的参数e为DegradeException实现类对象,说明此时的异常处理类DegradeException

第五步:使用BlockException的instanceof方法来对异常进行一个判断,再处理

String msg ="访问太过频繁,反应不过来啦!666";//默认为限流异常(直接和关联方式)
if (e instanceof DegradeException){//熔断异常
    msg = "服务不可用,稍后再访问吧!";
}
out.println(msg);
out.flush();
out.close();

 第六步:测试降级后的错误信息

异常比列

第一步:写测试方法,模拟出现异常情景

/**
 * 演示降级操作,通过如下代码创造降级条件:
 * 服务响应速度慢或服务不稳定,经常出现异常
 * */
//自增API,线程安全,对象内的参数为初始值
private AtomicLong atomicLong = new AtomicLong(1);
@GetMapping("/sentinel05")
public String doSentinel05() throws InterruptedException {
    //先获取,在自增
    long count = atomicLong.getAndIncrement();
    //判断,偶数线程阻塞或抛异常
    if (count%2==0){
        //线程休眠200ms,模拟线程阻塞
        //Thread.sleep(200);
        //或者直接抛出异常
        throw new RuntimeException("服务调用失败!");
    }
    return "sentinel05 test ...";
}

 第二步:指定资源配置降级

 此处的比例阈值为这些请求的30%都报异常时,就会熔断这个服务20s

第三步:测试降级

每两次就会抛异常,因为我们的测试方法抛出了运行时异常

 2秒内请求大于5次,且报异常的服务超过了30%,将该服务熔断20s

Sentinel系统规则实践

Sentinel热点规则实践

热点规则产生背景

当某一商品瞬间被大量人访问时,我们通过传递此商品的id到服务器进行热点限流

当某一用户大量访问时,我们通过传递此用户的id到服务器进行热点限流

实现原理

我们将热点数据通过参数传递到服务,并根据配置的限流阈值与模式,对包含热点资源的服务调用进行限流

热点限流可以看做一种特殊的流量控制,只针对包含热点参数的服务调用进行限流

Sentinel会利用LRU策略统计最近常用的热点参数,结合令牌桶的算法来进行参数级别的流控

快速入门

第一步:因为热点限流是基于@SentinelResource注解,也就是通过切面的通知方法进行限流,所以热点限流的异常处理方法应写在自定义的切面异常处理类中

//处理由@SentinelResource注解修饰时的方法处理限流时的异常
@Component
@Slf4j
public class ResourceBlockHandler {

    /**
     * 这里异常处理方法的要求:
     * 1.修饰符  public static
     * 2.返回值类型与@SentinelResource注解描述的方法返回指相同
     * 3.参数列表与@SentinelResource注解描述的方法返回值相同
     * 可以在最后多添加一个blockHandle参数
     * */
    public static String doHandle(BlockException ex){
        log.error("链路限流");
        return "访问太频繁";
    }

    public static String doHandle(Integer id,BlockException ex){
        log.error("热点限流");
        return "访问人数太多,稍后再试试吧!";
    }
}

因为此方法携带的有integer参数,所以可以与上一个方法同名

第二步:编写测试方法

@GetMapping("/sentinel06")
@SentinelResource(value = "resource",blockHandlerClass = ResourceBlockHandler.class,blockHandler = "doHandle")
//此处@RequestParam("id"),是为了向前端反向兼容,请求时该链接必须携带参数,否则报错
public String doSentinel06(@RequestParam("id") Integer id){
    return "Get Resource By"+id;
}

 第三步:配置热点限流规则

参数索引为@SentinelResource标识方法的参数下标,第一个参数为0,第二个参数为1....在统计窗口时长内超过单机阈值则进行热点限流

第四步:测试

服务器打印错误日志

2022-03-02 20:46:27.016 ERROR 15180 --- [nio-8082-exec-1] c.j.p.service.ResourceBlockHandler       : 热点限流

特定参数设置

点开热点规则,对目标资源进行编辑,点开高级选项

 例外项为在同一个统计窗口时长内,对不同的单机阈值进行热点限流

这里表示参数为1,单机阈值为1,这里表示参数为10,单机阈值为5

Sentinel授权限流实践

概述

很多时候,我们需要根据资源调用方进行限流,这时候就用到Sentinel的黑白名单功能,当设置白名单时,只有位于白名单的调用者才能调用资源,当设置黑名单时,除了黑名单的调用方,其余都能调用资源

快速入门

第一步:通过实现RequestOriginParser接口,重写里面的方法来获取请求地址中的参数,请求头,ip等信息,来进行授权限流,这个类要交给Spring容器管理

@Component
public class DefaultRequestOriginParser implements RequestOriginParser {
    /**
     * 这个方法基于业务规则对请求数据进行解析
     * */
    @Override
    public String parseOrigin(HttpServletRequest request) {
        1.解析请求参数,并返回参数值,然后将这个值应用在Sentinel的授权规则上
        String origin = request.getParameter("origin");
        return origin;
    }
}

 第二步:配置授权限流

 请求路径参数为app1,app2时,限流,其余不限流

第三步:测试

 我们自定义的DefaultRequestOriginParser实现类DefaultRequestOriginParser通过origin(K)拿到参数值app1(V),所以限流

授权异常处理

第一步:我们发现该异常是我们自定义BlockExceptionHandler实现类所报的异常,我们通过debug发现该异常类型为AuthorityException

 第二步:设置AuthorityException异常的前端显示内容

@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest,
                       HttpServletResponse response,
                       BlockException e) throws Exception {
        //设置响应状态码
        response.setStatus(429);
        //设施设备响应编码格式
        response.setContentType("text/html;charset=UTF-8");
        //设置输出流对象
        PrintWriter out = response.getWriter();
        String msg ="访问太过频繁,反应不过来啦!666";//默认为限流异常(直接和关联方式)
        if (e instanceof DegradeException){//熔断异常
            msg = "服务不可用,稍后再访问吧!";
        }
        if (e instanceof AuthorityException){//授权异常
            msg = "您已被拉入黑名单,无法访问该资源";
        }
        out.println(msg);
        out.flush();
        out.close();
    }
}

第三步:测试

 

我们该可以通过设置请求头内容进行授权限流

在自定义RequestOriginParser实现类获取请求头信息

@Component
public class DefaultRequestOriginParser implements RequestOriginParser {
    /**
     * 这个方法基于业务规则对请求数据进行解析
     * */
    @Override
    public String parseOrigin(HttpServletRequest request) {
        //1.解析请求参数,并返回参数值,然后将这个值应用在Sentinel的授权规则上
//        String origin = request.getParameter("origin");
//        return origin;
        //2.解析请求头,并返回参数值,然后将这个值应用在Sentinel的授权规则上
        String token = request.getHeader("token");
        System.out.println(token);
        return token;
        //3.解析ip地址,并返回参数值,然后将这个值应用在Sentinel的授权规则上
//        String ip = request.getRemoteAddr();
//        System.out.println("ip地址:"+ip);
//        return ip;
    }
}

配置授权限流信息

以为请求头无法在地址栏填写,我们使用http文件,token的值为AAA

 

 只有AAA才能访问/provider/sentinel01资源,因为只有AAA在白名单里

我们还可以通过获取调用者的ip来进行授权限流

 在自定义RequestOriginParser实现类获取ip信息,并在控制台打印

@Component
public class DefaultRequestOriginParser implements RequestOriginParser {
    /**
     * 这个方法基于业务规则对请求数据进行解析
     * */
    @Override
    public String parseOrigin(HttpServletRequest request) {
        //1.解析请求参数,并返回参数值,然后将这个值应用在Sentinel的授权规则上
//        String origin = request.getParameter("origin");
//        return origin;
        //2.解析请求头,并返回参数值,然后将这个值应用在Sentinel的授权规则上
//        String token = request.getHeader("token");
//        System.out.println(token);
//        return token;
        //3.解析ip地址,并返回参数值,然后将这个值应用在Sentinel的授权规则上
        String ip = request.getRemoteAddr();
        System.out.println("ip地址:"+ip);
        return ip;
    }
}

配置授权限流规则,将127.0.0.1放入白名单

在浏览器输入ip为127.0.0.1进行测试

可以访问到/provider/sentinel01资源

在浏览器输入ip为localhost时,就报错了,因为后端控制器输出的ip为0.0.0.0.0.1

注意:不能在http文件进行测试,因为idea可能会把localhost和127.0.0.1绑定在一起

请求的底层实现原理

第一步:从Tomcat的线程池获取一个线程

第二步:通过I/O对象读取http协议中的请求数据

第三步:解析http中的数据(请求头,请求行,请求体)

第四步:创建请求对象(request),响应对象(response),然后对请求数据进行封装

第五步:通过Filter对象对请求进行过滤

第六步:将合法的请求交给Servlet去处理(拦截器/controller..)

第七步:处理结束返回响应数据并传递给客户端

常见问题

何为熔断

让外部应用停止对该资源的访问,类似跳闸,前方施工请绕行

为什么要使用熔断

当一些服务平均响应时间太长或经常抛出异常,这儿样可能会造成调用链堆积,从而导致系统崩溃

Sentinel限流异常的顶底父类

BlockException

Sentinel降级抛出的异常是哪个类

DegradeException

Sentinel出现异常的处理接口是哪个

BlockExceptionHandler,此接口阿里有默认实现,我们也可以自定义此接口实现类

 第一个类DefaultBlocKExceptionHandler为阿里默认异常处理实现类

第二个类为我们自定义的实现类,注意,此类要交给Spring容器管理

Sentinel降级策略都有哪些

慢调用比例,异常比例,异常数

底层基于什么对热点数据进行限流

AOP

假如你去设计Sentinel,你将如何判定哪些数据是热点数据

LRU算法

java中是否有直接封装了LRU算法的类

有,LinkHashMap

你了解的系统限流规则都有哪些

cpu,RT,QPS,线程数等

如何理解Sentinel中的授权规则

对资源的访问限制,不是基于频次,而是基于中自定义黑白名单

Sentinel中解析黑白名单的接口是谁

RequestOriginParser

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值