郎创网站建设,注册商标名字,搭建小程序公司,网站推广套餐前言
重试#xff0c;其实我们其实很多时候都需要的#xff0c;为了保证容错性#xff0c;可用性#xff0c;一致性等。一般用来应对外部系统的一些不可预料的返回、异常等#xff0c;特别是网络延迟#xff0c;中断等情况。还有在现在流行的微服务治理框架中#xff0…前言
重试其实我们其实很多时候都需要的为了保证容错性可用性一致性等。一般用来应对外部系统的一些不可预料的返回、异常等特别是网络延迟中断等情况。还有在现在流行的微服务治理框架中通常都有自己的重试与超时配置比如dubbo可以设置retries1timeout500调用失败只重试1次超过500ms调用仍未返回则调用失败。如果我们要做重试要为特定的某个操作做重试功能则要硬编码大概逻辑基本都是写个循环根据返回或异常计数失败次数然后设定退出条件。这样做且不说每个操作都要写这种类似的代码而且重试逻辑和业务逻辑混在一起给维护和扩展带来了麻烦。从面向对象的角度来看我们应该把重试的代码独立出来。
痛点
请看大屏幕 一、代码实现 ①maven引入依赖 dependency groupIdorg.springframework.retry/groupId artifactIdspring-retry/artifactId /dependency
②启动类
proxyTargetClass :指定动态代理使用JDK还是CGLIB EnableRetry(proxyTargetClass true)
③重试方法需要重试的方法
核心注解Retryable Retryable(value Exception.class, maxAttempts 3, backoff Backoff(delay 2000, multiplier 1.5)) Override public int retry(int code) throws Exception { System.out.println(retry方法被调用,时间 LocalTime.now()); if (0 0) { throw new Exception(调用异常了); } System.out.println(retry方法正常调用); return 200; }
④回调方法重试失败之后的兜底操作
核心注解Recover Recover public int recover(Exception e, int code) { System.out.println(执行回调方法 code); //记日志到数据库 或者调用其余的方法 return 400; }
踩坑
踩坑
1、异常处理方法返回参数必须与retry方法保持一致2、该方法必须与retry方法在同一个类中
以上就对一个方法完成了一个简单的重试功能。 二、首先了解一些关键内容
①重试策略看一下Spring Retry自带的一些重试策略主要是用来判断当方法调用异常时是否需要重试 SimpleRetryPolicy 默认最多重试3次TimeoutRetryPolicy 默认在1秒内失败都会重试ExpressionRetryPolicy 符合表达式就会重试CircuitBreakerRetryPolicy 增加了熔断的机制如果不在熔断状态则允许重试CompositeRetryPolicy 可以组合多个重试策略NeverRetryPolicy 从不重试也是一种重试策略哈AlwaysRetryPolicy 总是重试 ②退避策略退避是指怎么去做下一次的重试在这里其实就是等待多长时间 FixedBackOffPolicy 默认固定延迟1秒后执行下一次重试ExponentialBackOffPolicy 指数递增延迟执行重试默认初始0.1秒系数是2那么下次延迟0.2秒再下次就是延迟0.4秒如此类推最大30秒。ExponentialRandomBackOffPolicy 在上面那个策略上增加随机性UniformRandomBackOffPolicy 这个跟上面的区别就是上面的延迟会不停递增这个只会在固定的区间随机StatelessBackOffPolicy 这个说明是无状态的所谓无状态就是对上次的退避无感知从它下面的子类也能看出来 三、引出问题Spring是如何实现的
①入口注解EnableRetry 核心注解
1、开启AOPEnableAspectJAutoProxy(proxyTargetClass false)
2、注入RetryConfigurationImport(RetryConfiguration.class) 核心 ②一起看看RetryConfiguration是干什么的 继承AbstractPointcutAdvisor,实现IntroductionAdvisor, BeanFactoryAware
上面断处是我们AOP中熟悉的切面和增强 ③核心拦截器AnnotationAwareRetryOperationsInterceptor 核心实现 这里主要是看我们有没有自定义拦截器如果有的话默认优先使用自定义的拦截器。 简单实现:getStatelessInterceptor ④核心拦截器RetryOperationsInterceptor Spring源码中一般出现了execute()一般就是真正开始干活了这里也一样 ⑤具体实现
1、第一个标注点判断是否可以重试
2、第二个标注点执行重试 ⑥三种实现 这三个类都是Java中的线程休眠工具类但它们的作用略有不同 ObjectWaitSleeper该类是通过调用对象的wait()方法来使线程休眠的。当一个线程调用对象的wait()方法时它会释放该对象的锁并进入等待状态直到其他线程调用该对象的notify()或notifyAll()方法来唤醒它。 StealingSleeper该类是通过调用Thread.yield()方法来使线程休眠的。当一个线程调用Thread.yield()方法时它会暂停当前线程的执行让其他线程有机会运行。 ThreadWaitSleeper该类是通过调用Thread.sleep()方法来使线程休眠的。当一个线程调用Thread.sleep()方法时它会暂停当前线程的执行让其他线程有机会运行但不会释放任何锁。 ⑦ThreadWaitSleeper