Úvod do systému Hystrix

1. Prehľad

Typický distribuovaný systém pozostáva z mnohých služieb spolupracujúcich spoločne.

Tieto služby sú náchylné na zlyhanie alebo oneskorené reakcie. Ak služba zlyhá, môže to mať vplyv na ďalšie služby, ktoré majú vplyv na výkon a možné zneprístupnenie ostatných častí aplikácie alebo v najhoršom prípade môžu celú aplikáciu poškodiť.

Samozrejme, že sú k dispozícii riešenia, ktoré pomáhajú zvyšovať odolnosť aplikácií a odolnosť voči chybám - jedným z takýchto rámcov je Hystrix.

Knižnica rámca Hystrix pomáha riadiť interakciu medzi službami poskytovaním tolerancie chýb a latencie. Zlepšuje celkovú odolnosť systému izoláciou zlyhávajúcich služieb a zastavením kaskádového efektu zlyhaní.

V tejto sérii príspevkov začneme tým, že sa pozrieme na to, ako Hystrix prichádza na záchranu, keď zlyhá služba alebo systém, a čo môže Hystrix za týchto okolností dosiahnuť.

2. Jednoduchý príklad

Spôsob, akým spoločnosť Hystrix poskytuje toleranciu voči chybám a latencii, je izolácia a zabalenie hovorov do vzdialených služieb.

V tomto jednoduchom príklade zabalíme hovor do run () metóda HystrixCommand:

class CommandHelloWorld rozširuje HystrixCommand {private String name; CommandHelloWorld (názov reťazca) {super (HystrixCommandGroupKey.Factory.asKey ("ExampleGroup")); this.name = meno; } @Override protected String run () {return "Hello" + name + "!"; }}

a hovor vykonáme nasledovne:

@Test public void givenInputBobAndDefaultSettings_whenCommandExecuted_thenReturnHelloBob () {assertThat (nový CommandHelloWorld ("Bob"). Execute (), equalTo ("Hello Bob!")); }

3. Nastavenie Maven

Aby sme mohli použiť Hystrix v projektoch Maven, musíme mať hystrix-core a rxjava-jadro závislosť od Netflixu v projekte pom.xml:

 com.netflix.hystrix hystrix-core 1.5.4 

Najnovšiu verziu nájdete vždy tu.

 com.netflix.rxjava rxjava-core 0.20.7 

Najnovšiu verziu tejto knižnice nájdete vždy tu.

4. Nastavenie vzdialenej služby

Začnime simuláciou príkladu zo skutočného sveta.

V príklade nižšie, trieda RemoteServiceTestSimulator predstavuje službu na vzdialenom serveri. Má metódu, ktorá po stanovenej dobe odpovie správou. Môžeme si predstaviť, že toto čakanie je simuláciou časovo náročného procesu na vzdialenom systéme, ktorého výsledkom je oneskorená odpoveď na volajúcu službu:

trieda RemoteServiceTestSimulator {súkromné ​​dlhé čakanie; RemoteServiceTestSimulator (dlhé čakanie) vyvolá InterruptedException {this.wait = wait; } String execute () hodí InterruptedException {Thread.sleep (počkajte); návrat "Úspech"; }}

A tu je náš vzorový klient ktorý volá RemoteServiceTestSimulator.

Hovor do služby je izolovaný a zabalený do run () metóda a HystrixCommand. Jedná sa o tento obal, ktorý poskytuje odolnosť, ktorej sme sa dotkli vyššie:

trieda RemoteServiceTestCommand rozširuje HystrixCommand {private RemoteServiceTestSimulator remoteService; RemoteServiceTestCommand (konfigurátor nastavovača, RemoteServiceTestSimulator remoteService) {super (konfigurácia); this.remoteService = remoteService; } @Override chránený String run () vyvolá výnimku {return remoteService.execute (); }}

Hovor sa uskutoční zavolaním na vykonať () metóda na inštancii RemoteServiceTestCommand objekt.

Nasledujúci test ukazuje, ako sa to deje:

@Test public void givenSvcTimeoutOf100AndDefaultSettings_whenRemoteSvcExecuted_thenReturnSuccess () vyvolá InterruptedException {HystrixCommand.Setter config = HystrixCommand .Setter .withGroupKey (HystrixCommandGroupKey.Factory. " assertThat (nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (100)). execute (), equalTo ("Úspech")); }

Doteraz sme videli, ako zabaliť vzdialené servisné volania do HystrixCommand objekt. V nasledujúcej časti sa pozrime, ako riešiť situáciu, keď sa vzdialená služba začne zhoršovať.

5. Práca so vzdialenou službou a obranné programovanie

5.1. Defenzívne programovanie s časovým limitom

Všeobecným programovacím postupom je stanovenie časových limitov pre volania do vzdialených služieb.

Začnime tým, ako sa nastaví časový limit HystrixCommand a ako pomáha skratom:

@Test public void dané HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter (); commandProperties.withExecutionTimeoutInMilliseconds (10_000); config.andCommandPropertiesDefaults (commandProperties); assertThat (nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (500)). execute (), equalTo ("Úspech")); }

Vo vyššie uvedenom teste oneskorujeme reakciu služby nastavením časového limitu na 500 ms. Nastavujeme tiež časový limit spustenia HystrixCommand 10 000 ms, čo poskytuje dostatok času na odpoveď vzdialenej služby.

Teraz sa pozrime, čo sa stane, keď je časový limit vykonania kratší ako volanie časového limitu služby:

@Test (expect = HystrixRuntimeException.class) public void givenSvcTimeoutOf15000AndExecTimeoutOf5000_whenRemoteSvcExecuted_thenExpectHre () vyvolá InterruptedException {HystrixCommand.Setter config = HystrixCommand .Setter .withG. HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter (); commandProperties.withExecutionTimeoutInMilliseconds (5_000); config.andCommandPropertiesDefaults (commandProperties); nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (15_000)). execute (); }

Všimnite si, ako sme znížili latku a nastavili časový limit vykonania na 5 000 ms.

Očakávame, že služba odpovie do 5 000 ms, zatiaľ čo sme nastavili, aby služba odpovedala po 15 000 ms. Ak si všimnete, že pri vykonávaní testu sa test ukončí po 5 000 ms namiesto čakania na 15 000 ms a vyhodí HystrixRuntimeException.

Toto demonštruje, ako Hystrix nečaká na odpoveď dlhšie ako nakonfigurovaný časový limit. Vďaka tomu bude systém chránený systémom Hystrix pohotovejší.

V nasledujúcich častiach sa pozrieme na nastavenie veľkosti fondu vlákien, ktorá zabráni vyčerpaniu vlákien, a prediskutujeme jeho výhody.

5.2. Defenzívne programovanie s obmedzeným počtom vlákien

Nastavenie časových limitov pre servisné volanie nerieši všetky problémy spojené so vzdialenými službami.

Keď vzdialená služba začne reagovať pomaly, typická aplikácia bude pokračovať v volaní na túto vzdialenú službu.

Aplikácia nevie, či je vzdialená služba v poriadku alebo nie, a nové vlákna sa objavujú zakaždým, keď príde požiadavka. To spôsobí, že sa budú používať vlákna na serveri, ktorý už má problémy.

Nechceme, aby sa to stalo, pretože tieto vlákna potrebujeme pre ďalšie vzdialené volania alebo procesy bežiace na našom serveri, a tiež sa chceme vyhnúť zvýšeniu využitia procesora.

Pozrime sa, ako nastaviť veľkosť fondu vlákien HystrixCommand:

@ Test verejné neplatné vzhľadom HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter (); commandProperties.withExecutionTimeoutInMilliseconds (10_000); config.andCommandPropertiesDefaults (commandProperties); config.andThreadPoolPropertiesDefaults (HystrixThreadPoolProperties.Setter () .withMaxQueueSize (10) .withCoreSize (3) .withQueueSizeRejectionThreshold (10)); assertThat (nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (500)). execute (), equalTo ("Úspech")); }

Vo vyššie uvedenom teste nastavujeme maximálnu veľkosť frontu, veľkosť jadra frontu a veľkosť odmietnutia frontu. Hystrix začne odmietať žiadosti, keď maximálny počet vlákien dosiahol 10 a front úloh dosiahol veľkosť 10.

Veľkosť jadra je počet vlákien, ktoré vždy zostanú nažive v skupine vlákien.

5.3. Defenzívne programovanie so vzorom ističa skratu

Stále však existuje vylepšenie, ktoré môžeme urobiť v prípade vzdialených servisných hovorov.

Uvažujme o prípade, že vzdialená služba začala zlyhávať.

Nechceme na to neustále strieľať a zbytočne míňať zdroje. V ideálnom prípade by sme chceli prestať s požiadavkami na určitý čas, aby sme službe poskytli čas na zotavenie pred obnovením požiadaviek. Toto sa nazýva Skratovač vzor.

Pozrime sa, ako Hystrix implementuje tento vzor:

@Test public void givenCircuitBreakerSetup_whenRemoteSvcCmdExecuted_thenReturnSuccess () vyvolá InterruptedException {HystrixCommand.Setter config = HystrixCommand. Setter .withGroupKey (HystrixCommandGroupKey.Factory.asKey) Vlastnosti HystrixCommandProperties.Setter = HystrixCommandProperties.Setter (); properties.withExecutionTimeoutInMilliseconds (1000); properties.withCircuitBreakerSleepWindowInMilliseconds (4000); properties.withExecutionIsolationStrategy (HystrixCommandProperties.ExecutionIsolationStrategy.THREAD); properties.withCircuitBreakerEnabled (true); properties.withCircuitBreakerRequestVolumeThreshold (1); config.andCommandPropertiesDefaults (vlastnosti); config.andThreadPoolPropertiesDefaults (HystrixThreadPoolProperties.Setter () .withMaxQueueSize (1) .withCoreSize (1) .withQueueSizeRejectionThreshold (1)); assertThat (this.invokeRemoteService (config, 10_000), equalTo (null)); assertThat (this.invokeRemoteService (config, 10_000), equalTo (null)); assertThat (this.invokeRemoteService (config, 10_000), equalTo (null)); Závit. Spánok (5 000); assertThat (nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (500)). execute (), equalTo ("Úspech")); assertThat (nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (500)). execute (), equalTo ("Úspech")); assertThat (nový RemoteServiceTestCommand (konfigurácia, nový RemoteServiceTestSimulator (500)). execute (), equalTo ("Úspech")); }
public String invokeRemoteService (HystrixCommand.Setter config, int timeout) vyvolá InterruptedException {String response = null; skus {response = new RemoteServiceTestCommand (config, new RemoteServiceTestSimulator (timeout)). execute (); } catch (HystrixRuntimeException ex) {System.out.println ("ex =" + ex); } návratová odpoveď; }

Vo vyššie uvedenom teste sme nastavili rôzne vlastnosti ističa. Najdôležitejšie sú:

  • The CircuitBreakerSleepWindow ktorá je nastavená na 4 000 ms. Týmto sa konfiguruje okno ističa a definuje sa časový interval, po ktorom bude požiadavka na vzdialenú službu obnovená
  • The CircuitBreakerRequestVolumeThreshold ktorá je nastavená na 1 a definuje minimálny počet požiadaviek potrebných pred zohľadnením poruchovosti

S vyššie uvedenými nastaveniami, naše HystrixCommand bude teraz otvorený po dvoch neúspešných požiadavkách. Tretia požiadavka nenarazí ani na vzdialenú službu, aj keď sme nastavili oneskorenie služby na 500 ms, Hystrix skrat a naša metóda sa vráti nulový ako odpoveď.

Následne pridáme a Thread.sleep (5 000) aby sme prekročili hranicu spánkového okna, ktorú sme nastavili. Toto spôsobí Hystrix uzavrieť okruh a následné požiadavky budú úspešne prebehnúť.

6. Záver

Stručne povedané, systém Hystrix je navrhnutý tak, aby:

  1. Poskytujte ochranu a kontrolu nad zlyhaniami a latenciou zo služieb, ku ktorým sa zvyčajne pristupuje cez sieť
  2. Zastavte kaskádové zlyhanie vyplývajúce z výpadku niektorých služieb
  3. Zlyhajte rýchlo a rýchlo sa zotavte
  4. Ak je to možné, elegantne degradujte
  5. Monitorovanie a varovanie riadiaceho centra v prípade zlyhania v reálnom čase

V nasledujúcom príspevku uvidíme, ako spojiť výhody Hystrixu s jarným rámcom.

Celý kód projektu a všetky príklady nájdete v projekte github.


$config[zx-auto] not found$config[zx-overlay] not found