Spring Cloud微服务Sentinel+Apollo限流、熔断实战总结

在Spring Cloud微服务体系中,因为限流熔断组件Hystrix开源版本不在维护,所以国内很多有相似需求的公司已经将眼光转向阿里开源的Sentinel框架。而如下要介绍的正是做者最近两个月的真实项目实践过程,这中间被很多网络Demo示例级别水文误导过,为了以正视听特将实践过程加以总结,但愿可以帮到有相似须要的朋友!(PS:此文有点长,看下概念部分后能够点击关注+收藏,以备须要)python

1、Sentinel概述

在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得愈来愈长,这无疑会增长了整个系统的不可靠因素。在并发流量比较高的状况下,因为网络调用之间存在必定的超时时间,链路中的某个服务出现宕机都会大大增长整个调用链路的响应时间,而瞬间的流量洪峰则会致使这条链路上全部服务的可用线程资源被打满,从而形成总体服务的不可用,这也就是咱们常说的“雪崩效应”。spring

而在微服务系统设计的过程当中,为了应对这样的糟糕状况,最经常使用的手段就是进行”流量控制“以及对网络服务的调用实现“熔断降级”。所谓流量控制就是根据服务的承载能力指定一个策略,对必定时间窗口内的网络调用次数进行限制,例如1s内某个服务最多只能处理10个请求,那么1s内的第11+的请求会被被限制丢弃;而熔断降级的概念则是说在A服务→B服务调用过程当中,按照必定的规则A服务发现调用B服务常常失败或响应时间过长,若是触发了A服务对B服务调用的熔断降级规则,那么在必定时间窗口内,A服务在处理请求的过程当中对于B服务的调用将会直接在A服务的逻辑中被熔断降级,请求则不会经过网络打到B服务,从而避免A服务因为过长的超时时间致使自身资源被耗尽的状况发生。编程

虽然咱们知道以上两种手段很是有用,但若没有合适的技术来支持,就好像一句话说的“虽然明白不少道理,可是依然过很差这一辈子”同样。而Sentinel就是这样一种技术,它是阿里巴巴开源的一款客户端限流组件,能够与Spring Cloud微服务体系无缝地集成;而与之对应的是另一款Netflix公司推出的知名度也比较高的Hystrix组件,Hystrix也是Spring Cloud官方集成熔断限流组件,只不过相对于Sentinel来讲,Hystrix所提供的功能和灵活度比较低,而且它目前已经处于开源版本暂停维护的状态,所以目前国内不少基于Spring Cloud搞微服务的公司都转向了Sentinel。关于两者的对比因为不是本文的重点,这里就再也不赘述,你们搜索下就好(ps:可能网上也没几篇能说明白的文章,关键还在于你们实际使用对比)。LIK1json

2、Sentinel+Apollo架构说明

Sentinel开源版本架构bootstrap

在Github Sentinel官方Wiki说明以及网上一大堆的水文中,关于Sentinel的资料已经不少了,可是大多数属于Demo级别,因此本文不想过多的耗费你们的精力(由于在学习过程当中,做者也被误导过)。如下将从实际生产的使用方式上来阐述如何构建Sentinel的使用架构。api

从本质上说Sentinel与Hystrix是一类性质的熔断限流组件,之因此说它们只是组件就在于它们都须要内嵌于微服务应用自己的主进程之中,全部的限流、熔断策略及指标信息的收集等逻辑都是基于客户端的(这里不要对客户端有所误会,它指的是处于调用端上游的微服务自己)。而这一点是明显区别于Service Mesh(服务网格)架构中将熔断、限流等逻辑抽象在SideCar(边车)而不是微服务应用自己的。缓存

所以从这种意义上说,Sentinel的使用应该是并不复杂的,它应该与Hystrix同样,在Spring Cloud微服务应用中引入相关依赖便可。事实上从某种程度来讲的确如此,只不过Sentinel提供了比Hystrix要强一点的规则配置能力,提供了能够进行限流、熔断降级以及热点、受权等其余规则统一配置和管理的控制台服务->sentinel-dashboard。网络

虽然如此,但这也并无改变Sentinel做为客户端限流组件性质,经过控制台配置的规则依然要推送到微服务应用Sentinel客户端自己才能生效,而微服务之间的调用链路等指标信息也须要推送给Sentinel控制台,才能比较方便地使用Sentinel提供的一些能力,所以在开源的架构版本中须要微服务应用自己开启独立端口与sentinel-dashboard进行通讯,从而获取配置规则以及上述微服务应用各种指标信息。而这一点,显然也会占用微服务额外的资源,而且因为sentinel-dashboard在此条件下并不具有集群部署能力,所以也会造成一个单节点问题,可是有一套控制台总好过于没有,若是但愿比较方便快速地应用Sentinel这也是一种代价。此时的Sentinel架构以下图所示:LIK2架构

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

Sentinel+Apollo架构并发

在开源版本架构中,经过sentinel-dashboard控制台配置的限流、熔断降级等规则都是存储于Sentinel控制台服务内存之中的,若是控制台服务重启或者微服务应用重启都会致使规则丢失。而这在生产环境下是不可接受的,所以Sentinel在官方的生产架构指导中也是推荐使用第三方数据源(如本文的Apollo)做为永久存储中心,这样各个微服务的限流、降级规则均可以永久存储。虽然Sentinel官方推荐使用第三方数据源做为规则存储中心,目前也提供了针对Apollo、Nacos、Zookeeper、Redis、Consul、Spring Cloud Config等多种存储源的依赖集成Jar,可是却并无针对这些数据源提供一个能够实际使用的sentinel-dashboard第三方数据源存储版本,因此当你选择了一种数据源那么就须要你本身对sentinel-dashboard项目进行改造,这里做者针对Sentinel 1.7.0(成文时最新版本)使用Apollo数据源改造了一个版本,全部规则基本可用,但可能会有细节的Bug须要自行Fix。具体代码改造点见Github连接:LIK3

关于以上sentinel-dashboard接入Apollo数据源的代码改造状况,你们能够详细参考上述连接,这里做者只说如下几个重点:

目前官方推荐的方式是经过Apollo的开放平台受权的方式进行写入,所以咱们须要在sentinel-dashboard项目pom.xml文件引入如下依赖:

<!-- Apollo配置依赖 -->
<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-openapi</artifactId>
    <version>1.5.0</version>
</dependency>

以后咱们须要在Apollo Portal建立一个针对sentinel-dashboard的应用,具体建立方法以下图所示:LIK4

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

以上咱们建立了一个针对Sentinel控制台的应用(这里的应用是Apollo配置中心的基本概念,具体微服务接入Apollo的方法,你们能够自行搜索)。

建立应用后,将来Sentinel控制台在启动时须要指定Apollo应用ID才能接入Apollo,而接入Apollo以后Sentinel的规则须要写入该应用下的namespace空间,所以还须要建立针对该应用的namespace空间,具体建立方式以下图所示:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

点击进入应用,而后点击“添加Namespace",建立一个具体存储Sentinel各类限流、熔断降级等规则的Apollo存储空间,这里须要注意的是所建立的空间类型必定要是"public"公共空间,由于最终这些规则是须要具体的微服务应用去获取的,而在Apollo中应用下只有公共Namecspace才能被其余应用继承。
最后咱们在Apollo控制台选择“管理员工具->开放平台受权管理”建立基于该应用的开放受权信息。

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

此时生成的Token信息将做为sentinel-dashboard与Apollo接口对接的重要凭证被配置。经过上述几个步骤,咱们基本上就完成了sentinel-dashboard对接Apollo的准备工做,剩下的就是针对sentinel-dashboard的具体代码改造,可参考前面的Github连接。改造中可以抽离的配置以下:LIK5

#Apollo本地演示环境
#Apollo应用ID
apollo.app.id=sentinel
#Apollo应用下对应的具体集群标识
apollo.cluster.name=local
#Apollo存储空间名称
apollo.namespace.name=sentinel-rule
#Apollo控制台地址
apollo.portal.url=http://127.0.0.1:8070
#Apollo控制台用户名
apollo.modify.user=apollo
apollo.release.user=apollo
#Apollo开放平台凭证
apollo.application.token=2647efacc9d55445f4055247cd028af60dd604b6

以上配置在编写具体的链接代码时会使用到,详情请参考具体改造代码!

为何要使用Apollo?Apollo是一款携程开源的配置中心,在目前基于Spring Cloud的微服务体系中也有一款官方的配置中心Spring Cloud Config。从实际的使用状况看,目前Apollo比起Spring Cloud Config从功能上说要更全一些,若是你的公司在使用Spring Cloud Config那么能够参考上述代码对sentinel-dashboard自行进行改造,只是因为做者所作公司目前使用的是Apollo做为配置中心,所以选择的是Apollo做为Sentinel第三方存储数据源(须要注意Apollo的版本,若是你所使用的Apollo版本比较老,可能会不兼容)。

引入Apollo做为Sentinel数据存储源后,此时的Sentinel架构以下图所示:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

3、Spring Cloud微服务集成Sentinel

讲到这里,咱们还只是完成了Sentinel控制台与Apollo数据存储源之间的打通,那么对于具体的Spring Cloud微服务应用而言,在代码编程上该如何接入和使用Sentinel呢?


微服务链接Sentinel控制台

在默认状况下微服务应用能够直接链接Sentinel控制台,从而经过Sentinel控制台获取限流、熔断降级等规则信息。具体步骤以下:

首先咱们须要在项目pom.xml文件中引入Sentinel相关依赖Jar,代码以下:

<!--Sentinel熔断限流组件依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.1.1.RELEASE</version>
    <!--根据实际状况决定是否排除冲突依赖-->
    <exclusions>
        <exclusion>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </exclusion>
    </exclusions>
</dependency>

以后咱们须要在项目的配置文件中加入Spring Cloud微服务链接sentinel dashboard的配置(此时微服务还还没有引入Apollo配置中心,引入Apollo配置中心后也能够加载配置中心),以下:

#sentinel
#在微服务应用中开启链接sentinel-dashboard的链接端口
spring.cloud.sentinel.transport.port = 8719
#sentinel-dashboard控制台地址
spring.cloud.sentinel.transport.dashboard = http://127.0.0.1:9090

在不考虑第三方数据源永久存储的状况下,以上方式也能够直接使用Sentinel对微服务进行限流、熔断降级等逻辑,只不过这些规则并不能永久存储!

微服务链接Apollo配置中心

接下来咱们将Spring Cloud微服务接入Apollo配置中心,并经过Apollo配置中心获取从Sentinel控制台持久化到Apollo应用存储空间的Sentinel规则。

引入Sentinel规则Apollo数据源依赖,该依赖也会默认包含Apollo自己的客户端依赖,所以也不用再额外引入其余JAR,代码以下:

<!--Sentinel规则Apollo数据源依赖-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-apollo</artifactId>
    <version>1.7.0</version>
    <!--根据实际状况决定是否排除冲突依赖-->
    <exclusions>
        <exclusion>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-extension</artifactId>
        </exclusion>
        <exclusion>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

接下来配置Spring Cloud微服务链接Apollo配置中心的基本信息,以下:

#Apollo中建立的微服务应用ID
app.id = pay-notify
#打开Apollo接入开关
apollo.bootstrap.enabled = true
apollo.bootstrap.eagerLoad.enabled = true

#apollo configserver地址不是portal
apollo.meta = http://127.0.0.1:8080
# 自定义本地配置文件缓存路径
apollo.cacheDir = ./config
#指定apollo命名空间
apollo.namespace =application,db,logback
#指定apollo集群
apollo.cluster=local

若是但愿在Apollo中生效的配置可以及时被Spring Cloud微服务感知到,咱们还须要在微服务主类中加入@EnableApolloConfig注解,代码以下:

@SpringBootApplication
@EnableFeignClients(basePackageClasses = {PayChannelFeignService.class})
@EnableDiscoveryClient
@EnableTransactionManagement
@EnableApolloConfig
public class PayNotifyApplication {

    public static void main(String[] args) {
        SpringApplication.run(PayNotifyApplication.class, args);
    }

    // 注解支持的配置Bean
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

此时抛开Sentinel自己不说,Spring Cloud微服务也能够经过Apollo进行配置管理了!

那么嵌入Spring Cloud微服务应用的Sentitle客户端该如何获取Apollo中关于Sentinel规则的配置呢?在文章前面关于Sentinel+Apollo架构的说明中,sentinel-dashboard是将规则写入它在Apollo所在应用的公共空间下,所以其余微服务自己是能够经过Apollo继承并读取到这些配置的。只是咱们在进行sentinel-dashboard的改造将规则的写入编成了必定的前/后缀标示,因此Spring Cloud微服务要想匹配到相应的规则,也须要在自身服务的配置中约定读取方式,具体以限流、熔断降级这两个规则为例进行配置,以下:

#指定该数据源为限流规则
spring.cloud.sentinel.datasource.flow.apollo.rule-type = flow
spring.cloud.sentinel.datasource.degrade.apollo.rule-type = degrade

#指定该规则在apollo应用中的key,从而实现约定读取
#spring.cloud.sentinel.datasource.ds1.apollo.flow-rules-key = ${spring.application.name}-${spring.cloud.sentinel.datasource.flow.apollo.rule-type}
spring.cloud.sentinel.datasource.flow.apollo.namespaceName = sentinel-rule
spring.cloud.sentinel.datasource.flow.apollo.flowRulesKey = ${spring.application.name}-${spring.cloud.sentinel.datasource.flow.apollo.rule-type}

#降级规则
spring.cloud.sentinel.datasource.degrade.apollo.namespaceName = sentinel-rule
spring.cloud.sentinel.datasource.degrade.apollo.flowRulesKey = ${spring.application.name}-${spring.cloud.sentinel.datasource.degrade.apollo.rule-type}

经过上述配置能够看出,咱们是经过Sentinel客户端依赖约定的配置方式,对各种规则经过命名规则进行了匹配(这里Sentinel规则的命名规则能够结合实际的管理需求进行约定,确保sentinel-dashboard写入与微服务读取匹配就行)!例如:若是从管理角度分类,能够加上{部门名称}.sentinel-rule,这要求建立namespace公共空间时带上部门名前缀。

4、微服务使用Sentinel的编程方式

经过上面操做,咱们已经从配置及环境方面完成了Sentinel与Spring Cloud微服务的接入,接下来咱们以实际的服务间调用为例演示如何在Spring Cloud微服务体系下,使用Sentinel进行限流、熔断降级等操做!以做者以前作过的支付系统为例,其中有两个微服务存在以下调用关系:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

以上两个服务的调用示例,是在支付系统中对支付订单状态进行实时检查的逻辑,目的是防止在出现支付调用链路中断,致使的支付掉单问题。pay-check服务会在支付请求发送到第三方后接受一条延迟消息,并在必定时间后经过对比支付流水状态与第三方渠道支付状态,如发现状态不一致,会经过Spring Cloud微服务间的Feign调用方式触发支付通知服务pay-notify,从而实现支付链路的补偿。这里pay-notify提供的服务接口为“/internel/pay/checkNotify”,关于这个服务接口,这里咱们要求pay-notify服务要对该资源进行限流,从而防止流量过大而致使正常的通知链路受影响;而对于pay-check服务则须要实现对pay-notify服务该接口资源的熔断降级逻辑防止因为故障或网络缘由致使pay-notify服务没法被正常调用,从而影响pay-check服务的稳定性。

Sentinel限流编程

须要明确的是,限流动做自己是服务提供方作出的,因此若是须要针对某个微服务的应用接口使用Sentinel进行限流处理,那么咱们能够在该服务的入口经过@SentinelResource注解进行Sentinel资源配置,以上述实例为例,咱们对pay-notify微服务接口/internel/pay/checkNotify进行以下资源定义:

@SentinelResource(value = "/pay/checkNotify", blockHandlerClass = SentinelFallback.class, blockHandler = "fallbackHandlerForCheckNotify")
@RequestMapping(value = "/pay/checkNotify", method = RequestMethod.POST)
public boolean checkNotify(@RequestParam(value = "paymentId") String paymentId,
        @RequestParam(value = "tradeNo") String tradeNo, @RequestParam(value = "status") int status,
        @RequestParam(value = "platform") String platform, @RequestParam(value = "platformtag") String platformtag,
        @RequestParam(value = "tradeTime") String tradeTime,
        @RequestParam(value = "notifyOrignMsg") String notifyOrignMsg,
        @RequestParam(value = "tradeStatus") String tradeStatus) {
    PayCoreNotifyEntity payCoreNotifyEntity = PayCoreNotifyEntity.builder().paymentId(paymentId).tradeNo(tradeNo)
            .status(status).platform(platform).platformtag(platformtag).tradeTime(tradeTime)
            .orignPlaintext(notifyOrignMsg).tradeStatus(tradeStatus).build();
    boolean result = false;
    try {
        result = payCheckNotifyServiceImpl.payCheckCallBack(payCoreNotifyEntity);
    } catch (CheckNotifyMsgException e) {
        log.error(e.toString() + "_" + e.getMessage(), e);
        CounterUtil.counter(Arrays.asList(Tag.of("exceptionType", e.getMessage())), "payNotifyExceptionMonitor");
    }
    return result;
}

在针对该接口进行Sentinel资源的定义时,为了服务端不直接抛出BlockException异常,咱们配置了异常处理类及异常处理方法。blockHandler函数会在原资源方法被限流系统保护时被调用,而在SentinelFallback类中,针对该资源方法也定义了相应的地处理方法fallbackHandlerForCheckNotify,代码以下:

@Slf4j
public class SentinelFallback {

    public static boolean fallbackHandlerForCheckNotify(String paymentId,
            @RequestParam(value = "tradeNo") String tradeNo, @RequestParam(value = "status") int status,
            @RequestParam(value = "platform") String platform, @RequestParam(value = "platformtag") String platformtag,
            @RequestParam(value = "tradeTime") String tradeTime,
            @RequestParam(value = "notifyOrignMsg") String notifyOrignMsg,
            @RequestParam(value = "tradeStatus") String tradeStatus, BlockException e) {
        log.error("对不起,该请求限流了,{}", e.toString());
        return false;
    }

须要注意的是Block异常处理函数,参数最后多一个BlockException,其他参数则须要与原函数一致,不然限流规则触发后将没法正常进入该fallback方法,而是直接抛出异常,服务消费方则直接收到500错误,输出上会显得不是很友好!关于限流资源异常处理代码编程方式,以上只是参考,你们能够写的更优雅,例如能够参考Feign的fallback编程方式。

定义Sentinel资源后,此时若是须要针对该资源进行限流规则的配置,咱们可使用sentinel-dashboard进行配置,如图所示:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

在pay-notify微服务节点上,选择流控规则,并按照前面定义的Sentinel资源名称进行限流规则配置,这里咱们为了便于测试,限流规则配置的极端所,选择QPS方式,并定义阀值为0。此时因为已经将sentinel-dashbord与Apollo配置中心打通,所以也能从Apollo中看到已经持久化存储的限流规则,以下图所示:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

此时若是针对该资源方法进行网络调用就会被Sentinel规则限流掉,例如经过postman对/internel/pay/checkNotify接口进行网络调用,服务端代码运行以下:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

能够看到此时针对该方法的调用已经触发限流规则,并在抛出BlockException异常后,进入了咱们前面经过@SentinelResource注解定义的blockHandler方法!

Sentinel熔断降级编程

熔断降级针对的是对其余服务资源进行网络调用时,为了防止外部服务的不稳定拖垮自身,当该服务出现不稳定状态(例如调用超时或者异常比例升高等状况),对该资源的调用动做进行限制,从而让请求快速失败,避免出现级联错误的状况。而当资源被降级后,在接下来的降级时间窗口内,对该资源的服务调用都会自动熔断,而不会真正进行网络调用,而在Sentinel中则默认会抛出DegradeException异常。

从使用方向上看熔断降级规则逻辑的发生,是发生在服务消费方,而不是服务提供方。以上述例子举例,pay-notify服务除了针对自身接口进行限流外,pay-check对pay-notify服务的调用也能够进行熔断降级处理。这里咱们将pay-check服务中对pay-notify服务接口的调用方法进行Sentinel资源定义,代码以下:

@SentinelResource(value = "/pay/goCheckNotify", blockHandler = "testNotifyFallback")
public boolean testNotify(String paymentId, String tradeNo, int status, String platform, String platformtag,
        String tradeTime, String notifyOrignMsg, String tradeStatus) throws BlockException {
    return notifyClient
            .checkNotify(paymentId, tradeNo, status, platform, platformtag, tradeTime, notifyOrignMsg, tradeStatus);
}

//熔断降级异常处理方法
public boolean testNotifyFallback(String paymentId, String tradeNo, int status, String platform, String platformtag,
        String tradeTime, String notifyOrignMsg, String tradeStatus, BlockException ex) {
    log.error("服务被降级了!");
    //todo 调用其余降级服务
    return false;
}

以后咱们经过Sentinel控制台在微服务节点pay-check中针对该资源配置降级规则,以下图所示:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

这里的意思是对该资源方法的调用按照平均响应时间进行熔断降级,当1S内持续进入5个请求,对应时刻的资源平均响应时间(秒级)均超过阀值,这里配置的是200ms,那么在接下来的时间窗口内,这里配置的是10s,对该资源的调用都会自动进行熔断,默认抛出DegradeException。为了演示效果,这里咱们将pay-notify服务的接口响应时间故意sleep(600ms),代码以下:

try {
    Thread.sleep(600);
} catch (InterruptedException e) {
    e.printStackTrace();
}

接下来咱们经过JMeter调用pay-check服务,而pay-check服务将以Spring Cloud微服务的调用方式经过Feign来调用pay-notify的服务,以下图所示:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

这里咱们设置的请求方式为1s内发送7次请求调用,按照熔断降级规则,因为前5个请求的响应时间都将超过200ms的阀值,所以第六、7个请求将被直接熔断而进入fallback方法。代码运行效果以下:

Spring Cloud微服务Sentinel+Apollo限流、熔断实战

 

从演示效果看熔断降级规则已经生效,Sentinel抛出了DegradeException异常!

Sentinel与Feign的集成关系

在实际的Spring Cloud微服务开发中,微服务之间的调用能够经过Feign来实现,与Spring Cloud微服务官方集成的Hystrix框架同样,在Feign中若是须要开启Sentinel熔断降级逻辑,须要在调用端(示例中为pay-check服务)配置中进行以下配置:

feign.sentinel.enabled = true

而做为Spring Cloud微服务调用端,在基于Feign对其余微服务存在接口调用的话,通常状况下咱们还须要编写基于Feign的调用代码,并指定其fallback逻辑,以本文示例为例:

@FeignClient(value = "pay-notify", configuration = PayNotifyClientConfiguration.class, fallbackFactory = PayNotifyClientFallbackFactory.class)
public interface PayNotifyClient {
    /**
     * 支付状态核对发生掉单现象时,经过此接口完成补单回调操做
     */
    @RequestMapping(value = "/internal/pay/checkNotify", method = RequestMethod.POST)
    boolean checkNotify(@RequestParam(value = "paymentId") String paymentId,
            @RequestParam(value = "tradeNo") String tradeNo, @RequestParam(value = "status") int status,
            @RequestParam(value = "platform") String platform, @RequestParam(value = "platformtag") String platformtag,
            @RequestParam(value = "tradeTime") String tradeTime,
            @RequestParam(value = "notifyOrignMsg") String notifyOrignMsg,
            @RequestParam(value = "tradeStatus") String tradeStatus);

其所指定的Fallback逻辑代码以下:

public class PayNotifyClientFallbackFactory implements FallbackFactory<PayNotifyClient> {

    @Override
    public PayNotifyClient create(Throwable throwable) {
        return new PayNotifyClient() {
            @Override
            public boolean checkNotify(String paymentId, String tradeNo, int status, String platform,
                    String platformtag, String tradeTime, String notifyOrignMsg, String tradeStatus) {
                log.info("enter flow limit/fallback logic");
                log.error(throwable.getMessage());
                return false;
            }
        };
    }
}


@Slf4j
@Configuration
public class PayNotifyClientConfiguration {

    @Bean
    PayNotifyClientFallbackFactory payNotifyClientFallbackFactory() {
        return new PayNotifyClientFallbackFactory();
    }
}

须要说明的是,在微服务调用时,若是发送调用超时等状况会直接进入以上Feign所指定的fallback逻辑;而Sentinel熔断降级规则被触发时在某些场景下,例如在上述以平均响应时间为例的降级规则中,则只会直接进入@SentinelResource所指定的fallback方法,这一点也是Sentinel与Feign整合不够优雅的地方,所以在编写容错代码时并不能像Hystrix那样作到那么优雅统一!

相关文章
相关标签/搜索