wzór: Circuit Breaker
Context
zastosowałeś architekturę Mikroserwisu.Usługi czasami współpracują przy obsłudze żądań.Gdy jedna usługa synchronicznie wywołuje drugą, zawsze istnieje możliwość, że druga usługa jest niedostępna lub wykazuje tak duże opóźnienie, że jest zasadniczo bezużyteczna.Cenne zasoby, takie jak wątki, mogą być zużywane w rozmówcy podczas oczekiwania na odpowiedź drugiej usługi.Może to prowadzić do wyczerpania zasobów, co sprawi, że usługa wywołująca nie będzie w stanie obsłużyć innych żądań.Awaria jednej usługi może potencjalnie przejść kaskadowo do innych usług w całej aplikacji.
Problem
jak zapobiec kaskadowej awarii sieci lub usługi do innych usług?
rozwiązanie
klient usługi powinien wywołać zdalną usługę za pośrednictwem serwera proxy, który działa w podobny sposób jak wyłącznik elektryczny.Gdy liczba kolejnych awarii przekroczy próg, wyłącznik wyłącza się, a na czas trwania okresu oczekiwania wszystkie próby wywołania usługi zdalnej zakończą się natychmiastowo niepowodzeniem.Po upływie czasu wyłącznik umożliwia przejście ograniczonej liczby żądań testowych.Jeśli te żądania się powiedzie, wyłącznik wznawia normalną pracę.W przeciwnym razie, jeśli wystąpi błąd, okres timeout rozpoczyna się ponownie.
przykład
RegistrationServiceProxy
z mikrousług Przykładowa aplikacja jest przykładem komponentu, który jest napisany w Scali, który używa wyłącznika do obsługi awarii podczas wywoływania usługi zdalnej.
@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
organizuje połączenia do registerUser()
, które mają być wykonane za pomocą wyłącznika.
funkcja wyłącznika jest włączona za pomocą adnotacji @EnableCircuitBreaker
w klasie UserRegistrationConfiguration
.
@EnableCircuitBreakerclass UserRegistrationConfiguration {
kontekst wynikowy
ten wzorzec ma następujące zalety:
- usługi obsługują awarię usług, które wywołują
ten wzorzec ma następujące problemy:
- trudno jest wybrać wartości limitu czasu bez tworzenia fałszywych alarmów lub wprowadzania nadmiernych opóźnień.
- Brama API będzie używać tego wzorca do wywoływania usług
- Router discovery po stronie serwera może używać tego wzorca do wywoływania usług
Zobacz także
- Netflix Hystrix to przykład biblioteki, która implementuje ten wzorzec