padrão: disjuntor
contexto
aplicou a arquitectura de Microservice.Os serviços às vezes colaboram ao lidar com pedidos.Quando um serviço invoca síncronamente outro há sempre a possibilidade de que o outro serviço está indisponível ou está exibindo uma latência tão elevada que é essencialmente inutilizável.Recursos preciosos, tais como threads podem ser consumidos no chamador enquanto espera que o outro serviço para responder.Isso pode levar à exaustão de recursos, o que tornaria o serviço de chamada incapaz de lidar com outros pedidos.A falha de um serviço pode potencialmente cair em cascata para outros serviços ao longo da aplicação.
problema
como evitar que uma falha de rede ou de serviço de cascata para outros serviços?
solução
um cliente de serviço deve invocar um serviço remoto através de um proxy que funciona de forma semelhante a um disjuntor elétrico.Quando o número de falhas consecutivas atravessa um limiar, o disjuntor tropeça, e durante um período de tempo, todas as tentativas de invocar o serviço remoto falharão imediatamente.Depois que o tempo-limite expira, o disjuntor permite que um número limitado de pedidos de teste para passar.Se esses pedidos tiverem sucesso, o disjuntor recomeça a operação normal.Caso contrário, se houver uma falha o período de Tempo-Limite começa novamente.
Exemplo
RegistrationServiceProxy
a partir de Microservices Exemplo de aplicação é um exemplo de um componente que está escrito em Scala, que usa um disjuntor para lidar com falhas ao invocar um serviço remoto.
@Componentclass RegistrationServiceProxy @Autowired()(restTemplate: RestTemplate) extends RegistrationService { @Value("${user_registration_url}") var userRegistrationUrl: String = _ @HystrixCommand(commandProperties=Array(new HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="800"))) override def registerUser(emailAddress: String, password: String): Either = { try { val response = restTemplate.postForEntity(userRegistrationUrl, RegistrationBackendRequest(emailAddress, password), classOf) response.getStatusCode match { case HttpStatus.OK => Right(response.getBody.id) } } catch { case e: HttpClientErrorException if e.getStatusCode == HttpStatus.CONFLICT => Left(DuplicateRegistrationError) } }}
o @HystrixCommand
faz com que as chamadas para registerUser()
sejam executadas usando um disjuntor.
a funcionalidade do disjuntor está activa usando a anotação @EnableCircuitBreaker
na classe UserRegistrationConfiguration
.
@EnableCircuitBreakerclass UserRegistrationConfiguration {
Contexto Resultante
Este padrão tem as seguintes vantagens:
- Serviços de lidar com a falha dos serviços que eles invocam, em
Este padrão tem os seguintes problemas:
- é um desafio para a escolha de valores de tempo limite sem a criação de falsos positivos ou introdução de latência excessiva.
- A Microservice Chassi pode implementar este padrão
- Um Gateway de API vai usar este padrão para invocar serviços
- Um do lado do Servidor de descoberta de roteador pode usar esse padrão para invocar serviços
Veja também:
- Netflix Hystrix é um exemplo de uma biblioteca que implementa este padrão