Estrutura de nova tentativa do Spring

Introdução

Endereço de origem do Spring Retry

A estrutura de repetição Spring Retry suporta o uso declarativo e imperativo.

Requerimentos ambientais

Spring Retry requer Java 1.7 e Maven 3.0.5 (ou superior).
Recomenda-se que Java 1.8 e superior sejam usados ​​para simplificar o código usando expressões lambda.

Declarativo

O uso declarativo é baseado na programação de aspecto AOP, que requer a introdução de aspectjweaver ou spring-boot-starter-aop
pom.xml

	<!-- Spring Retry -->
	<dependency>
	    <groupId>org.springframework.retry</groupId>
	    <artifactId>spring-retry</artifactId>
	</dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
@Configuration
@EnableRetry
public class Application {
    
    

}

@Service
class Service {
    
    
    @Retryable(RemoteAccessException.class)
    public void service() {
    
    
        // ... do something
    }
    @Recover
    public void recover(RemoteAccessException e) {
    
    
       // ... panic
    }
}

caso real:

    @Override
    @Retryable(value = {
    
     Exception.class }, maxAttempts = 3, backoff = @Backoff(delay = 5000L, multiplier = 1))
    public Object restPostTest(Map map, String url) throws Exception {
    
    
        logger.info("调用第三方接口");
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //设置访问的Entity
        HttpEntity entity = new HttpEntity<>(map, headers);
        ResponseEntity<String> result;
        JSONObject data = new JSONObject();
        //发起一个POST请求
        logger.info("发起一个POST请求");
        result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        data = JSONObject.parseObject(result.getBody());
        logger.info("返回结果{}",data);
        return data;
    }
    
    @Recover
    public Object recover(Exception e, Map map, String url) {
    
    
       // ... 放入消息队列或数据库
    }

@Retryable Annotation O
método anotado será tentado novamente
quando ocorrer uma exceção. Valor: Especifique a ocorrência da exceção para tentar novamente.
Incluir: O mesmo que o valor, vazio por padrão. Quando excluir também está vazio, todas as exceções são repetidas.
Exclude: Especifique o exceção para não tentar novamente., O padrão é vazio, quando a inclusão também está vazia, todas as exceções são repetidas
maxAttemps: número de tentativas, padrão 3
recuo: mecanismo de compensação de nova tentativa, padrão não

@Backoff annotation
delay: Tentar novamente após o
multiplicador de atraso especificado : especifique o múltiplo do atraso, como delay = 5000l, multiplicador = 2, a primeira tentativa é 5 segundos, a segunda vez é 10 segundos e a terceira vez é 20 segundos

@Recover
Quando as novas tentativas atingirem o número especificado de vezes, o método anotado será chamado de volta e o processamento do log pode ser executado neste método. Deve-se observar que o callback só ocorrerá quando ocorrer a exceção e o tipo de parâmetro de entrada for o mesmo.

Descrição:

  • O objeto de classe onde as anotações acima estão localizadas deve ser assumido pelo container spring, usando @Service, @Bean, etc.
  • Os valores de retorno dos métodos marcados por @Retryable e @Recover devem ser consistentes!
  • Parâmetro do método @Recover, Exception e deve ser colocado na primeira posição do parâmetro e o tipo deve ser consistente com o tipo lançado por @Retryable.
  • Os métodos @Retryable não podem mais usar try ... catch para capturar exceções para evitar que as exceções não sejam recebidas.

Programático (imperativo)

RetryTemplate template = new RetryTemplate();

TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);

template.setRetryPolicy(policy);

Foo result = template.execute(new RetryCallback<Foo>() {
    
    

    public Foo doWithRetry(RetryContext context) {
    
    
        // Do stuff that might fail, e.g. webservice operation
        return result;
    }

});

Uso de cadeia combinado com expressão lambda para simplificar o código

RetryTemplate template = RetryTemplate.builder()
				.maxAttempts(3)
				.fixedBackoff(1000)
				.retryOn(RemoteAccessException.class)
				.build();

template.execute(ctx -> {
    
    
    // ... do something
});

A parte lambda não reescreve a lógica de RetryCallback # doWithRetry.

public interface RetryCallback<T> {
    
    

    T doWithRetry(RetryContext context) throws Throwable;

}

Ouvinte:

public interface RetryListener {
    
    

    void open(RetryContext context, RetryCallback<T> callback);

    void onError(RetryContext context, RetryCallback<T> callback, Throwable e);

    void close(RetryContext context, RetryCallback<T> callback, Throwable e);
}

template.registerListener(new MethodInvocationRetryListenerSupport() {
    
    
      @Override
      protected <T, E extends Throwable> void doClose(RetryContext context,
          MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
    
    
        monitoringTags.put(labelTagName, callback.getLabel());
        Method method = callback.getInvocation()
            .getMethod();
        monitoringTags.put(classTagName,
            method.getDeclaringClass().getSimpleName());
        monitoringTags.put(methodTagName, method.getName());

        // register a monitoring counter with appropriate tags
        // ...
      }
    });

Acho que você gosta

Origin blog.csdn.net/ory001/article/details/108546494
Recomendado
Clasificación