Guava-Retryer, инструмент для повторных попыток

задняя часть .NET Байду удаленная работа

написать впереди

В повседневной разработке мы часто сталкиваемся со сценариями, в которых нам нужно вызывать внешние сервисы и интерфейсы. Внешние службы, как правило, ненадежны для вызывающих абонентов, особенно в случае плохой сетевой среды, дрожание сети может легко привести к ненормальным условиям, таким как тайм-аут запроса. . Стратегия повторных попыток также широко используется в управлении службами: она проверяет, является ли служба активной (активной) путем регулярного обнаружения.

Guava Retrying — это гибкие и удобные компоненты повторной попытки, включающие несколько стратегий повторной попытки и очень легко масштабируемые.

Со слов автора:

Это небольшое расширение библиотеки Google Guava, позволяющее создавать настраиваемые стратегии повторных попыток для произвольного вызова функции, например, что-то, что взаимодействует с удаленной службой с непостоянным временем безотказной работы.

Используя Guava-retry, вы можете настроить выполнение повторных попыток, а также вы можете отслеживать результаты и поведение каждой повторной попытки, и, что наиболее важно, метод повторных попыток в стиле Guava действительно удобен.

пример кода

  • Представьте Guava-retry
<guava-retry.version>2.0.0</guava-retry.version>
<dependency>
      <groupId>com.github.rholder</groupId>
      <artifactId>guava-retrying</artifactId>
      <version>${guava-retry.version}</version>
</dependency>
  • Определите метод, который реализует интерфейс Callable, чтобы повторитель Guava мог вызывать
/**
    * @desc 更新可代理报销人接口
    * @author jianzhang11
    * @date 2017/3/31 15:17
    */
   private static Callable<Boolean> updateReimAgentsCall = new Callable<Boolean>() {
       @Override
       public Boolean call() throws Exception {
           String url = ConfigureUtil.get(OaConstants.OA_REIM_AGENT);
           String result = HttpMethod.post(url, new ArrayList<BasicNameValuePair>());
           if(StringUtils.isEmpty(result)){
              throw new RemoteException("获取OA可报销代理人接口异常");
           }
           List<OAReimAgents> oaReimAgents = JSON.parseArray(result, OAReimAgents.class);
           if(CollectionUtils.isNotEmpty(oaReimAgents)){
               CacheUtil.put(Constants.REIM_AGENT_KEY,oaReimAgents);
               return true;
           }
           return false;
       }
   };
  • Определить объекты Retry и установить соответствующие политики
Retryer<Boolean> retryer = RetryerBuilder
                .<Boolean>newBuilder()
                //抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。
                .retryIfException()
                //返回false也需要重试
                .retryIfResult(Predicates.equalTo(false))
                //重调策略
                .withWaitStrategy(WaitStrategies.fixedWait(10, TimeUnit.SECONDS))
                //尝试次数
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .build();
 
        try {
            retryer.call(updateReimAgentsCall);
        } catch (ExecutionException e) {
//            e.printStackTrace();
        } catch (RetryException e) {
            logger.error("更新可代理报销人异常,需要发送提醒邮件");
        }

В три простых шага вы можете использовать Guava Retryer для элегантной реализации методов перенастройки.
Далее подробно объясняется:

  • RetryerBuilderЭто создатель фабрики, который может настраивать источник повторных попыток и поддерживать несколько источников повторных попыток, настраивать количество повторных попыток или тайм-аут повторных попыток, а также настраивать интервал времени ожидания и создавать экземпляр Retryer для повторной попытки.
  • RetryerBuilderИсточник повторных попыток поддерживает объект Exception и пользовательский объект утверждения черезretryIfExceptionиretryIfResultНастройка, поддерживает несколько и совместимых одновременно.
  • retryIfException, когда возникает исключение времени выполнения или проверенное исключение, оно будет повторено, но когда возникнет ошибка, оно не будет повторено.
  • retryIfRuntimeExceptionБудет пытаться снова, только когда время выполнения ненормально, Checked не возвращается.
  • retryIfExceptionOfTypeПозволяет нам повторять попытку только при возникновении определенных исключений, таких какNullPointerException和IllegalStateException` — это все исключения времени выполнения, включая пользовательские ошибки.

как:

.retryIfExceptionOfType(Error.class)// 只在抛出error重试

Конечно, мы также можем повторить попытку только тогда, когда возникает указанное исключение, например:

.retryIfExceptionOfType(IllegalStateException.class)  
.retryIfExceptionOfType(NullPointerException.class)

Или через предикат

.retryIfException(Predicates.or(Predicates.instanceOf(NullPointerException.class),  
                Predicates.instanceOf(IllegalStateException.class)))

retryIfResult может указать, что ваш метод Callable будет повторять попытку при возврате значения, например

// 返回false重试 
.retryIfResult(Predicates.equalTo(false))  
//以_error结尾才重试 
.retryIfResult(Predicates.containsPattern("_error$"))  

Когда происходит повторная попытка, если нам нужно выполнить некоторые дополнительные действия по обработке, такие как отправка электронного письма с предупреждением или что-то еще, мы можем использоватьRetryListener. После каждой повторной попытки guava-retry будет автоматически вызывать зарегистрированный нами слушатель.可以注册多个RetryListener, который будет вызываться в порядке регистрации.

import com.github.rholder.retry.Attempt;  
import com.github.rholder.retry.RetryListener;  
  
import java.util.concurrent.ExecutionException;  
  
public class MyRetryListener<Boolean> implements RetryListener {  
  
    @Override  
    public <Boolean> void onRetry(Attempt<Boolean> attempt) {  
  
        // 第几次重试,(注意:第一次重试其实是第一次调用)  
        System.out.print("[retry]time=" + attempt.getAttemptNumber());  
  
        // 距离第一次重试的延迟  
        System.out.print(",delay=" + attempt.getDelaySinceFirstAttempt());  
  
        // 重试结果: 是异常终止, 还是正常返回  
        System.out.print(",hasException=" + attempt.hasException());  
        System.out.print(",hasResult=" + attempt.hasResult());  
  
        // 是什么原因导致异常  
        if (attempt.hasException()) {  
            System.out.print(",causeBy=" + attempt.getExceptionCause().toString());  
        } else {  
            // 正常返回时的结果  
            System.out.print(",result=" + attempt.getResult());  
        }  
  
        // bad practice: 增加了额外的异常处理代码  
        try {  
            Boolean result = attempt.get();  
            System.out.print(",rude get=" + result);  
        } catch (ExecutionException e) {  
            System.err.println("this attempt produce exception." + e.getCause().toString());  
        }  
  
        System.out.println();  
    }  
} 

Далее указываем прослушиватель в объекте Retry:

.withRetryListener(new MyRetryListener<>())

Использованная литература:

blog.CSDN.net/Ai Soup/…

сегмент fault.com/ah/119000000…

blog.CSDN.net/Ai Soup/…

Сотни семьи. Baidu.com / есть? ID = 157532 ...

Ооо, ооо на .cn blog .com/почти 5/страх/6...