实战小知识----11.27----重试机制

383 阅读2分钟

这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

第三方服务之重试机制

业务上存在一个功能是实现推送服务,利用内部服务的RocketMQ推送数据到服务后,推送到用户指定的url地址

2.1为什么需要重试

不谈整个功能的实现,在实现该功能的时候,容易出现一个小问题——推送失败重试; 明面上是推送的功能,其实就是内部调用API,在服务端内部利用restTemplate 调用HTTP请求。并且需要保证HTTP请求在可控的范围内

然而如果用HTTP推送到客户的接口地址的话,失败的追溯、重试等问题都需要受到重视并追溯.

  • 如果单纯自己实现重试+追溯的话,可能需要依靠恶心的try/catch 里面的catch实现业务逻辑——错误日志
  • 重试的话,可能需要自己利用局部变量去不断循环调用该接口
  •     public Boolean doPush(DeviceDataDto dto) {
            //设置重试次数
            int retries = 0;
            while (true){
                try {
                   return doRetryPush(dto, header, retries);
                }catch (Exception e){
                    if (retries == 1){
                        throw e;
                    }
                    retries++;
                }
            }
        }
    

很显然,这样并不优雅,也会存在较大的隐患

2.2 利用Spring-retry

利用Spring-retry 实现重试机制

  • 只需引入依赖

    • 依赖包括Spring retry的重试
    • 以及借助AOP的切面
            <!--Spring retry-->
            <dependency>
                <groupId>org.springframework.retry</groupId>
                <artifactId>spring-retry</artifactId>
            </dependency>
    ​
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </dependency>
    
  • 代码层实现注解的加入

    • @Retryable

      • value:指定Exception类型
      • maxAttempts:重试次数
      • backoff:默认为@Backoff,delay:失败后回调次数;multiplier:失败后偏移量
    • @Recover:失败后达到指定阈值后调用方法(自定义)

      • 加入该注解可以自定义回调方法
      • 在本次的功能上,自定义失败回调方法,可以在平台内有一个日志报表,记录推送失败的日志;该日志由异步回调方法编写业务
        @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 1.5))
        public int minGoodsnum(int num) throws Exception {
            log.info("网络请求开始" + LocalTime.now());
            try {
                Future<FarmWeatherDTO> future = taskDeom.taskCity();
                future.get();
            } catch (Exception e) {
                throw new IllegalArgumentException("网络请求失败");
            }
            log.info("网络请求结束" + LocalTime.now());
            return totalNum - num;
        }
    ​
    ​
        @Recover
        public int rover(Exception e){
            log.warn("网络请求失败!!!" + LocalTime.now());
            return totalNum;
        }