A repetição da primavera é uma função de energia independente do lote da mola, que implementa principalmente a tentativa e o fusível. Existem restrições de cenário para tentar novamente, e nem todos os cenários são adequados para tentar novamente, como verificação ilegal de parâmetros, operações de gravação etc. (você precisa considerar se a gravação é idempotente) não é adequada para tentar novamente. O tempo limite de chamada remota ou a interrupção da rede podem ser tentados. Na estrutura de governança de microsserviço, geralmente possui sua própria configuração de tentativa e tempo limite. Por exemplo, o dubbo pode definir tentativas = 1, tempo limite = 500 falha na chamada e tente novamente uma vez, e a chamada falha se não retornar após mais de 500ms. Na Spring Remof, você pode especificar o tipo de exceção que precisa ser repetido e definir o intervalo para cada tentativa e se a tentativa falhar, continue novamente novamente.
Design e implementação
RetryOperations definem a API de tentativa. RetryTemplate é a implementação do modo de modelo da API, que implementa a tentativa e a quebra do circuito. A API fornecida é a seguinte:
Abertura da interface pública {<t, e estende o throwable> t Execute (RETRYCALLBACK <t, e> retrycallback) lança e; } // Outras APIs foram omitidas RetryCallback define a operação que precisa ser executada. Depois de definir a operação, é a questão de como tentar novamente. RetryTemplate executa a lógica de como tentar novamente, formulando diferentes estratégias de repetição. A estratégia de tentativa padrão é SimpleRetryPlicy , o que significa que será repetido 3 vezes. Se a tentativa for bem -sucedida, você não continuará tentando novamente. E daí se a tentativa de 3 pés falhou? O processo termina ou retorna o resultado de baixo para cima. Para retornar o resultado de baixo para cima, você precisa configurar RecoveyCallBack . A partir do nome, você pode ver que esta é uma interface de retorno de chamada de baixo para cima, que é a lógica da execução depois que a tentativa falhou. Além do SimpleRetryPolicy , existem outras estratégias de repetição. Vamos dar uma olhada na interface RetryPolicy :
interface pública Retypolicy estende serializável {boolean canRretry (contexto de rerycontext); ReryContext aberto (pai -rerycontext); Void Close (contexto de rerycontext); Void Registertrowable (contexto de rerycontext, arremesso de arremesso);} canRetry é chamado toda vez que você tentar novamente. A condição de julgamento de se você pode continuar tentando novamente
Chamado Antes do início da repetição open , um contexto de nova tentativa será criado para RetryContext , e a pilha de nova tentativa será salva.
registerThrowable é chamado toda vez que a exceção é repetida (há uma exceção e continuará a tentar novamente)
Tome SimpleRetryPolicy como exemplo. Quando o número de tentismo atingir 3 (padrão 3 vezes), pare de tentar novamente e o número de repetições é salvo no contexto de nova tentativa.
Forneça a seguinte implementação de estratégia de tentativa:
Represente a estratégia de fallback refere -se a se cada tentativa está novamente novamente ou esperar um pouco antes de tentar novamente. Por padrão, você precisa especificar a política de retirada de BackoffRetryPolicy se precisar configurar um período de espera e tentar novamente. BackOffretRypolicy tem a seguinte implementação:
Representação com estado ou tentativa apátrida
A chamada tentativa de apátrida refere-se à tentativa de novo, concluída em um contexto de thread. Caso contrário, se a nova tentativa não concluída em um contexto de thread, tente novamente uma tentativa. A forma anterior SimpleRetryPolicy era uma tentativa apátrida porque a tentativa foi concluída em um loop. Então, o que acontece depois disso ou precisa ser repetido em um estado? Geralmente, existem duas situações: reversão da transação e disjuntor.
DataAccessException é excepcional. A tentativa não pode ser realizada, mas se outras exceções forem lançadas, você poderá tentar novamente.
O fusível significa não lidar com a tentativa no loop atual, mas no modo de tentativa global (não no contexto do thread). O disjuntor saltará do loop e as informações da pilha do contexto do thread serão inevitavelmente perdidas. Definitivamente, é necessário salvar essas informações em um "modo global". A implementação atual é colocada em um cache (implementação do mapa). Você pode continuar a tentar novamente depois de obtê -lo do cache na próxima vez.
Início rápido
Use @EnableRetry na classe que precisa executar a tentativa, se proxyTargetClass=true for definido, isso usa o CGLIB Dynamic Proxy:
@Configuration@enableretry (proxyTargetClass = true) @ComponentPublic Classe RezyExample {} Represente com base no número máximo de estratégia de tentativas, se a nova tentativa for repetida 3 vezes e a exceção ainda for lançada, a tentativa será interrompida e o retorno de chamada de baixo para cima será executado. Portanto, o resultado da saída final é Integer.MAX_VALUE :
private void reryexample3 () lança Exceção {RETRYTEMPLATE RETRYTEMPLATE = new RETRYTEMPLATE (); SimpleRetryPolicy SimpleRetryPolicy = new SimpleRetryPolicy (); SimpleRetryPolicy.SetMaxattempts (3); RETRYTEMPLATE.SETRRETRYPOLICY (SimpleRetryPolicy); Inteiro resultado = RETRYTEMPLATE.EXECUTE (novo RETRYCALLBACK <Inteiro, Exception> () {int i = 0; // Representar a operação @Override public integer DowithRetry (RETRYCONTEXT RETRYCONTRYCTEXT) lança exceção {Log.info ("contagem de retidos: {}", RETRYCONTEXT) }, novo recuperyCallback <Teger> () {// Retornete base @Override Public Inteiro Recuperação (RETRYCONTEXT RETRYCONTEXT) lança exceção {Log.info ("Após a nova nova): {}, método de recuperação chamado! log.info ("resultado final: {}", resultado); } private int len (int i) lança exceção {if (i <10) lançar uma nova exceção (i + "le 10"); retornar i; }A seguir, descreve como usar o modo de política de repetição do disjuntor (CircuitbreakerretriaPolicy). Os três parâmetros a seguir precisam ser definidos:
Julgamento de abertura e fechamento do disjuntor:
O código de teste é o seguinte:
Modelo de RETRYTEMPLATE = new RETRYTEMPLATE (); CircuitbreakerretriaPolicy Retrypolicy = new CircuitbreakerretriaPolicy (nova SimpleretryPolicy (3)); retrypolicy.setOpEntimeout (5000); retrypolicy.setReretTimeout (20000); template.setRetRyPolicy (Retropolicia); for (int i = 0; i <10; i ++) {//thread.sleep(100); tente {objeto key = "circuito"; boolean isforceRefresh = false; Estado de repetição = new DefaultretyState (chave, isforceRefresh); String result = template.execute (novo RETRYCALLBACK <String, RunTimeException> () {@Override public String DowithRetry (contexto RERYCONTEXT) lança RUNTimeException {Log.info ("RETYT Count: {}", context.getRetRyCount ()); ThrowAltElTime ("timeout"; String Recuperar (contexto de rerinchontext) lança a exceção {return "padrão"; log.info ("Resultado: {}", resultado); } catch (Exceção e) {System.out.println (e); }} Como isForceRefresh = false é definido, o valor de key = "circuit" (ou seja, rerycontext) será obtido do cache. Portanto, quando a tentativa falha e this.time < this.openWindow RetryContext
Desenvolvimento de anotação
Se a gravação de um RetryTemplate toda vez que você tiver um requisito de tentativa estiver muito inchado, o uso de anotações pode simplificar bastante o desenvolvimento e reduzir o código duplicado. Aqui está uma tentativa da estratégia máxima de tentativa implementada usando anotações:
@Retryable (value = sqldataexception.class, backoff = @backoff (value = 0l)) public string service3 () lança sqldataException {log.info ("serviço3 aberto"); lançar novas sqldataException (); } @Recover public string recuperar (sqldataException ne) {return "sqldataException recuperado"; }As anotações incluem:
@Enableretry
@Retryable
@Recuperar
@Backoff
@Circuitbreaker
@Enableretry: você pode tentar novamente? Quando a propriedade ProxyTargetClass é verdadeira (padrão false), use o CGLIB Proxy
@Retryable: o método que a anotação precisa ser tentativa
@Backoff: tente novamente a estratégia de fallback (tente agora ou espere um tempo antes de tentar novamente)
@Recover: para uso com métodos. Usado como um método "garantido" quando o @Retryable falha. O método da anotação @Recover deve ser consistente com o método "assinatura" da anotação @retryable. O primeiro parâmetro de entrada é a exceção a ser repetida. Outros parâmetros são consistentes com @retryable. O valor de retorno deve ser o mesmo, caso contrário, não pode ser executado!
@Circuitbreaker: usado para método, implemente o modo de quebra de circuito.
Para mais exemplos, seja bem-vindo ao meu github (https://github.com/happyxiaofan/springboot-learning-example). Obrigado
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.