SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第1张图片

文章目录

    • Sentinel
    • 常见的容错思路
    • Sentinel流量控制规则
    • sentinel 自定义异常 + @sentinelresources 注解使用
    • Feign整合Sentinel
      • **面试题:结合Feign后,你在项目中的降级方法中会实现什么样的操作/功能?**

Sentinel

Sentinel是阿里巴巴开源的分布式系统流量防卫防护组件,主要对分布式系统中的流量进行控制、熔断降级等保护操作。Sentinel的目标是成为互联网级别分布式系统的流量防卫防护组件,它与系统的各个部分集成,保护着系统的入口和出口。

概念:
Sentinel是一个分布式系统的流量防卫防护组件,它通过对分布式系统中的流量进行控制、熔断降级等保护操作,保障系统的稳定性和可用性。

背景:
随着分布式系统的广泛应用,系统的复杂度和耦合度越来越高,系统中的流量控制和保护变得越来越重要。Sentinel正是在这样的背景下诞生的,它通过流量控制、熔断降级等手段,保护着分布式系统的入口和出口,保障系统的稳定性和可用性。

运用:
Sentinel可以运用于各种分布式系统中,例如微服务架构、SOA架构等。它对系统的各个部分进行流量控制、熔断降级等保护操作,从而提高系统的可用性和稳定性。

定位:
Sentinel主要定位于分布式系统的流量防卫防护组件,它与系统的各个部分集成,对系统的入口和出口进行保护。它不仅提供流量控制、熔断降级等基础功能,还支持自定义策略和插件扩展,可以满足不同场景下的需求。

使用:
Sentinel的使用非常简单,可以通过配置文件或API进行配置和调用。它提供了丰富的统计数据和监控信息,方便用户对系统进行监控和管理。同时,Sentinel还提供了多种语言的客户端库,方便用户进行集成和使用。

API:
Sentinel提供了丰富的API供用户进行自定义策略和插件扩展。它的API包括流量控制、熔断降级、系统调用等各个方面。用户可以通过调用这些API实现自定义的流量控制和熔断降级策略。
Sentinel可以通过这些 API 来设置流量控制规则、获取系统状态、执行流量控制等操作。例如,FlowRuleManager.loadRules() 方法可以加载流量控制规则;SystemStateManager.getBlockQpsInInterval(String resource, Duration interval) 方法可以获取资源在特定时间段内的被限流次数等。

总结:
Sentinel是一个分布式系统的流量防卫防护组件,它通过对分布式系统中的流量进行控制、熔断降级等保护操作,保障系统的稳定性和可用性。它具有简单易用、灵活可扩展等特点,可以适用于各种分布式系统中。


常见的容错思路

​ 要防止雪崩的扩散,我们就要做好服务的容错,容错说白了就是保护自己不被猪队友拖垮的一些措施, 下面介绍常见的服务容错思路和组件。

常见的容错思路

常见的容错思路有隔离、超时、限流、熔断、降级这几种,下面分别介绍一下。

  • 隔离机制: 比如服务A内限制有100个线程, 现在服务A可能会调用服务B,服务C,服务D.我们在服务A进行远程调用的时候,给不同的服务分配固定的线程,不会把所有线程都分配给某个微服务. 比如调用服务B分配30个线程,调用服务C分配30个线程,调用服务D分配40个线程. 这样进行资源的隔离,保证即使下游某个服务挂了,也不至于把服务A的线程消耗完。比如服务B挂了,这时候最多只会占用服务A的30个线程,服务A还有70个线程可以调用服务C和服务D.

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第2张图片

  • 超时机制: 在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应,

    就断开请求,释放掉线程。

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第3张图片

  • 限流机制: 限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到

    的需要限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第4张图片

  • 熔断机制: 在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整

    体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第5张图片

服务熔断一般有三种状态:

  • 熔断关闭状态(Closed)

服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制

  • 熔断开启状态(Open)

后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法

  • 半熔断状态(Half-Open)

尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预

期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断开启状

态。

  • 降级机制: 降级其实就是为服务提供一个兜底方案,一旦服务无法正常调用,就使用兜底方案。

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第6张图片


Sentinel流量控制规则

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第7张图片

Sentinel具有流控、热点、降级、授权和系统规则保护等功能。

流控是指控制分布式系统的流量,防止系统被过大的流量击垮。Sentinel可以通过设置流量控制阈值,对超过阈值的流量进行限流操作。

热点是指系统中访问频率较高的部分,通常是系统的瓶颈所在。Sentinel可以通过热点限流功能,对热点流量进行限制,避免热点流量过大导致系统崩溃。

降级是指当系统出现故障或响应过慢时,通过降低部分功能或服务的等级,保证整个系统的可用性。Sentinel可以通过降级功能,对故障的服务进行降级处理,避免故障影响整个系统的运行。

授权是指对不同的用户或服务设置不同的访问权限,保证系统的安全性。Sentinel可以通过设置黑白名单规则,对指定的用户或服务进行授权操作。

系统规则保护是指对系统的入口和出口进行保护,防止系统被恶意攻击或滥用。Sentinel可以通过设置系统保护规则,对系统的入口和出口进行防护操作。


sentinel 自定义异常 + @sentinelresources 注解使用

Sentinel 可以通过自定义异常和 @SentinelResource 注解来提供更加灵活的保护机制。

首先,Sentinel 允许用户自定义异常处理类,通过继承 BlockException 类并重写其中的方法,可以定制异常处理逻辑。同时,在定义资源时,可以使用 @SentinelResource 注解来指定异常处理类,以便在发生异常时执行自定义的异常处理逻辑。

  • FlowException 限流异常

  • DegradeException 降级异常

  • ParamFlowException 参数限流异常

  • AuthorityException 授权异常

  • SystemBlockException 系统负载异常

在shop-order-server项目中定义异常返回处理类

package cn.wolfcode.error;
@Component
public class ExceptionHandlerPage implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        response.setContentType("application/json;charset=utf-8");
        ResultData data = null;
        if (e instanceof FlowException) {
            data = new ResultData(-1, "接口被限流了");
        } else if (e instanceof DegradeException) {
            data = new ResultData(-2, "接口被降级了");
        }else if (e instanceof ParamFlowException) {
            data = new ResultData(-3, "参数限流异常");
        }else if (e instanceof AuthorityException) {
            data = new ResultData(-4, "授权异常");
        }else if (e instanceof SystemBlockException) {
            data = new ResultData(-5, "系统负载异常了...");
        }
        response.getWriter().write(JSON.toJSONString(data));
    }
}
@Data
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
class ResultData {
    private int code;
    private String message;
}

其次,@SentinelResource 注解可以用于定义资源并提供可选的异常处理和 fallback 配置项。通过使用 @SentinelResource 注解,用户可以方便地将特定的类、方法或函数定义为资源,并在其中配置异常处理和 fallback 逻辑。这样,在系统运行时,Sentinel 可以自动对这些资源进行保护,确保系统的稳定性和可用性。

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。

其主要参数如下:

属性 作用
value 资源名称,必需项(不能为空)
entryType entry 类型,可选项(默认为 EntryType.OUT
blockHandler/blockHandlerClass blockHandler 对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
fallback/fallbackClass fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
1. 返回值类型必须与原函数返回值类型一致;
2.方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
3.fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
defaultFallback 默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
1. 返回值类型必须与原函数返回值类型一致;
2. 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
3. defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

定义限流和降级后的处理方法

直接将限流和降级方法定义在方法中

package cn.wolfcode.controller;
@RestController
@Slf4j
public class AnnoController {
    @RequestMapping("/anno1")
    @SentinelResource(value = "anno1",
            blockHandler="anno1BlockHandler",
            fallback = "anno1Fallback"
    )
    public String anno1(String name){
        if("wolfcode".equals(name)){
            throw new RuntimeException();
        }
        return "anno1";
    }
    public String anno1BlockHandler(String name,BlockException ex){
        log.error("{}", ex);
        return "接口被限流或者降级了";
    }
    //Throwable时进入的方法
    public String anno1Fallback(String name,Throwable throwable) {
        log.error("{}", throwable);
        return "接口发生异常了";
    }
}

Feign整合Sentinel

  1. 在shop-order-server项目的配置文件中开启feign对Sentinel的支持

    feign:
      sentinel:
        enabled: true
    
  2. 创建容错类

    @Component
    public class ProductFeignFallBack implements IProductFeginService {
        @Override
        public Product findByPid(Long pid) {
            Product product = new Product();
            product.setPid(-1L);
            product.setPname("兜底数据");
            product.setPprice(0.0);
            return product;
        }
    }
    
  3. 在feign接口中定义容错类

    @FeignClient(name = "product-service",fallback = ProductFeignFallBack.class)
    public interface ProductFeignApi {
        @RequestMapping("/product/{pid}")
        public Product findByPid(@PathVariable("pid") Long pid);
    }
    
  4. 停止所有 商品服务,重启 shop-order 服务,访问请求,观察容错效果

可能上面的案例并不是特别恰当,我们只是通过案例来演示Feign集成Sentinel实现降级的效果. 接下来我们具体更贴切的案例来讲解Feign降级的作用.

比如我们在购物的时候,查看商品详情页面的时候,里面包含库存信息,商品详情信息,评论信息,这个需求包含的微服务如下:

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel_第8张图片

假设现在评论服务宕机了,那是不是意味用户发出查看商品请求也无法正常显示了,商品都看不到了,那用户也无法进行下单的操作了. 但是对于用户来说,评论看不到并不影响他购物,所以这时候我们应该对评论服务进行及·降级处理,返回一个兜底数据(空数据),这样用户的查看商品请求能正常显示,只是评论数据看不到而已,这样的话,用户的下单请求也不会受到影响。

面试题:结合Feign后,你在项目中的降级方法中会实现什么样的操作/功能?

  • 记录操作日志,业务日志
  • 尝试重试操作
  • 记录操作失败信息(MQ),方便后续人工介入
  • 异常提示

你可能感兴趣的:(SpringCloud,JAVA,后端,spring,cloud,sentinel)