文档章节

微服务常用技能之优雅的重试

稻草鸟人
 稻草鸟人
发布于 2017/04/08 15:04
字数 976
阅读 4.3K
收藏 189

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

一般从事软件开发工作的同时通常需要调用远程服务,但是即使是亚马逊、阿里巴巴、腾讯这些巨头提供的服务也可能因为网络或者服务高可用方面的一些问题,或许会遇到超时等异常情况,这时候我们就必需要考虑到异常情况下我们的应用如何能处变不惊处理这些异常,是直接抛出异常还是说可以自动进行一些处理呢? 通常情况下我们首先想到的解决方案一定是重试对吧。

我看过很多代码,他们都怎么写的呢,如下

public String invoke(int times) {
    for(int i = 0; i < times; i ++) {
        try{
            // do some thing
            // return
        }catch(Exception e) {
            return invoke(i);
        }
    }
}

上面的代码意思是首先传入一个次数参数,假设我们传递的是3,那么当遇到异常的时候,重新调用当前方法,次数变为2…

你有没有发现如果调用外部服务很多的时候,这样的for循环写的让人不舒服,因为都是重复的代码,而且显的很啰嗦呢,spring boot给我们带来了一些福音,我们看看spring boot框架下如何进行重试

1、 首先引入JAR包

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

2、使用注解 @EnableRetry @Retryable 下面先给出代码,然后我们再讲注解的含义

@SpringBootApplication
@EnableRetry
public class LeaningNotesApplication {

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

private Random random = new Random();

@Retryable(include = RuntimeException.class, maxAttempts = 3)
public String readingList() {
    int randomInt= random.nextInt(10) ;
    if(randomInt < 8){  //模拟调用失败情况
        System.out.println("调用失败发生异常");
        throw new RuntimeException("call dependency service fail.");
    }else{
        System.out.println("调用成功");
        return "调用成功 ;number:"+randomInt;
    }
}

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


3、我们再写一个接口,通过浏览器来访问这个接口,看看上面的代码帮我们进行了几次重试,另外如果重试了几次都失败,他又执行了什么方法

@RestController
public class BookController {

@Autowired
private BookService bookService;

@GetMapping("/book")
public String book() {
    return bookService.readingList();
}
}

上面的这个代码就比较简单了,我们可以通过http://localhost:8080/book 来访问这个接口,然后在控制台看结果,我都迫不及待想要去试试了,你呢?

4、我打开了浏览器输入了地址,然后我看到控制台打印了下面这样的信息

调用失败发生异常 
调用成功 
是的,你没看错,先输出了一个异常日志,然后又输出了一个成功日志,说明了它在异常的情况下帮我重试了一次,然后才成功的,当然你也可以多尝试几次看看不一样的结果。

5、@Retryable 几个比较重要的参数

value : 抛出某些异常的时候才进行重试

include: 和value的含义类似

exclude: 排除某些异常不进行重试,这里要注意的是,如果value、include、exclude都为空的时候则任何异常都进行重试

maxAttempts: 最大重试次数

backoff: 重试策略,默认使用注解@Backoff 而@BackOff中value的默认为1000L,multiplier的默认值为0,表示默认情况下固定暂停1秒进行重试,如果我们把multiplier调整为2,那么表面第一次进行重试时间为1秒,第二次为2秒,第三次为4秒。

是不是很牛逼,有木有GET到新技能?

注意:注解了@Recover方法的参数可以没有,如果有一定是和注解@Retryable处理的异常是一样的或者是它的子集,否则recover方法将不能被执行,并不是网上一些人瞎逼逼说一定要和@Retryable处理的异常要保持一致

 

请大家多多关注,让我能有勇气坚持下去

© 著作权归作者所有

稻草鸟人

稻草鸟人

粉丝 51
博文 23
码字总数 20500
作品 0
上海
后端工程师
私信 提问
加载中

评论(20)

kubei
kubei
谢谢 博主的 分享
稻草鸟人
稻草鸟人 博主

引用来自“终曲”的评论

生产环境重试有时候很危险,根据不同的异常可能要fail fast,那就把错误处理的逻辑全部隐式转嫁到抛什么异常上了,代码更难读

回复@终曲 : 重试只是其中最常见的方式,不错,有些可能要FAILFAST有些需要FAIL OVER当然还有其他降级等策略
Z
Zollty
没看出有多优雅。。。
终曲
终曲
生产环境重试有时候很危险,根据不同的异常可能要fail fast,那就把错误处理的逻辑全部隐式转嫁到抛什么异常上了,代码更难读
稻草鸟人
稻草鸟人 博主

引用来自“楼雨”的评论

一点都不优雅,当项目越久越大,人员N次更替之后,你这简直是恶梦。
当然,也不赞同第一种写法。

回复@楼雨 : 如何写更好?请指教
楼雨
楼雨
一点都不优雅,当项目越久越大,人员N次更替之后,你这简直是恶梦。
当然,也不赞同第一种写法。
HeartArea
HeartArea
原理就是aop,但是low逼的是为什么引入retry时不能把aspectj-weaver依赖也搞进入啊,还得自己手加。
HideHai
HideHai
又涨姿势了
notreami
notreami
无非改成切面实现,自己实现,一样没有问题。
notreami
notreami
无非改成切面实现,自己实现,一样没有问题。
微服务架构的故障隔离及容错处理机制

本文首先介绍微服务架构存在的风险,然后针对如何避免微服务架构的故障,提出了多种有效的微服务架构中的方法和技术,其中例如服务降级、变更管理、健康检查和修复、断路器、限流器等。 目录...

伊竹凌
2018/08/27
0
0
Spring Cloud中Hystrix、Ribbon及Feign的熔断关系是什么?

导读 今天和大家聊一聊在Spring Cloud微服务框架实践中,比较核心但是又很容易把人搞得稀里糊涂的一个问题,那就是在Spring Cloud中Hystrix、Ribbon以及Feign它们三者之间在处理微服务调用超...

osc_cw9m1qtk
2019/07/22
27
0
好程序员Java培训面试进阶知识点之微服务框架

  好程序员Java培训面试进阶知识点之微服务框架,微服务(Microservices)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。随着越来越多的人加入到Java开发行列,企业对求职者的...

好程序员
04/27
0
0
springcloud中微服务的优雅停机(已验证)

大部分项目部署中,为了方便,可能都直接使用kill -9 服务的pid来停掉服务。 但是由于Eureka采用心跳的机制来上下线服务,会导致服务消费者调用此已经kill的服务提供者然后出错。 可以采用以...

osc_x690pobu
2019/08/25
1
0
Hyperf 发布 Retry 重试组件及 v1.1.7 版本

更新内容 本周更新主要为新增 hyperf/retry 组件,网络通讯天然是不稳定的,因此在分布式系统中,需要有良好的容错设计,无差别重试是非常危险的。当通讯出现问题时,每个请求都重试一次,相...

huangzhhui
2019/11/21
1.3K
12

没有更多内容

加载失败,请刷新页面

加载更多

QT 执行shell命令

(1)首先包含头文件: #include <QProcess> (2)执行shell命令: QProcess::execute("ls");

悲催的古灵武士
24分钟前
22
0
osgEarth使用笔记3——加载倾斜摄影数据

目录 1. 概述 2. 详论 2.1. 位置 2.2. 着色 2.3. 其他 3. 结果 4. 参考 1. 概述 我在《OSG加载倾斜摄影数据》这篇博文中论述了如何通过OSG生成一个整体的索引文件,通过这个索引文件来正确显...

osc_7oc4d1en
26分钟前
19
0
cesium加载gltf模型点击以及列表点击定位弹窗

前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材。 之前有部分订阅者咨询我,...

osc_cx8uhydz
26分钟前
14
0
思维导图软件如何插入图片?具体步骤?

学习思维导图制作的过程中,会遇到很多没有学过的知识,需要我们不断地去改进和学习,这样增强自己的学习能力,才能更好地掌握制图软件。以后帮助我们快速方便地完成制图,今天我们就要来看看...

深蓝月上
27分钟前
25
0
Notepad++ 列块模式编辑,替换换行符

一、列块模式编辑: 1、数据准备 2、按住 “Alt + 鼠标左键” 选择需要列块模式编辑的区域,可以看到多了一条竖线 3、之后批量可以添加,修改内容 二、替换换行符 上面说了列块模式的编辑,后...

osc_itgved4p
27分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部