07_sentinel—QPS—流控规则

sentinel—QPS—流控规则

流控规则

应用场景:秒杀 大促 下单 订单回流处理

在这里插入图片描述

QPS(query per second) 每秒请求数,就是说服务器在一秒的时间内处理了多少个请求

controller再加个请求

@RequestMapping("flow")
public String flow(){
    return  "正常访问";
}

在这里插入图片描述

这是如果你快速访问 http://localhost:8861/order/flow 就会显示

Blocked by Sentinel (flow limiting)

自定义流控信息

@RequestMapping("flow")
@SentinelResource(value = "flow",blockHandler = "flowBlockHandler")
public String flow(){
    return  "正常访问";
}
public String flowBlockHandler(BlockException e){
    return  "流控";
}

重启后 规则就没了 得重新设置 后续设置持久化

在这里插入图片描述

sentinel—并发线程数—流控规则

并发线程数用于保护业务线程池不被慢调用耗尽

Sentinel并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号呈隔离。并发数控制通常在调用端进行配置。

controller层添加代码

@RequestMapping("flowThread")
@SentinelResource(value = "flowThread",blockHandler = "flowBlockHandler")
public String flowThread() throws InterruptedException {
    TimeUnit.SECONDS.sleep(5);
    return  "正常访问";
}

//上面先新添加的  下面是原来的 为了直观我就放上来了


public String flowBlockHandler(BlockException e){
    return  "流控";
}

控制台设置

在这里插入图片描述

两个浏览器访问 http://localhost:8861/order/flowThread

出现结果 一个再访问 另一个就会被流控的现象
在这里插入图片描述

sentinel—BlockException统一异常处理

不想老是用@SentinelResource 来处理异常的话,可以定义一个BlockException统一异常处理,每一个方法的异常处理结果一样就适用,每一个方法的异常处理结果不想一样就不适用

1.加统一返回结果类 Result

package com.tian.order.domain;

public class Result<T> {
    private Integer code;
    private String msg;
    private T data;

    public Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static Result error(Integer code, String msg){
        return new Result(code,msg);
    }
}

2.加统一处理类MyBlockExceptionHandler

package com.tian.order.exception;

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 com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tian.order.domain.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
    Logger log= LoggerFactory.getLogger(this.getClass());
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse response, BlockException e) throws Exception {
        //e.getRule() 资源 规则的信息信息
        log.info("BlockExceptionHandler BlockException============="+e.getRule());
        Result r=null;
        if(e instanceof FlowException){
            //流控
            r=Result.error(100,"接口限流了");
        }else if(e instanceof DegradeException){ //降级
            r=Result.error(101,"服务降级了");
        }
        else if(e instanceof ParamFlowException){
            r=Result.error(102,"热点参数限流了");
        }
        else if(e instanceof SystemBlockException){
            r=Result.error(103,"触发系统保护规则了");
        }
        else if(e instanceof AuthorityException){
            r=Result.error(104,"授权规则不通过");
        }

        //返回json数据
        response.setStatus(500);
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        new ObjectMapper().writeValue(response.getWriter(),r);
    }
}

3.注释掉@SentinelResource

  @RequestMapping("flow")
    //@SentinelResource(value = "flow",blockHandler = "flowBlockHandler")
    public String flow(){
        return  "正常访问";
    }

4.控制台添加流控规则

5.访问 http://localhost:8861/order/flow

快速访问页面出现 {"code":100,"msg":"接口限流了","data":null}

sentinel—关联流控模式

在这里插入图片描述

应用场景

对数据库又增 又查的 那么就对增(插入)增加这个规则,让查询被流控

例 生成订单访问量大的话就让查询订单限流

controller层 代码

   @RequestMapping("/add")
    public String add(){
        System.out.println("下单成功!");
        return "生成订单";
    }

    @RequestMapping("/get")
    public String get(){
        return "查询订单";
    }

控制台增加规则

在这里插入图片描述

访问 http://localhost:8861/order/add (1s中3次以上)

再访问 http://localhost:8861/order/get 出现限流

sentinel—链路流控模式

           getUser
            /   \
           /     \
   /order/test1  /order/test2 

上图中来自入口/order/test1和/order/test2的请求都调用到了资源getUser,Sentinel允许只根据某个入口的统计信息对资源限流

1.service层

public interface IOrderService {
    String getUser();
}
@Service
public class OrderServiceImpl implements IOrderService{
    //使用了@SentinelResource,就不会被全局统一异常处理了
    @SentinelResource(value = "getUser",blockHandler = "blockHandlerGetUser")
    public String getUser() {
        return "查询用户";
    }

    public String blockHandlerGetUser(BlockException e) {
        return "流控用户";
    }
}

2.controller层

    @Autowired
    IOrderService orderService;

    @RequestMapping("/test1")
    public String test1(){
        return orderService.getUser();
    }

    @RequestMapping("/test2")
    public String test2(){
        return orderService.getUser();
    }

3.控制台配置规则

在这里插入图片描述

访问 http://localhost:8861/order/test1 和 http://localhost:8861/order/test2

发现链路模式不生效,配置文件添加

spring.cloud.sentinel.web-contenxt-unity:false # 默认将调用链收敛

重启访问 发现/order/test1随便快速点击访问都可以,但/order/test2会被流控

sentinel—流控效果介绍

在这里插入图片描述

sentinel—预热流控效果

  • 对激增流量的处理
比如秒杀活动,一下子很多流量访问一个资源 ,这个时候就可以用预热流控,
效果是 先让一部分人进来,经过缓存(例如redis),如果没有就去数据库,
然后数据库再把值缓存到redis中,那后面慢慢进来的就会去redis层查,没有的去数据库查,数据库再慢慢补全查询记录到redis。

冷加载因子: codeFactor默认是3,即请求QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的QPS 阈值。

在这里插入图片描述

访问 http://localhost:8861/order/flow 快速点击 发现刚开始没几下就限流了,后面快速点击几十下都不限流

sentinel—排队等待

  • 对脉冲流量的处理

1s10个请求 4个线程

快速失败结果

在这里插入图片描述

设置为排队等待 先让多的请求等待5s,等在空闲的时间再执行这些请求,超过时间则不执行

在这里插入图片描述

排队等待结果 (完全利用了空闲时间)

在这里插入图片描述

sentinel—熔断降级规则

  • 慢调用比例

测试代码

@RequestMapping("flowThread")
//@SentinelResource(value = "flowThread",blockHandler = "flowBlockHandler")
public String flowThread() throws InterruptedException {
    TimeUnit.SECONDS.sleep(2);
    return  "正常访问";
}

启动 控制台配置规则

在这里插入图片描述

  • 异常比例
@RequestMapping("/err")
public String err(){
    int i=1/0;
    return "hello";
}

启动 控制台配置规则

在这里插入图片描述

  • 异常数

在这里插入图片描述

sentinel—整合openfeign降级

  • 搭建环境

order-openfeign-sentinel模块

1.依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--    nacos服务注册发现 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!--   添加openfeign依赖   前提要有springcloud依赖支持  -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.service层 StockFeignService

@FeignClient(value = "stock-nacos",path = "/stock")
public interface StockFeignService {
		
    //和stock-nacos模块中的一个方法一样
    @RequestMapping("/reduct")
    public String reduct2();

}

3.controller层

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    StockFeignService stockFeignService;

    @RequestMapping("/add")
    public String add(){
        System.out.println("下单成功!");
        String msg = stockFeignService.reduct2();
        return "hello feign"+msg;
    }
}

4.配置文件

server:
  port: 8041
#应用名称 nacos会将该名称当作服务名称
spring:
  application:
    name: product-service
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        username: nacos
        password: nacos
        namespace: public

5.主启动类

@SpringBootApplication
@EnableFeignClients
public class OrderNacosApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderNacosApplication.class,args);
    }

}

stock-nacos模块

controller层

@RequestMapping("/stock")
public class StockController {

@RequestMapping("/reduct2")
    public String reduct2(){
        int i=1/0;
        System.out.println("扣减库存");
        return "扣减库存"+port;
    }
}

访问测试 http://localhost:8041/order/add 页面报500

整合sentinel

order-openfeign-sentinel模块

1.导入依赖

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

2.编写配置文件

feign:
  sentinel:
    # openfeign整合sentinel
    enabled: true  #默认是false

3.编写降级方法 StockFeignServiceFallback

@Component
public class StockFeignServiceFallback implements StockFeignService{
    public String reduct2() {
        return "降级啦!!!";
    }
}

4.StockFeignService接口调用

@FeignClient(value = "stock-nacos",path = "/stock",fallback = StockFeignServiceFallback.class)
public interface StockFeignService {

    @RequestMapping("/reduct")
    public String reduct2();

}

5.访问测试 http://localhost:8041/order/add 页面显示 hello feign降级啦!!!

sentinel—热点参数流控

1.controller添加代码

/**
     * 热点规则,必须使用@SentinelResource
     * @param id
     * @return
     */
@RequestMapping("/get/{id}")
@SentinelResource(value = "getById",blockHandler = "HotBlockHander")
public String getById(@PathVariable Integer id){
    System.out.println("正常访问");
    return "正常访问";
}

public String HotBlockHander(@PathVariable Integer id,BlockException e){
    return "热点异常处理";
}

2.控制台配置规则

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.测试访问

现象 http://localhost:8861/order/get/2 无论你请求多快都可以访问
http://localhost:8861/order/get/1 请求快了页面就显示 热点异常处理

sentinel—系统保护规则

在这里插入图片描述

在这里插入图片描述

  • CPU usage (1.5.0+版本)︰当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0),比较灵敏。
  • 平均RT: 当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数: 当单台机器上所有入口流呈的并发线程数达到阈值即触发系统保护。
  • 入口QPS: 当单台机器上所有入口流量的QPS达到阈值即触发系统保护。

sentinel—规则持久化

  • 原始模式

好处 无依赖

坏处 应用重启规则就会消失,仅用于简单测试,不能用于生产环境

  • 拉模式
  • 推模式 (建议!!!)

1.配置规则

在这里插入图片描述

在这里插入图片描述

[{
    "resource": "/order/flow",
    "controlBehavior": 0,
    "count":2,
    "grade":1,
    "limitApp":"default",
    "strategy":0
}]

在这里插入图片描述

order-sentinel项目添加依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

编写配置

server:
  port: 8861
spring:
  application:
    name: order-sentinel
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8888
      web-context-unify: false   # 默认将调用链收敛
      datasource:
        flow-rule:
          nacos:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            dataId: order-sentinel-flow-rule
            rule-type: flow

访问 http://localhost:8861/order/flow 已经有流控规则了,只要你刷新快就会被流控

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值