文档章节

微服务常用技能之熔断

稻草鸟人
 稻草鸟人
发布于 2017/04/18 09:39
字数 1159
阅读 306
收藏 1

微服务常用技能之优雅重试这篇里面我们聊到了如何在调用服务发生异常的情况下进行重试(优雅的重试),但是我们也发现了一些问题,问题如下:

1、 当第三方服务宕机或者不可用,一个请求过来之后失败了3次,第二次、第三次请求都是失败3次,我们能不能直接失败,而不是重复调用不可用的服务呢 
2、spring-retry中的@Recover只能是对异常进行事后处理,所有的@Retryable都可能会调用到此方法,我们有没有针对某一个服务的降级处理呢?

如果你也想了如上的问题或者你想到更多的问题,那么恭喜你,你的才能一定在我之上,并且现在或者将来一定大有可为,架构师指日可待,当上CEO、赢取白富美…

现在我们带着这些问题,我们来看看都有哪些解决方法

Spring Retry 注解@CircuitBreaker 实现

微服务常用技能之优雅重试中的代码类似,maven导入的包也一样,修改如下代码

@Service
public class BookService {

private Random random = new Random();

//    @Retryable(value = WebServiceException.class ,include = RuntimeException.class, maxAttempts = 3)
    @CircuitBreaker(maxAttempts = 1, resetTimeout = 10000L, openTimeout = 5000L)
    public String readingList(String str) {
        int randomInt= random.nextInt(10) ;
        if(randomInt < 8){  //模拟调用失败情况
            System.out.println("random:" + randomInt 
                +" time:" + LocalTime.now());
            throw new WebServiceException("call dependency service fail.");
        }else{
            System.out.println("调用成功" + str);
            return "调用成功 ;number:" + randomInt;
        }
    }

    @Recover
    public String reliable() {
        return "Cloud Native Java (O'Reilly)";
    }
}

如上代码,注释掉@Retryable注解,改为@CircuitBreaker注解即可,为了测试方便maxAttempts 我设置为1是因为测试当失败一次则开始熔断开关,以后所有请求则不再调用此方法,resetTimeout 设置为10秒,默认是2秒,时间足够大,点击按钮才能感受到效果。

说明
1、maxAttempts 表示重试次数,默认为3 
2、resetTimeout 熔断开关打开后等待重置时间即何时恢复 
3、openTimeout 表示在此设置的时间段内如果失败次数达到maxAttempts 设置的次数则熔断 
注意(如果我说的不对,请指正): 
如果在openTimeout 时间范围内失败次数达到maxAttempts 并且陆续会有请求进来的话,熔断开关将会一直处于打开状态也就是所有请求只能走@Recover方法

hystrix 实现

首先引入所需包

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    </dependency>

代码部分

@SpringBootApplication
@EnableCircuitBreaker
public class HystrixNotesApplication {

    public static void main(String[] args) {
        SpringApplication.run(HystrixNotesApplication.class, args);
    }
}
@Service
public class BookService {

    private Random random = new Random();

    @HystrixCommand(fallbackMethod = "reliable",
            commandProperties = {@HystrixProperty(name = EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE")})
    public String readingList(String str) {
        int randomInt= random.nextInt(10) ;
        if(randomInt < 8){  //模拟调用失败情况
            System.out.println("调用失败发生异常" + str);
            throw new WebServiceException("call dependency service fail.");
        }else{
            System.out.println("调用成功" + str);
            return "调用成功 ;number:"+randomInt;
        }
    }

    public String reliable(String str) {
        System.out.println(str + "===");
//        System.out.println(e.fillInStackTrace());
        return "Cloud Native Java (O'Reilly)";
    }
}

代码部分大概就如上这样了,主要就是在入口方法上面加上注解@EnableCircuitBreaker,在具体的服务上添加上@HystrixCommand注解 
1、 fallbackMethod 方法指定了熔断时执行的方法,上面的指定的方法是reliable(String str),这个方法必须和@HystrixCommand注解所在类保持一致且参数也应该和readingList一样 
2、HystrixCommand 在熔断方面有几个比较重要的配置参数,都HystrixCommandProperties.java里面了,我们先说下熔断的逻辑(过程)

熔断过程

1、假设通过断路器的量达到一定的阈值(默认20) 
(HystrixCommandProperties.circuitBreakerRequestVolumeThreshold())… 
2、并且假设错误的百分比达到设定的阈值百分比(默认50) 
(HystrixCommandProperties.circuitBreakerErrorThresholdPercentage())… 
3、这时候熔断开关从CLOSE 状态变为OPEN状态 
4、当熔断开关打开的时候,将会阻断所有的请求 
5、经过一段时间之后(默认5秒) 
(HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds()),下一个请求将会被放行(这就是HALF-OPEN状态),如果这次请求失败了,熔断器将会恢复到OPEN 状态,如果这次请求成功了,熔断开关变为CLOSE状态,然后继续进行步骤1,循环往复。

写在最后

熔断咱们就先说到这里了,短短小文不足以完全说明白熔断,并且希望看到的朋友能够给予补充和指正,另外上面hystrix实现的熔断我们还留下了不少疑问,比如注解@HystrixCommand里面的fallbackMethod ,HystrixProperty里面的隔离策略(EXECUTION_ISOLATION_STRATEGY),隔离策略中信号量、线程大小应该怎么设置才合理等等

参考文档

[1] command & thread properties 
[2] CircuitBreaker Properties 
[3] CircuitBreaker - How it work

© 著作权归作者所有

稻草鸟人

稻草鸟人

粉丝 51
博文 12
码字总数 10204
作品 0
上海
后端工程师
私信 提问
进击的微服务实战派丨 Micro Service Open Talk 北京站

一、活动介绍 2016年10月,Spring Cloud 中国社区(http://springcloud.cn) 作为国内首个 Spring Cloud 构建微服务架构的交流社区正式成立,致力于为 Spring Boot 和 Spring Cloud 技术人员提...

又拍云
2017/09/27
91
1
进击的微服务实战派丨 Micro Service Open Talk 北京站

一、活动介绍 2016年10月,Spring Cloud 中国社区(http://springcloud.cn) 作为国内首个 Spring Cloud 构建微服务架构的交流社区正式成立,致力于为 Spring Boot 和 Spring Cloud 技术人员提...

又拍云
2017/09/27
164
1
广州站|一场36小时的集中脑爆式Docker培训课程

Docker是基于Go语言实现的云开源项目,诞生于2013年初,最初发起者是dotCloud公司。Docker自开源后就受到广泛的关注和讨论,目前已有多个相关项目,逐渐形成了围绕Docker的生态体系。dotClou...

DockOne
2016/11/10
38
0
基于.NET CORE微服务框架 -谈谈surging的服务容错降级

一、前言 对于不久开源的surging受到不少.net同学的青睐,也受到.net core学习小组的关注,邀请加入.NET China Foundation 以方便国内.net core开源项目的推广,我果断接受邀请加入了队伍进行...

fanly11
2017/07/23
0
0
ASP.NET Core 微服务初探[2]:熔断降级之Polly

当我们从单体架构迁移到微服务模式时,其中一个比较大的变化就是模块(业务,服务等)间的调用方式。在以前,一个业务流程的执行在一个进程中就完成了,但是在微服务模式下可能会分散到2到1...

雨夜朦胧
01/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
6
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
8
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
6
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部