model: Circuit Breaker
Context
ați aplicat arhitectura Microservice.Serviciile colaborează uneori la gestionarea cererilor.Când un serviciu invocă sincron altul, există întotdeauna posibilitatea ca celălalt serviciu să nu fie disponibil sau să prezinte o latență atât de mare, încât este în esență inutilizabil.Resursele prețioase, cum ar fi firele, ar putea fi consumate în apelant în timp ce așteaptă ca celălalt serviciu să răspundă.Acest lucru ar putea duce la epuizarea resurselor, ceea ce ar face ca serviciul de apelare să nu poată gestiona alte solicitări.Eșecul unui serviciu poate potențial cascadă la alte servicii în întreaga aplicație.
problemă
cum să preveniți o eroare de rețea sau de serviciu de la cascadă la alte servicii?
soluție
un client de servicii ar trebui să invoce un serviciu la distanță printr-un proxy care funcționează în mod similar cu un întrerupător electric.Când numărul de defecțiuni consecutive depășește un prag, întrerupătorul se declanșează și, pe durata unei perioade de expirare, toate încercările de a invoca serviciul la distanță vor eșua imediat.După expirarea timpului de expirare, întrerupătorul permite trecerea unui număr limitat de solicitări de testare.Dacă aceste solicitări reușesc, întrerupătorul reia funcționarea normală.În caz contrar, dacă există un eșec perioada de expirare începe din nou.
Example
RegistrationServiceProxy
din aplicația Microservices Example este un exemplu de componentă, care este scrisă în Scala, care utilizează un întrerupător de circuit pentru a gestiona eșecurile atunci când invocă un serviciu la distanță.
@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) } }}
@HystrixCommand
aranjează ca apelurile către registerUser()
să fie executate folosind un întrerupător de circuit.
funcționalitatea disjunctorului este activată utilizând adnotarea @EnableCircuitBreaker
din clasa UserRegistrationConfiguration
.
@EnableCircuitBreakerclass UserRegistrationConfiguration {
context rezultat
acest model are următoarele beneficii:
- serviciile gestionează eșecul serviciilor pe care le invocă
acest model are următoarele probleme:
- este dificil să alegeți valori de expirare fără a crea fals pozitive sau a introduce o latență excesivă.
- șasiul Microservice ar putea implementa acest model
- un gateway API va folosi acest model pentru a invoca servicii
- un router discovery de pe Server ar putea utiliza acest model pentru a invoca servicii
Vezi și
- Netflix Hystrix este un exemplu de bibliotecă care implementează acest model