Java 远程调用失败?如何优雅的进行重试?

网站建设3年前发布
6 0 0

在日常开发的过程中我们经常会需要调用第三方组件或者数据库,有的时候可能会因为网络抖动或者下游服务抖动,导致我们某次查询失败。,这种时候我们往往就会进行重试,当重试几次后依旧还是失败的话才会向上抛出异常进行失败。接下来阿粉就给大家演示一下通常是如何做的,以及如何更优雅的进行重试。,我们先来看一下常规做法,常规做法首先会设置一个重试次数,然后通过 while 循环的方式进行遍历,当循环次数没有达到重试次数的时候,直到有正确结果后就返回,如果重试依旧失败则会进行睡眠一段时间,再次重试,直到正常返回或者达到重试次数返回。,这里为了模拟异常的情况,阿粉在 doSomething​ 函数里面进行了随机数的生成和使用,当随机出来的值为 0 的时候,则会触发 java.lang.ArithmeticException 异常,因为 0 不能作除数。,接下来我们再对外提供一个接口用于访问,代码如下,正常启动过后,我们通过浏览器进行访问。,2023030601343696464aa01adf1f80fb06939e67af38eb9c7193464,可以看到,我们第一次方法的时候就成功的达到了我们要的效果,随机数就是 0 ,在 1 秒后重试后结果正常。在多试了几次过后,会遇到三次都是 0 的情况,这个时候才会抛出异常,说明服务是真的有问题了。,2023030601343703fe51002e740c6b0302745ec3b9340c8457b6593,2023030601343721ba8f294172fa7bbff1033baae71c6a461027785,20230306013623034548800f5712fea0f7641fe0df63b471705c923,上面的代码可以看到是有效果了,虽然不是很好看,特别是在还有一些其他逻辑的情况,看上去会很臃肿,但是确实是可以正常使用的,那么有的小伙伴就要问了,有没有一种优雅的方式呢?总不能在很多地方都重复的这样写重试的代码吧。,要知道我们普通人在日常开发的时候,如果遇到一个问题肯定是别人都遇到过的,什么时候当我们遇到的问题,没有人遇到过的时候,那说明我们是很前卫的。,因此小伙伴能想到的是不是有简单的方式来进行重试,有的人已经帮我们想好了,可以通过 @Retryable 注解来实现一样的效果,接下来阿粉就给大家演示一下如何使用这个注解。,首先我们需要在启动类上面加入 @EnableRetry​ 注解,表示要开启重试的功能,这个很好理解,就像我们要开启定时功能需要添加 @EnableScheduling​ 注解一样,Spring​ 的 @Enablexxx 注解也是很有意思的,后面我们再聊。,添加完注解以后,需要加入切面的依赖,如下,如下不加入这个切面依赖,启动的时候会有如下异常,202303060134384505dc397cb3afca24796231a20192df917d17270,添加的注解和依赖过后,我们需要改造 HelloService​ 里面的 sayHello()​ 方法,简化成如下,增加  @Retryable 注解,以及设置相应的参数值。,再次通过浏览器访问 http://127.0.0.1:8080/hello?name=ziyou 我们看到效果如下,跟我们自己写的重试一样。,202303060134397300485435f5d95cd9c3018393356118ea4ed0715,点到这个注解里面,我们可以看到这个注解的代码如下,其中有几个参数我们来解释一下,配合上面的一些属性的使用,我们就可以达到通过注解简单来实现方法调用异常后的自动重试,非常好用。我们可以在执行重试方法的时候设置自定义的重试拦截器,如下所示,自定义重试拦截器需要实现 MethodInterceptor​ 接口并实现 invoke 方法,不过要注意,如果使用了拦截器的话,那么方法上的参数就会被覆盖。,自定义回滚方法,我们还可以在重试几次依旧错误的情况,编写自定义的回滚方法。,20230306013439455cdef631940d7a7b81404fd2217c8f39fa0f970,要注意:,上面代码中的 @Backoff(delay = 1000, multiplier = 2) 表示第一次延迟 1000ms 重试,后面每次重试的延迟时间都翻倍。,阿粉今天给大家介绍了一下 Spring​ 的 @Retryable 注解使用,并通过几个 demo 来带大家编写了自己重试拦截器以及回滚方法的时候,是不是感觉用起来会很爽,那还在等什么赶紧用起来吧,其中还有很多细节,只有自己真正的使用过才能体会到。,

© 版权声明

相关文章