文档章节

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

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

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

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

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处理的异常要保持一致

 

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

© 著作权归作者所有

共有 人打赏支持
稻草鸟人

稻草鸟人

粉丝 50
博文 12
码字总数 10204
作品 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
无非改成切面实现,自己实现,一样没有问题。
微服务神经元--Neural

微服务神经元(Neural) 为微服务架构的提供一个类似于中枢神经的功能,主要功能如下: NPI(SPI):解决JDK原生SPI的缺陷 支持实现的排序 支持实现的分组 支持单例、多例选择 个性化重试 支持...

李景枫
2016/05/14
3.5K
0
微服务学习(1)-微服务概念

一、什么是微服务(Microservices )? 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注...

花蝴蝶511
2017/12/14
0
0
Polly 故障处理(一): 重试策略

在微服务架构下,我相信大家都应该遇到类似以下问题: 某些接口异常,最终造成应用程序池奔溃; 某些接口不稳定、偶尔超时,数据获取异常; 某些服务不稳定,调用方连接不上; 某些服务异常,...

BeckJin
05/14
0
0
IT架构师绝对不能错过的34张史上最全技术知识图谱

架构师图谱 Java架构师图谱 微服务架构秘籍 一致性图谱 互联网大流量的方法 安全秘籍 阿里巴巴常用小框架 架构方法论图谱 设计模式秘籍图谱 JVM虚拟机垃圾回收图谱 Java并发图谱 Java集合图谱...

棋帅小七
2017/12/22
0
1
微服务网关netflix-zuul

引言:前面一个系列文章介绍了认证鉴权与API权限控制在微服务架构中的设计与实现 ,好多同学询问有没有完整的demo项目,笔者回答肯定有的。由于之前系列文章侧重讲解了权限前置,所以近期补上...

aoho
2017/11/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Memcached启动参数详解

memcached -d -m 1024 -l 192.168.100.101 -p 11211 -P /tmp/memcached.pid -c 1024 -f 1.25 -n 80 -t 16 运行参数描述 -d:以守护(daemon)进程方式启动; -u:是运行Memcache的用户,例如 ......

月下狼
16分钟前
0
0
xgboost-kaggle

https://www.kaggle.com/dansbecker/xgboost This tutorial is part of the Learn Machine Learning series. In this step, you will learn how to build and optimize models with the powe......

tantexian
16分钟前
0
0
nginx学习八 代理服务

最常用的语法 proxy_pass Syntax: proxy_pass URL;Default: --Context:location.if in location,limit_exception 反向代理 例:/etc/nginx/conf.d/default.conf 反向代理(代理服务端)......

Romanceling
24分钟前
0
0
npm ERR! Unexpected end of JSON ...

npm install 报错: npm ERR! Unexpected end of JSON input while parsing near '..."^2.8.14"},"_hasShrin' npm ERR! A complete log of this run can be found in: ... 打开终端 命令: 第......

大_侠
28分钟前
0
0
Android中的设计模式之责任链模式

参考 《设计模式:可复用面向对象软件的基础 》5.1 Chain of responsibility 职责链 对象行为型模式 《Android源码设计模式解析与实战》第9章 使编程更有灵活性--责任链模式 意图 使多个对象...

newtrek
31分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部