1. Mecanismo de nova tentativa
Devido à instabilidade ou instabilidade da rede, as solicitações de interface geralmente falham. Quando tentamos novamente, conseguimos. Este é o mecanismo de nova tentativa.
Este artigo foi publicado pela primeira vez no blog pessoal do Java Teacher Pan : SpringBoot integra o componente spring-retry para implementar o mecanismo de nova tentativa
Seu principal objetivo é aumentar ao máximo a probabilidade de uma solicitação bem-sucedida, mas geralmente, se nossa solicitação falhar pela primeira vez, o código lançará uma exceção e terminará. Se você quiser solicitar novamente, pode ser necessário fazer manualmente operações, o que é muito inconveniente., a viabilidade também não é boa. Portanto, a estrutura Spring fornece suporte para o mecanismo de nova tentativa e pode ser usada em conjunto com Hystrix no Spring Cloud para evitar o acesso a instâncias anormais.
2. Elementos do mecanismo de nova tentativa
Os elementos do mecanismo de nova tentativa são os seguintes:
- Limite o número de novas tentativas
- O intervalo de tempo entre cada nova tentativa
- Alarme ou reversão dos resultados finais da falha
- Escolha tentar novamente em caso de exceções de falha específicas
3. Coisas a serem observadas sobre o mecanismo de nova tentativa
Para métodos não idempotentes, devemos utilizar o mecanismo de nova tentativa com cautela, pois pode causar consequências inesperadas.
A chamada idempotência significa que os resultados de uma solicitação ou de múltiplas solicitações iniciadas pelo usuário para a mesma operação são consistentes e não haverá efeitos colaterais causados por múltiplos cliques.
4. SpringBoot integra repetição de primavera
Vamos dar uma olhada em como devemos usar o SpringBoot para integrar o componente spring-retry para implementar o mecanismo de nova tentativa.
1) Adicione dependências
Primeiro, adicionamos dependências relevantes ao projeto SpringBoot pom.xml
, como segue:
<!-- 重试相关依赖包 -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2) Adicione a anotação @EnableRetry
Adicione a anotação @EnableRetry à classe de inicialização principal Application para oferecer suporte ao mecanismo de nova tentativa.
@SpringBootApplication
@EnableRetry
public class RetryApplication {
public static void main(String[] args) {
SpringApplication.run(RetryApplication.class, args);
}
}
Nota: @EnableRetry também pode ser usado em classes de configuração, classes ServiceImpl e métodos
3) Adicione a anotação @Retryable
Adicionamos anotações aos métodos que precisam ser repetidos @Retryable
para que o método possa ser repetido. Aqui listo um método em ServiceImpl:
@Service
public class RetryServiceImpl implements RetryService {
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))
public String testRetry() throws Exception {
System.out.println("开始执行代码:"+ LocalTime.now());
int code = 0;
// 模拟一直失败
if(code == 0){
// 这里可以使自定义异常,@Retryable中value需与其一致
throw new Exception("代码执行异常");
}
System.out.println("代码执行成功");
return "success";
}
}
Descrição: metadados de configuração @Retryable:
valor: Nova tentativa para o tipo de exceção especificado lançado, o que é especificado aqui é Exception
maxAttempts: Configure o número máximo de novas tentativas, aqui é configurado como 3 vezes (incluindo a primeira e a última vez)
atraso: O intervalo de atraso da primeira tentativa, configurado aqui é
um multiplicador de 2s: cada intervalo de nova tentativa é várias vezes o anterior, aqui é 1,5 vezes
4) Código de teste do controlador
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private RetryService retryService;
@GetMapping("/retry")
public String testRetry() throws Exception {
return retryService.testRetry();
}
}
5) Enviar solicitação
Depois de enviar a solicitação, descobrimos que a situação de impressão em segundo plano foi realmente tentada três vezes e uma exceção foi lançada apenas quando a última tentativa falhou. Os detalhes são os seguintes (você pode prestar atenção ao intervalo de tempo):
6) Suplemento: @Recover
Em circunstâncias normais, se ainda falharmos e lançarmos uma exceção após tentar novamente o número máximo definido de vezes, iremos tratá-la uniformemente por meio da classe global de tratamento de exceções, mas podemos realmente lidar com isso nós mesmos, o que pode ser alcançado por meio de anotações, como segue @Recover
:
@Service
public class RetryServiceImpl implements RetryService {
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))
public String testRetry() throws Exception {
System.out.println("开始执行代码:"+ LocalTime.now());
int code = 0;
if(code == 0){
// 这里可以使自定义异常,@Retryable中value需与其一致
throw new Exception("代码执行异常");
}
System.out.println("代码执行成功");
return "success";
}
/**
* 最终重试失败处理
* @param e
* @return
*/
@Recover
public String recover(Exception e){
System.out.println("代码执行重试后依旧失败");
return "fail";
}
}
Nota:
1) O tipo de exceção do parâmetro no método @Recover precisa ser consistente com o método de nova tentativa.
2) O tipo de valor de retorno do método deve ser consistente com o método de nova tentativa.
Teste novamente como segue (nenhuma outra exceção será lançada ):
Este artigo foi publicado pela primeira vez no blog pessoal do Java Teacher Pan : SpringBoot integra o componente spring-retry para implementar o mecanismo de nova tentativa