Sentinel~服务容错

目录

 

1 前言

2 Sentinel

2.1 微服务集成 Sentinel

2.2 安装Sentinel控制台

2.3  Sentinel简单使用

2.4  @SentinelResource的使用

2.5 feign整合sentinel实现容错


1 前言

在分布式系统中,由于网络原因或者自身的原因,服务一般无法保证100%可用。如果一个服务出现了问题,那么调用这个服务就会出现线程阻塞的情况,此时若有大量的请求进来,就会出现多条线程阻塞等待、进而导致服务瘫痪。所以我们一般在服务中进行服务容错,来对出现这种问题的服务进行处理。

常见的容错组件:

  • Hystrix

        Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性和容错性。

  • Resilience4j

        Resilience4j一款非常轻量简单,并且文档非常清晰,丰富的熔断工具,这也是Hystrix官方推荐的替代产品。不仅如此,Resilience4j还原生支持Spring Boot1.x/2.x,而且监控也支持和prometheus等多款主流产品进行整合

  • Sentinel

Sentinel是阿里巴巴开源的一款断路器的实现。

2 Sentinel

Sentinel是阿里开源的一套用于服务容错的综合性解决方案。它以流量为切入点、从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。

Sentinel的特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel分为两个部分

核心库(java客户端)不依赖任何框架/库。都够运行所有的java运行时环境,同时对Dubbo/Spring Cloud等框架也有较好的支持。

控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器。

2.1 微服务集成 Sentinel

注意:此篇文章是基于之前文章来写的,直接看到这里会摸不着头脑

加入Sentinel相关依赖。

注意:如果是上游微服务调用下游微服务(比如:订单微服务>>>商品微服务),那么应该在上游微服务(订单微服务)中引入依赖。

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

2.2 安装Sentinel控制台

Sentinel提供一个轻量级的控制台、它提供机器发现、单机资源实时监控以及规则管理等功能。

1)下载地址:Releases · alibaba/Sentinel · GitHub

 2)找到下载路径,cmd进入后执行jar命令启动

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.4.jar

3)访问http://localhost:8080/#/login(默认用户名和密码都是sentinel)

4)编写配置文件 

sentinel:
  transport:
    port: 9999 #和控制台交流的端口,随意指定一个未使用的端口即可
    dashboard: localhost:8080 #指定控制台服务的地址
  eager: true #取消懒加载(否则服务启动之后,必须访问一次才能注册到sentinel中)

 5)启动微服务并且重新访问sentinel客户端

发现我们的订单服务已经注册上去了。

2.3  Sentinel简单使用

 sentinel会记录我们服务的请求,我们可以简单的对一个接口进行流控测试。如上图所示点击“流控”后。

流控:

1)QPS(先测试该接口一秒钟访问请求不超过2次)

 然后连续访问接口(1s内请求多次)就会发现被流控了

 2.4  @SentinelResource的使用

在定义了资源之后,我们可以通过Dashboard来设置限流和降级策略来对资源点进行保护。同时还能通过@SentinelResource来指定出现异常时的处理策略。@SentinelResource用于自定义资源,并提供可选的异常处理和fallback配置项。主要参数如下:

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

自定义异常:

@Service
@Slf4j
public class OrderServiceImpl2 {


    /**
     * 定义一个资源 并且定义当资源内部发生异常时的处理逻辑
     * blockHandler 定义当资源内部发生了BlockException应该进入的方法(捕获的是sentinel定义的异常)
     * fallback 定义当资源内部发生了Throwable应该进入的方法
     * @return
     */
    @SentinelResource(value = "message",
    blockHandler = "blockHandler",
    fallback = "fallback")
    public String message(String name) {

        return "SentinelResource";
    }

    /**
     * 当前方法的返回值必须和原方法一致
     * 允许在参数列表后面最后加入一个参数BlockException,用来接收原方法中发生的异常
     * @return
     */
    public String blockHandler(String name, BlockException e){

        //自定义异常处理逻辑
        log.info("触发了BlockException异常");
        return "BlockException";
    }

    /**
     * 当前方法的返回值必须和原方法一致
     * 允许在参数列表后面最后加入一个参数BlockException,用来接收原方法中发生的异常
     * @return
     */
    public String fallback(String name, Throwable e){
        //自定义异常处理逻辑
        log.info("触发了Throwable异常");
        return "Throwable";
    }
}

如上:定义了两个异常处理。一个是BlockException(针对Sentinel的异常会被捕捉),一个是

Throwable(针对业务异常)。以此来测试。我们可以先进行一个流控,让其触发Sentinel异常。

一秒钟之内点击多次,就会触发 Sentinel异常,随后进行访问:http://localhost:8091/order/message

    @RequestMapping("/order/message")
    public String message3(){
        return orderServiceImpl2.message("suibianla");
    }

 可见,已经捕获了我们的sentinel中的异常,那如果是业务逻辑异常呢?

可以将业务处理代码改为:

其余代码不变。然后继续访问。 

 可见fallback已经捕获到了业务逻辑异常。

这个时候可能有人发现了问题,一个方法就要写一个blockHandler异常和一个fallback异常。这样肯定是不可取的。所以Sentinel给我们提供了异常处理类,这样就不用每一个方法都去这样写了。就是将之前定义的两个异常方法抽取出来(方法必须变成静态的)。

@Slf4j
public class OrderBlockException {

    /**
     * 当前方法的返回值必须和原方法一致
     * 允许在参数列表后面最后加入一个参数BlockException,用来接收原方法中发生的异常
     * @return
     */
    public static String blockHandler(String name, BlockException e){
        //自定义异常处理逻辑
        log.info("触发了BlockException异常");
        return "触发了BlockException异常";
    }


}
@Slf4j
public class OrderFallbackException {

    /**
     * 当前方法的返回值必须和原方法一致
     * 允许在参数列表后面最后加入一个参数BlockException,用来接收原方法中发生的异常
     * @return
     */
    public static String fallback(String name, Throwable e){
        //自定义异常处理逻辑
        log.info("触发了Throwable异常");
        return "触发了Throwable异常";
    }
}

然后业务方法变为一下就可完成之前的功能:

    @SentinelResource(value = "message",
    blockHandlerClass = OrderBlockException.class,
    blockHandler = "blockHandler",
    fallbackClass = OrderFallbackException.class,
    fallback = "fallback")
    public String message(String name) {
        return "SentinelResource";
    }

2.5 feign整合sentinel实现容错

1)在配置文件中开启feign对Sentinel的支持

#开启feign对sentinel的支持
feign:
  sentinel:
    enabled: true

 2)编写容错类

import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @Author: liubujun
 * @Date: 2022/5/8 19:47
 */

//一旦feign远程调用出现问题,就会进入当前类中同名方法,执行容错逻辑
@Slf4j
@Service
public class ProductServiceFallbackFacyory implements FallbackFactory<ProductService> {
    @Override
    public ProductService create(Throwable throwable) {
        //throwable就是在feign调用过程中产生异常
        return new ProductService() {
            @Override
            public Product findById(Integer pid) {
                log.error("{}",throwable);
                Product product = new Product();
                product.setPid(-100);
                product.setPname("商品微服务出现异常,进入微服务当中");
                return product;
            }
        };

    }
}

3)在feign调用过程中声明

4)调用(若想模拟feign调用异常,只需关闭商品微服务即可) 

 错误异常控制台已经打印出来:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值