SpringCloud Alibaba_Sentinel实现熔断与限流

文章目录

  • 安装Sentinel
    • 下载
    • 运行命令
    • 访问sentinel管理界面
  • 流控规则
    • 基本介绍
  • 降级规则
    • RT
    • 异常比例
    • 异常数
  • 热点key限流
    • 配置
    • 参数例外项
  • 系统规则
  • @SentinelResource
    • 按照资源名称+流控规则限流+后续处理
    • 按照url+流控规则限流+后续处理
    • 现阶段问题
    • 自定义限流处理逻辑
  • 服务熔断
    • 消费侧Sentinel整合Ribbon+OpenFeign+FallBack
      • Ribbon
      • OpenFeign
  • 规则持久化

安装Sentinel

sentinel组件由两个部分组成:

  • 核心库(Java客户端),不依赖任何框架和库,能够运行于Java运行时环境,同时对SpringCloud等框架也有较好的支持。
  • 控制台(DashBoard)基于SpringBoot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器

下载

https://github.com/alibaba/Sentinel/releases

运行命令

java -jar sentinel-dashboard-1.7.2.jar

注意:8080端口不能被占用

访问sentinel管理界面

http://localhost:8080
账号密码:sentinel

流控规则

基本介绍

SpringCloud Alibaba_Sentinel实现熔断与限流_第1张图片

  • 资源名:唯一名称,默认请求路径
  • 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
  • 阈值类型/单机阈值
    • QPS(每秒请求数量):当调用该api的QPS达到阈值的时候,进行限流
    • 线程数:当调用该api的线程数达到阈值的时候,进行限流
  • 是否集群:不需要集群
  • 流控模式:
    • 直接:api达到限流条件时,直接限流
      SpringCloud Alibaba_Sentinel实现熔断与限流_第2张图片
    • 关联:当关联的资源达到阈值时,就限流自己
      SpringCloud Alibaba_Sentinel实现熔断与限流_第3张图片
    • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)
  • 流控效果
    • 快速失败:直接失败。抛异常
    • Warm up:根据coldfactor(冷加载因子,默认3)的值,从阈值/coldfactor,经过预热时长,才达到设置的QPS阈值
      SpringCloud Alibaba_Sentinel实现熔断与限流_第4张图片
      如:秒杀系统在开启瞬间,会有很多流量上来,很可能把系统打死,预热方式就是为了保护系统,可慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。
    • 排队等待:匀速排队,让请求以匀速通过,阈值类型必须设置为QPS,否则无效
      SpringCloud Alibaba_Sentinel实现熔断与限流_第5张图片
      SpringCloud Alibaba_Sentinel实现熔断与限流_第6张图片

降级规则

RT

SpringCloud Alibaba_Sentinel实现熔断与限流_第7张图片

SpringCloud Alibaba_Sentinel实现熔断与限流_第8张图片
SpringCloud Alibaba_Sentinel实现熔断与限流_第9张图片

异常比例

在这里插入图片描述
SpringCloud Alibaba_Sentinel实现熔断与限流_第10张图片
SpringCloud Alibaba_Sentinel实现熔断与限流_第11张图片

异常数

SpringCloud Alibaba_Sentinel实现熔断与限流_第12张图片
SpringCloud Alibaba_Sentinel实现熔断与限流_第13张图片
SpringCloud Alibaba_Sentinel实现熔断与限流_第14张图片

热点key限流

配置

SpringCloud Alibaba_Sentinel实现熔断与限流_第15张图片

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                         @RequestParam(value = "p2",required = false) String p2)
{
    //int age = 10/0;
    return "------testHotKey";
}

返回异常不友好界面,blocked by sentinel

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                         @RequestParam(value = "p2",required = false) String p2)
{
    //int age = 10/0;
    return "------testHotKey";
}
public String deal_testHotKey (String p1, String p2, BlockException exception)
{
    return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
    }

自定义blockHandler,处理异常。

参数例外项

假如当p1的值等于5时,它的阈值可以达到200:
SpringCloud Alibaba_Sentinel实现熔断与限流_第16张图片
参数类型仅限于基本数据类型或者String

系统规则

SpringCloud Alibaba_Sentinel实现熔断与限流_第17张图片
SpringCloud Alibaba_Sentinel实现熔断与限流_第18张图片
系统配置管辖太宽泛,可能引起全局范围内的问题,不使用,危险。

@SentinelResource

按照资源名称+流控规则限流+后续处理

SpringCloud Alibaba_Sentinel实现熔断与限流_第19张图片

@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource()
{
    return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
}
public CommonResult handleException(BlockException exception)
{
    return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}

按照url+流控规则限流+后续处理

SpringCloud Alibaba_Sentinel实现熔断与限流_第20张图片

@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl()
{
    return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
}

现阶段问题

  • 系统默认,没有体现特定的业务要求
  • 自定义Handler与业务逻辑耦合
  • 每个业务逻辑都需要独自的兜底Handler,代码膨胀
  • 没有全局统一的处理方法

自定义限流处理逻辑

  • 自定义限流处理类
public class CustomerBlockHandler
{
    public static CommonResult handlerException(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----1");
    }
    public static CommonResult handlerException2(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----2");
    }
}
  • 修改@SentinelResource
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
        blockHandlerClass = CustomerBlockHandler.class,
        blockHandler = "handlerException2")
public CommonResult customerBlockHandler()
{
    return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
}

服务熔断

消费侧Sentinel整合Ribbon+OpenFeign+FallBack

  • pom

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>

<dependency>
    <groupId>com.alibaba.cloudgroupId>
    <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
  • yml
server:
  port: 84

spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719

#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider

# 激活Sentinel对Feign的支持
feign:
  sentinel:
    enabled: true

Ribbon

  • 配置RestTemplate
@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}
  • 业务逻辑
@RequestMapping("/consumer/fallback/{id}")
//fallback只负责业务异常
//blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
        exceptionsToIgnore = {IllegalArgumentException.class})
public CommonResult<Payment> fallback(@PathVariable Long id)
{
    CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

    if (id == 4) {
        throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
    }else if (result.getData() == null) {
        throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
    }

    return result;
}
//本例是fallback
public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
    Payment payment = new Payment(id,"null");
    return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
}
//本例是blockHandler
public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
    Payment payment = new Payment(id,"null");
    return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
}

OpenFeign

  • Service
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
  • FallBackService
@Component
public class PaymentFallbackService implements PaymentService
{
    @Override
    public CommonResult<Payment> paymentSQL(Long id)
    {
        return new CommonResult<>(44444,"服务降级返回,---PaymentFallbackService",new Payment(id,"errorSerial"));
    }
}

  • Controller
@Resource
private PaymentService paymentService;

@GetMapping(value = "/consumer/paymentSQL/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandler")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
{
    return paymentService.paymentSQL(id);
}

规则持久化

一旦重启应用,sentinel规则消失,生产环境需要将配置规则进行持久化。
将限流规则持久进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看得到,只要Nacos里面的配置不删除,针对8401上的流控规则持续有效

  • pom
<!--SpringCloud ailibaba nacos -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  • yaml
server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

management:
  endpoints:
    web:
      exposure:
        include: '*'

feign:
  sentinel:
    enabled: true # 激活Sentinel对Feign的支持
  • 添加Nacos业务规则配置
    SpringCloud Alibaba_Sentinel实现熔断与限流_第21张图片
    SpringCloud Alibaba_Sentinel实现熔断与限流_第22张图片
    SpringCloud Alibaba_Sentinel实现熔断与限流_第23张图片

你可能感兴趣的:(Spring,java,spring,spring,boot,中间件,分布式)