Vodič za Spring Cloud Netflix - Hystrix

1. Pregled

U ovom ćemo uputstvu pokriti Spring Cloud Netflix Hystrix - knjižnicu tolerancije kvarova. Koristit ćemo knjižnicu i implementirati obrazac poduzeća Circuit Breaker, koji opisuje strategiju protiv kaskadnog kvara na različitim razinama u aplikaciji.

Načelo je analogno elektronici: Hystrix promatra metode za neuspješne pozive povezanim službama. Ako postoji takav kvar, otvorit će krug i proslijediti poziv na zamjensku metodu.

Knjižnica će tolerirati kvarove do praga. Osim toga, krug ostavlja otvorenim. Što znači, proslijedit će sve naredne pozive na zamjensku metodu, kako bi se spriječili budući kvarovi. To stvara vremenski međuspremnik da bi se povezana usluga oporavila iz stanja neuspjeha.

2. OSTALI Proizvođač

Da bismo stvorili scenarij koji pokazuje obrazac prekidača, prvo nam je potrebna usluga. Nazvat ćemo ga "REST Producer" jer pruža podatke za "REST Consumer" s omogućenom Hystrixom, a koji ćemo stvoriti u sljedećem koraku.

Stvorimo novi Maven projekt pomoću proljeće-boot-starter-web ovisnost:

 org.springframework.boot spring-boot-starter-web 2.2.6.OSLOBODI 

Sam projekt namjerno je jednostavan. Sastoji se od sučelja kontrolera s jednim @RequestMapping anotirana GET metoda koja vraća jednostavno a Niz, a @RestController implementirajući ovo sučelje i @SpringBootApplication.

Započet ćemo sa sučeljem:

javno sučelje GreetingController {@GetMapping ("/ pozdrav / {korisničko ime}") Pozdrav niza (@PathVariable ("korisničko ime") Korisničko ime niza); }

I provedba:

@RestController javna klasa GreetingControllerImpl implementira GreetingController {@Override javni String pozdrav (@PathVariable ("username") String username) {return String.format ("Hello% s! \ N", username); }}

Zatim ćemo zapisati glavnu klasu aplikacije:

@SpringBootApplication javna klasa RestProducerApplication {public static void main (String [] args) {SpringApplication.run (RestProducerApplication.class, args); }}

Da bismo dovršili ovaj odjeljak, preostaje nam samo konfigurirati aplikacijski port na kojem ćemo slušati. Nećemo koristiti zadani priključak 8080 jer bi port trebao ostati rezerviran za aplikaciju opisanu u sljedećem koraku.

Nadalje, definiramo naziv aplikacije kako bismo mogli potražiti našeg proizvođača iz klijentske aplikacije koju ćemo predstaviti kasnije.

Odredimo onda luku 9090 i ime ostatak-producent u našem primjena.svojstva datoteka:

server.port = 9090 spring.application.name = ostatak-proizvođač

Sada smo u mogućnosti testirati našeg proizvođača pomoću cURL-a:

$> curl // localhost: 9090 / pozdrav / Cid Zdravo Cid!

3. OSTALI Potrošač s Hystrixom

Za naš demonstracijski scenarij implementirat ćemo web-aplikaciju koja koristi REST uslugu iz prethodnog koraka RestTemplate i Hystrix. Radi jednostavnosti nazvat ćemo ga "OSTALI Potrošač".

Slijedom toga, kreiramo novi Maven projekt sa proljetni-oblak-starter-histriks, proljeće-boot-starter-web i opruga-čizma-starter-majčina dušica kao ovisnosti:

 org.springframework.cloud spring-cloud-starter-hystrix 1.4.7.RELEASE org.springframework.boot spring-boot-starter-web 2.2.6.RELEASE org.springframework.boot spring-boot-starter-thymeleaf 2.2.6. OSLOBOĐENJE 

Da bi prekidač funkcionirao, Hystix će skenirati @Komponenta ili @Servis komentirane satove za @HystixCommand anotiranim metodama, implementirajte proxy za njega i nadgledajte njegove pozive.

Stvorit ćemo a @Servis razred, koji će se ubrizgati u @Controller. Budući da gradimo web aplikaciju pomoću Thymeleafa, potreban nam je i HTML predložak koji će poslužiti kao prikaz.

Ovo će biti naša injekcija @Servis provedba a @HystrixCommand s pridruženom zamjenskom metodom. Ovaj rezervni element mora koristiti isti potpis kao i original:

@Service javna klasa GreetingService {@HystrixCommand (fallbackMethod = "defaultGreeting") javni String getGreeting (String korisničko ime) {return new RestTemplate () .getForObject ("// localhost: 9090 / pozdrav / {korisničko ime}", String.class, username ); } private String defaultGreeting (korisničko ime niza) {return "Hello User!"; }}

RestConsumerApplication bit će naša glavna klasa prijave. The @EnableCircuitBreaker napomena će skenirati put predavanja za bilo koju kompatibilnu implementaciju prekidača.

Da bismo eksplicitno koristili Hystrix, moramo ovu klasu označiti s @EnableHystrix:

@SpringBootApplication @EnableCircuitBreaker javna klasa RestConsumerApplication {javna statička void glavna (String [] args) {SpringApplication.run (RestConsumerApplication.class, args); }}

Postavit ćemo kontroler koristeći naš Pozdravna usluga:

@Controller javna klasa GreetingController {@Autowired private GreetingService pozdravService; @GetMapping ("/ get-pozdrav / {korisničko ime}") javni niz getGreeting (Model modela, @PathVariable ("korisničko ime") Korisničko ime niza) {model.addAttribute ("pozdrav", pozdravService.getGreeting (korisničko ime)); povratak "pozdrav-pogled"; }}

A ovdje je HTML predložak:

   Pozdrav od Hystrixa 

Da bismo osigurali da aplikacija preslušava na definiranom priključku, stavili smo sljedeće u primjena.svojstva datoteka:

poslužitelj.port = 8080

Da bismo vidjeli zaštitni prekidač Hystix na djelu, pokrećemo potrošača i usmjeravamo svoj preglednik na // localhost: 8080 / get-pozdrav / Cid. U normalnim okolnostima prikazat će se sljedeće:

Pozdrav Cid!

Da bismo simulirali kvar našeg proizvođača, jednostavno ćemo ga zaustaviti, a nakon završetka osvježavanja preglednika trebali bismo vidjeti generičku poruku, vraćenu iz zamjenske metode u našem @Servis:

Pozdrav korisniče!

4. OSTALI Potrošač s Hystrixom i glumom

Sada ćemo izmijeniti projekt iz prethodnog koraka tako da koristimo Spring Netflix Feign kao deklarativni REST klijent, umjesto Spring RestTemplate.

Prednost je u tome što smo kasnije u mogućnosti lako refaktorizirati naše sučelje klijenta Feign kako bi koristili Spring Netflix Eureka za otkrivanje usluge.

Da bismo započeli novi projekt, napravit ćemo kopiju našeg potrošača i dodati našeg proizvođača i proljeće-oblak-starter-finga kao ovisnosti:

 com.baeldung.spring.cloud proljeće-oblak-histriks-odmorište-proizvođač 1.0.0-SNAPSHOT org.springframework.cloud proljeće-oblak-starter-feign 1.1.5.Opusti 

Sada smo u mogućnosti koristiti svoj GreetingController proširiti klijenta koji glumi. Provest ćemo Hystrix rezervni oblik kao statična unutarnja klasa označena s @Komponenta.

Alternativno, mogli bismo definirati a @Grah anotirana metoda koja vraća instancu ove rezervne klase.

Svojstvo imena @FeignClient je obavezno. Koristi se za traženje aplikacije bilo otkrivanjem usluge putem Eureka klijenta ili URL-om, ako je dato ovo svojstvo:

@FeignClient (name = "rest-producent" url = "// localhost: 9090", fallback = GreetingClient.GreetingClientFallback.class) javno sučelje GreetingClient proširuje GreetingController {@Component javna statička klasa GreetingClientFallback implementira GreetingController {@Override @ public String PathVariable ("username") Korisničko ime niza) {return "Hello User!"; }}}

Za više informacija o korištenju Spring Netflix Eureke za otkrivanje usluga pogledajte ovaj članak.

U RestConsumerFeignApplication, stavit ćemo dodatnu napomenu kako bismo omogućili integraciju Feigna, zapravo, @EnableFeignClients, do glavne klase aplikacije:

@SpringBootApplication @EnableCircuitBreaker @EnableFeignClients javna klasa RestConsumerFeignApplication {public static void main (String [] args) {SpringApplication.run (RestConsumerFeignApplication.class, args); }}

Izmijenit ćemo kontroler tako da upotrebljava automatski ožičeni klijent privika, umjesto prethodno ubrizganog @Servis, da dohvatimo naš pozdrav:

@Controller javna klasa GreetingController {@Autowired private GreetingClient pozdravClient; @GetMapping ("/ get-pozdrav / {korisničko ime}") javni niz getGreeting (Model modela, @PathVariable ("korisničko ime") Korisničko ime niza) {model.addAttribute ("pozdrav", pozdravClient.greeting (korisničko ime)); povratak "pozdrav-pogled"; }}

Da bismo razlikovali ovaj primjer od prethodnog, izmijenit ćemo port za slušanje aplikacije u primjena.svojstva:

poslužitelj.port = 8082

Na kraju ćemo testirati ovog potrošača s omogućenom prijavom kao što je onaj iz prethodnog odjeljka. Očekivani rezultat trebao bi biti jednak.

5. Zamjena predmemorije s Hystrix

Sada ćemo dodati Hystrix u naš projekt Spring Cloud. U ovom projektu u oblaku imamo uslugu ocjenjivanja koja razgovara s bazom podataka i dobiva ocjene knjiga.

Pretpostavimo da je naša baza podataka zahtijevani resurs, a kašnjenje njenog odgovora može se vremenom razlikovati ili vremenom možda neće biti dostupno. Riješit ćemo ovaj scenarij tako da se Hystrix Circuit Breaker vrati u predmemoriju podataka.

5.1. Postavljanje i konfiguracija

Dodajmo i proljeće-oblak-starter-histriks ovisnost o našem modulu za ocjenu:

 org.springframework.cloud proljeće-oblak-starter-histriks 

Kad se ocjene umetnu / ažuriraju / izbrišu u bazu podataka, iste ćemo replicirati u predmemoriju Redis s pomoću Spremište. Da biste saznali više o Redisu, pogledajte ovaj članak.

Ažurirajmo RatingService za umotavanje metoda upita baze podataka u naredbu Hystrix sa @HystrixCommand i konfigurirajte ga sa zamjenom za čitanje iz Redisa:

@HystrixCommand (commandKey = "ratingByIdFromDB", fallbackMethod = "findCachedRatingById", ignoreExceptions = {RatingNotFoundException.class}) javna ocjena findRatingById (Long ratingId) {return Optional.ofNullable (ratingRepository. (RatingRepositor.d). novi RatingNotFoundException ("Ocjena nije pronađena. ID:" + ratingId)); } javna ocjena findCachedRatingById (Long ratingId) {return cacheRepository.findCachedRatingById (ratingId); }

Imajte na umu da rezervna metoda treba imati isti potpis zamotane metode i mora se nalaziti u istoj klasi. Sad kad findRatingById ne uspije ili se odgodi više od zadanog praga, Hystrix zamjenjuje na findCachedRatingById.

Kako se mogućnosti Hystrixa transparentno ubrizgavaju kao AOP savjet, moramo prilagoditi redoslijed slaganja savjeta, u slučaju da imamo druge savjete poput Springovih transakcijskih savjeta. Ovdje smo prilagodili proljetni transakcijski AOP savjet kako bi imao nižu prednost od Hystrix AOP savjeta:

@EnableHystrix @EnableTransactionManagement (order = Ordered.LOWEST_PRECEDENCE, mode = AdviceMode.ASPECTJ) javna klasa RatingServiceApplication {@Bean @Primary @Order (value = Ordered.HIGHEST_PRECEDENCE) public HystrixCommandAspect hystrixCommandAspect hystrixCommandAspect (HystrixCommandAspect) } // // grah, konfiguracije}

Ovdje smo prilagodili proljetni AOP savjet za transakcije tako da ima nižu prednost od savjeta Hystrix AOP.

5.2. Testiranje rezervnog Hystrixa

Sad kad smo konfigurirali sklop, možemo ga testirati srušivši H2 bazu podataka s kojom naše spremište komunicira. Ali prvo, pokrenimo instancu H2 kao vanjski proces, umjesto da je pokrenemo kao ugrađenu bazu podataka.

Kopirajmo H2 knjižnicu (h2-1.4.193.jar) u poznati direktorij i pokrenite H2 poslužitelj:

> java -cp h2-1.4.193.jar org.h2.tools.Server -tcp TCP poslužitelj pokrenut na tcp: //192.168.99.1: 9092 (samo lokalne veze)

Ažurirajmo sada URL izvora podataka našeg modula u rating-service.svojstva da pokažem na ovaj H2 poslužitelj:

spring.datasource.url = jdbc: h2: tcp: // localhost / ~ / ocjene

Svoje usluge možemo započeti kao što je dato u prethodnom članku iz serije Spring Cloud i testirati ocjene svake knjige rušenjem vanjske instance H2 koju pokrećemo.

Mogli smo vidjeti da kad baza podataka H2 nije dostupna, Hystrix se automatski vraća na Redis da pročita ocjene za svaku knjigu. Izvorni kod koji pokazuje ovaj slučaj upotrebe možete pronaći ovdje.

6. Korištenje opsega

Obično a @HytrixCommand anotirana metoda izvršava se u kontekstu spremišta niti. Ali ponekad treba biti pokrenut u lokalnom opsegu, na primjer, a @SessionScope ili a @RequestScope. To se može učiniti davanjem argumenata u napomeni naredbe:

@HystrixCommand (fallbackMethod = "getSomeDefault", commandProperties = {@HystrixProperty (name = "execu.isolation.strategy", value = "SEMAPHORE")})

7. Hystrix nadzorna ploča

Lijepa neobavezna značajka Hystrixa je mogućnost praćenja njegovog statusa na nadzornoj ploči.

Da bismo to omogućili, stavit ćemo proljeće-oblak-starter-histriks-nadzorna ploča i pokretač pokretača opruge-čizme u pom.xml našeg potrošača:

 org.springframework.cloud spring-cloud-starter-hystrix-dashboard 1.4.7.Opusti org.springframework.boot spring-boot-starter-aktuator 2.2.6.Opusti 

Prvo treba omogućiti označavanjem a @Konfiguracija s @EnableHystrixDashboard a potonji automatski omogućuje potrebne mjerne podatke unutar naše web aplikacije.

Nakon što završimo ponovno pokretanje aplikacije, usmjerit ćemo preglednik na // localhost: 8080 / hystrix, unesite URL mjernih podataka protoka Hystrix i započnite praćenje.

Konačno, trebali bismo vidjeti nešto poput ovoga:

Nadgledanje toka Hystrixa je nešto u redu, ali ako moramo gledati više aplikacija s omogućenim Hystrixom, postat će nezgodno. U tu svrhu Spring Cloud nudi alat pod nazivom Turbine, koji može agregirati tokove kako bi ih predstavio na jednoj Hystrix nadzornoj ploči.

Konfiguriranje turbine izvan je dosega ovog opisa, ali ovdje treba spomenuti mogućnost. Tako je također moguće prikupiti ove tokove putem poruka, koristeći Turbine stream.

8. Zaključak

Kao što smo do sada vidjeli, sada smo u mogućnosti implementirati obrazac prekidača koristeći Spring Netflix Hystrix zajedno s bilo kojim Springom RestTemplate ili proljetna Netflixova finga.

To znači da smo u mogućnosti trošiti usluge s uključenim rezervnim podacima koristeći zadane podatke i u mogućnosti smo nadzirati upotrebu tih podataka.

Kao i obično, izvore možemo pronaći na GitHubu.