04SCA--Sentinel简述

限流算法: 计数器、令牌桶、漏斗算法,滑动窗口算法(sentinel)
使用限流和熔断的原因: 访问流量大,资源处理不足
限流:高并发情况下,对流量进行(部分)限制
熔断:全部被动
降级:部分主动服务响应速度慢一些②服务不稳定,经常出现异常

Sentinel (分布式系统的流量防卫兵)(观察者模式)

下载及启动

下载网址:https://github.com/alibaba/Sentinel/releases

在这里插入图片描述

 下载文件目录下打开小黑窗口,执行如下命令:
当然也可以通过Idea启动该服务,idea启动sentinel,mysql,nacos常用配置_闪耀太阳de超级piracy的博客-CSDN博客

java -Dserver.port=8180 -Dcsp.sentinel.dashboard.server=localhost:8180 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar

-Dserver.port=8180   制定启动服务的端口
-Dcsp.sentinel.dashboard.server=localhost:8180  制定控制台地址
-Dproject.name=sentinel-dashboard  制定控制台名称
-jar sentinel-dashboard-1.8.1.jar  执行jar文件

访问测试,密码和用户名都是sentinel 

 

Sentinel流控(限流)使用流程

添加依赖
添加sentinel限流依赖,此时项目中会注入一个拦截器HandlerInterceptor的实现类AbstractSentinelInterceptor(spring mvc)对象,对请求进行拦截,记录请求的单位时间的访问次数.HandlerInterceptor接口有三个默认方法,preHandle()请求在访问controller前执行;

postHandle()请求访问完controller时执行,afterCompletion()返回数据给前段时执行

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

 配置文件bootstrap.yml,添加sentinel配置

spring:
  cloud:
    sentinel:
      transport:
         dashboard: localhost:8180 # 指定sentinel控制台地址。

创建一个用于演示限流操作的Controller对象,

@RestController
@RequestMapping("/provider")
public class ProviderSentinelController {
       @GetMapping("/sentinel01")
       public String doSentinel01(){
           return "sentinel 01 test  ...";
       }
}

浏览器访问,sentinel设置限流规则,进行测试

在这里插入图片描述

 在这里插入图片描述

 反复刷新访问你的服务,检测是否有限流信息输出:

在这里插入图片描述

自定义限流异常处理

抛出的异常是BlockException,通过BlockExceptionHandler的实现类DefaultBlockExceptionHandler对异常进行处理,若对异常处理方案不满意,可以自己写实现类对异常进行处理,底层会调用sentinelWebMvcConfig类自动注入该实现类

/**
 * 自定义BlockException的异常处理对象
 */
@Component
public class DefaultSentinelExceptionHandler
        implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       BlockException e) throws Exception {
        //设置响应内容类型,以及告诉高客户端应该按什么编码显示数据
        response.setContentType("text/html;charset=utf-8");
        //设置响应状态码(将来可以基于这个状态码进行相关处理)
        response.setStatus(429);
        //获取响应输出流对象
        PrintWriter out = response.getWriter();
        String msg="访问太频繁,稍等片刻再访问.";
        //判断e指向的对象是否为DegradeException类型(降级)
        if(e instanceof DegradeException){//DegradeException 熔断异常
            msg="服务暂时不可用,稍等片刻再访问.";
        }else if(e instanceof AuthorityException){//AuthorityException 表示授权异常
            msg="您无权访问这个资源";
        }
        out.print(msg);
        out.flush();
        out.close();
    }
}

Sentinel限流流控规则

在这里插入图片描述

 阈值类型:
QPS(Queries Per Second):当调用相关url对应的资源时,QPS达到单机阈值时,就会限流。
线程数:当调用相关url对应的资源时,线程数达到单机阈值时,就会限流。

限流效果:
快速失败:访问不成功直接返回异常处理结果
Warm Up:访问过大,可以在指定时间内处理这些请求
排队等待:访问依次排队处理

限流模式:
直接模式: 对某资源的访问进行限流
关联模式: 当核心业务流量非常大时,可以对一些不那么重要的业务进行限流,保证核心业务正常运行

在这里插入图片描述
链路模式: 某业务占时还在修复时,占时不对外开放(Aop)
准备一类资源Service类(SentinelResourceAspect切面,对该目标方法进行)

package com.jt.provider.service;
@Service
public class ResourceService{
    /**sentinelResource注解描述的方法为一个切入点方法,
    * 也就是说对此方法进行访问时,进行一些限流操作.
    *具体的限流动作会放在切面的通知方法中.*/
    @SentinelResource("doGetResource")
    public String doGetResource(){
        return "doGetResource";
    }
}

 准备controller的两个不通方法对同一资源进行调用

    @Autowired
    private ResourceService resourceService;
    @GetMapping("/sentinel03")
    public String doSentinel03(){
        resourceService.doGetResource();
        return "sentinel 03 test";
    }
    
    @GetMapping("/sentinel04")
    public String doSentinel04(){
       resourceService.doGetResource();
       return "sentinel 04 test";
    }

配置打散链路聚焦 (其他版本可能不需要打散链路聚焦)

spring:
    cloud:
        sentinel:
            web-context-unify: false #打散链路聚焦

访问,sentinel设置流控规则
在这里插入图片描述

访问测试,链路限流异常

 自定义链路限流处理

HandlerInterceptor接口有三个默认方法,preHandle()请求在访问controller前执行;postHandle()请求访问完controller时执行,afterCompletion()返回数据给前段时执行

在这里插入图片描述

/**
 * 通过此类处理由@SentinelResource注解描述的方法出现的限流异常.
 */
@Slf4j
@Component
public class ResourceBlockHandler {
    /**
     * 这里的异常处理方法有要求:
     * 1)修饰符 public static
     * 2)返回值类型要与@SentinelResource注解描述方法返回值类型相同
     * 3)参数列表要与@SentinelResource注解描述方法参数列表相同,
     * 可以再最后多添加一个BlockException参数
     */

    public static String doHandle(BlockException ex){
        log.error("被限流了.....,{}",ex);
        return "访问太频繁了....";
    }
}
@SentinelResource(value="doGetResource",
        blockHandlerClass = ResourceBlockHandler.class,
        blockHandler = "doHandle")
public String doGetResource(){
    return "do get resource";
}

自定义拦截器对象对特定请求进行拦截

自定义拦截器

/**
 * 自定义spring mvc中的拦截器对象,基于此对象对请求和响应进行拦截
 */
public class TimeInterceptor implements HandlerInterceptor {
    /**
     * 此方法会在目标controller方法执行之前执行,可以这里对请求进行
     * 预处理,然后在交给后端的controller,同时也可以基于此方法的
     * 返回值,决定请求是继续放行,还是到此结束.
     * 在当前应用中,我们基于访问时间通过拦截器对请求进行限制.
     * @param request
     * @param response
     * @param handler
     * @return  true表示放行,false表示拦截.
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler)
            throws Exception {
        System.out.println("==preHandle==");
        //1.获取当前时间
        LocalTime now = LocalTime.now();
        //2.获取当前时间的对应的小时
        int hour=now.getHour();
        System.out.println("hour="+hour);
        //3.判断时间是否在允许范围之内
        if(hour<10||hour>=23){
            throw new RuntimeException("请在允许时间访问6~23");
        }
        return true;
    }
}

配置拦截器(位于配置类/启动类中)

/**
 * Spring MVC 配置类
 */
@Configuration
public class SpringWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TimeInterceptor())
                .addPathPatterns("/provider/sentinel01");
    }
}

Sentinel降级

降级:部分主动服务响应速度慢一些②服务不稳定,经常出现异常 ③

 访问太频繁,服务就会自动降级,抛出DegradeException异常
可以对该异常处理进行修改

/**
 * 自定义BlockException的异常处理对象
 */
@Component
public class DefaultSentinelExceptionHandler
        implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       BlockException e) throws Exception {
        //设置响应内容类型,以及告诉高客户端应该按什么编码显示数据
        response.setContentType("text/html;charset=utf-8");
        //设置响应状态码(将来可以基于这个状态码进行相关处理)
        response.setStatus(429);
        //获取响应输出流对象
        PrintWriter out = response.getWriter();
        String msg="访问太频繁,稍等片刻再访问.";
        //判断e指向的对象是否为DegradeException类型(降级)
        if(e instanceof DegradeException){//DegradeException 熔断异常
            msg="服务暂时不可用,稍等片刻再访问.";
        }else if(e instanceof AuthorityException){//AuthorityException 表示授权异常
            msg="您无权访问这个资源";
        }
        out.print(msg);
        out.flush();
        out.close();
    }
}

Sentinel热点规则(AOP)

@SentinelResource(value="resource", blockHandlerClass = ResourceBlockHandler.class, blockHandler = "doHandle")定义目标方法,切面SentinelResourceAspect
LRU策略:最近最少使用策略(缓存淘汰,热点数据限流),java中LinkedHashMap内置了该算法

簇点链路中设置制定参数进行限流

在这里插入图片描述

 热点规则中对制定参数的值进行限流

 在这里插入图片描述

 Sentinel系统规则

监控服务器的CPU、内存、IO等的使用率,主要目的就是保证服务器正常的运行,针对于所有的资源

在这里插入图片描述

 Sentinel授权规则

修改请求解析器,获取请求ip并返回

@Component
public class DefaultRequestOriginParser
        implements RequestOriginParser {
    /**这个方法中基于业务规则对请求数据进行解析,然后进行授权
     * 1)可以对请求参数进行解析
     * 2)可以对请求头数据进行解析
     * 3).......*/
    @Override
    public String parseOrigin(HttpServletRequest request) {

        //对请求参数进行解析,并返回参数值,然后将这个值应用在sentinel的授权规则中
        //http://ip:port/path?origin=xxx
        //String origin=request.getParameter("origin");//这里的名字为参数名
        //return origin;

        //对请求头中的数据进行解析,请求头的名字为token,然后基于值进行授权。
        //String token=request.getHeader("token");
        //return token;

        //对请求ip地址进行解析,然后获取ip值进行授权。
        String ip = request.getRemoteAddr();
        int port=request.getRemotePort();
        System.out.println("ip="+ip);
        return ip;
    }
}

在sentinel控制台定义授权规则 

在这里插入图片描述

 Sentinel授权异常如上降级异常中的AuthorityException

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值