Útmutató a rugalmassághoz4j
1. Áttekintés
Ebben az oktatóanyagban a Resilience4j könyvtárról fogunk beszélni.
A könyvtár segít a rugalmas rendszerek megvalósításában a távoli kommunikáció hibatűrésének kezelésével.
A könyvtárat a Hystrix ihlette, de sokkal kényelmesebb API-t és számos egyéb funkciót kínál, mint a Rate Limiter (túl gyakori kérések blokkolása), Bulkhead (a túl sok egyidejű kérés elkerülése) stb.
2. Maven Setup
A kezdéshez hozzá kell adnunk a célmodulokat a sajátunkhoz pom.xml (pl. itt hozzáadjuk a megszakítót):
io.github.resilience4j resilience4j-megszakító 0.12.1
Itt használjuk a biztosíték modul. Minden modul és azok legújabb verziói megtalálhatók a Maven Central oldalon.
A következő szakaszokban áttekintjük a könyvtár leggyakrabban használt moduljait.
3. Megszakító
Vegye figyelembe, hogy ehhez a modulhoz szükségünk van a ellenálló képesség4j-megszakító fent látható függőség.
A megszakító minta segít megelőzni a meghibásodások lépcsőfokát, ha egy távoli szolgáltatás nem működik.
Számos sikertelen próbálkozás után úgy gondolhatjuk, hogy a szolgáltatás nem érhető el / túlterhelt, és lelkesen elutasíthatunk minden későbbi kérést hozzá. Ily módon megtakaríthatjuk a rendszer erőforrásait a valószínűleg sikertelen hívásokra.
Lássuk, hogyan érhetjük el ezt a Resilience4j segítségével.
Először meg kell határoznunk a használni kívánt beállításokat. A legegyszerűbb mód az alapértelmezett beállítások használata:
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults ();
Lehetőség van egyéni paraméterek használatára is:
CircuitBreakerConfig config = CircuitBreakerConfig.custom () .failureRateThreshold (20) .ringBufferSizeInClosedState (5) .build ();
Itt az arány küszöbértéket 20% -ra és minimum 5 hívási kísérletre állítottuk be.
Ezután létrehozunk egy Biztosíték objektumot, és hívja rajta keresztül a távoli szolgáltatást:
interfész RemoteService {int folyamat (int i); } CircuitBreakerRegistry register = CircuitBreakerRegistry.of (config); CircuitBreaker circuitBreaker = register.circuitBreaker ("én"); Funkció díszítve = CircuitBreaker .decorateFunction (áramkörmegszakító, szolgáltatás :: folyamat);
Végül nézzük meg, hogyan működik ez a JUnit teszt segítségével.
Tízszer próbáljuk felhívni a szolgáltatást. Ellenőriznünk kell, hogy a hívást legalább ötször megkísérelték-e, majd leállították, amint a hívások 20% -a kudarcot vallott:
mikor (service.process (bármely (Integer.class))). thenThrow (új RuntimeException ()); mert (int i = 0; i <10; i ++) {próbálkozzon {díszített.alkalmazzon (i); } catch (Exception ignore) {}} verify (service, times (5)). process (any (Integer.class));
3.1. Megszakítók Állapotok és beállítások
A Biztosíték a három állapot egyikében lehet:
- ZÁRVA - minden rendben van, nincs rövidzárlat
- NYISD KI - a távoli szerver nem működik, az összes kérés rövidzárlatos
- HALF_OPEN - konfigurált idő eltelt az OPEN állapotba lépés óta és Biztosíték lehetővé teszi a kérelmek számára annak ellenőrzését, hogy a távoli szolgáltatás online állapotban van-e
A következő beállításokat konfigurálhatjuk:
- a meghibásodási küszöbérték, amely felett a Biztosíték megnyitja és megkezdi a rövidzárlatot
- a várakozási idő, amely meghatározza a Biztosíték nyitva kell maradnia, mielőtt félig nyitva állna
- a gyűrűpuffer mérete, amikor a Biztosíték félig nyitott vagy zárt
- szokás CircuitBreakerEventListener amelyik kezeli Biztosíték események
- szokás Állítmány amely értékeli, hogy egy kivételnek meghibásodásnak kell-e számítania, és ezáltal növelnie kell a meghibásodási arányt
4. Rate Limiter
Az előző szakaszhoz hasonlóan ehhez a funkcióhoz a rugalmasság4j-ratelimiter függőség.
Ahogy a neve is mutatja, ez a funkció lehetővé teszi bizonyos szolgáltatásokhoz való hozzáférés korlátozását. API-ja nagyon hasonlít a Megszakítók - vannak Iktató hivatal, Konfig és Limiter osztályok.
Íme egy példa a megjelenésére:
RateLimiterConfig config = RateLimiterConfig.custom (). LimitForPeriod (2) .build (); RateLimiterRegistry register = RateLimiterRegistry.of (config); RateLimiter rateLimiter = register.rateLimiter ("én"); Dekorált függvény = RateLimiter.decorateFunction (rateLimiter, service :: process);
Most minden hívás a díszített szervizblokkra, ha szükséges, hogy megfeleljen a sebességkorlátozó konfigurációjának.
Konfigurálhatunk olyan paramétereket, mint:
- a limit frissítésének időszaka
- a frissítési periódus engedélyeinek korlátja
- az alapértelmezett várakozás az engedély időtartamára
5. Válaszfal
Itt először szükségünk lesz a rugalmasság4j-válaszfal függőség.
Lehetséges egy adott szolgáltatásra korlátozni az egyidejű hívások számát.
Lássunk egy példát a Bulkhead API használatára egyidejű hívások maximális számának konfigurálásához:
BulkheadConfig config = BulkheadConfig.custom (). MaxConcurrentCalls (1) .build (); BulkheadRegistry register = BulkheadRegistry.of (config); Válaszfal válaszfal = register.bulkhead ("én"); Funkció díszítve = Bulkhead.decorateFunction (válaszfal, szolgáltatás :: folyamat);
A konfiguráció teszteléséhez meghívjuk az álszolgáltatás módszerét.
Ezután biztosítjuk ezt Válaszfal nem engedélyez más hívásokat:
CountDownLatch retesz = new CountDownLatch (1); mikor (service.process (anyInt ())). thenAnswer (meghívás -> {latch.countDown (); Thread.currentThread (). join (); return null;}); ForkJoinTask task = ForkJoinPool.commonPool (). Submit (() -> {próbáld ki {díszített.apply (1);} végül {bulkhead.onComplete ();}}); retesz.várakozik (); assertThat (válaszfal.isCallPermitted ()). isFalse ();
A következő beállításokat konfigurálhatjuk:
- a válaszfal által megengedett párhuzamos végrehajtások maximális mennyisége
- a szál maximális időtartama, amíg egy telített válaszfalba próbál belépni
6. Próbálja újra
Ehhez a funkcióhoz hozzá kell adnunk a resilience4j-próbálkozzon újra könyvtár a projekthez.
Tudunk próbálkozzon újra egy sikertelen hívással a Retry API használatával:
RetryConfig config = RetryConfig.custom (). MaxAtt kísérletek (2) .build (); RetryRegistry register = RetryRegistry.of (config); Újrapróbálkozás = regisztráció.retry ("én"); Funkció díszítve = Retry.decorateFunction (próbálkozzon újra, (Egész szám s) -> {szolgáltatás.folyamat (ok); return null;});
Most utánozzunk egy olyan helyzetet, amikor a távoli szolgáltatási hívás során kivételt képezünk, és győződjünk meg arról, hogy a könyvtár automatikusan újrapróbálja a sikertelen hívást:
mikor (service.process (anyInt ())). thenThrow (new RuntimeException ()); próbáld ki a {díszített.alkalmazás (1); sikertelen ("Várható kivétel vetése, ha minden újrapróbálkozás sikertelen"); } catch (e kivétel) {verify (service, times (2)). process (any (Integer.class)); }
A következőket is konfigurálhatjuk:
- a max. kísérletek száma
- az újrapróbálkozás előtti várakozási idő
- egyedi funkció a hiba utáni várakozási intervallum módosítására
- szokás Állítmány amely kiértékeli, hogy egy kivétel eredményezheti-e a hívás újrapróbálkozását
7. Gyorsítótár
A Cache modulhoz a resilience4j-cache függőség.
Az inicializálás kissé eltérően néz ki, mint a többi modul:
javax.cache.Cache cache = ...; // Itt használja a megfelelő gyorsítótárat. Gyorsítótár cacheContext = Cache.of (cache); Funkció díszítve = Cache.decorateSupplier (cacheContext, () -> service.process (1));
Itt a gyorsítótárat a használt JSR-107 gyorsítótár-megvalósítás végzi, és a Resilience4j lehetőséget nyújt annak alkalmazására.
Vegye figyelembe, hogy a függvények (például Cache.decorateFunction (Funkció)), az API csak támogatja Támogató és Hívható típusok.
8. TimeLimiter
Ehhez a modulhoz hozzá kell adnunk a resilience4j-timelimiter függőség.
Lehetséges korlátozza a távoli szolgáltatás hívására fordított idő mennyiségét a TimeLimiter használatával.
A demonstráláshoz állítsunk fel egy TimeLimiter 1 milliszekundum konfigurált időtúllépés esetén:
hosszú ttl = 1; TimeLimiterConfig config = TimeLimiterConfig.custom (). TimeoutDuration (Durill.ofMillis (ttl)). Build (); TimeLimiter timeLimiter = TimeLimiter.of (config);
Ezután ellenőrizzük, hogy a Resilience4j hív-e Future.get () a várható időtúllépéssel:
Future futureMock = gúny (Future.class); Hívható limitedCall = TimeLimiter.decorateFutureSupplier (timeLimiter, () -> futureMock); limitedCall.call (); ellenőrizze (futureMock) .get (ttl, TimeUnit.MILLISECONDS);
Kombinálhatjuk azzal is Biztosíték:
Callable chainedCallable = CircuitBreaker.decorateCallable (circuitBreaker, limitedCall);
9. Kiegészítő modulok
A Resilience4j számos kiegészítő modult is kínál, amelyek megkönnyítik integrálását a népszerű keretrendszerekkel és könyvtárakkal.
Néhány legismertebb integráció:
- Tavaszi csizma - resilience4j-spring-boot modul
- Ratpack - resilience4j-ratpack modul
- Utólagos felszerelés - rugalmasság4j-utólagos felszerelés modul
- Vertx - rugalmasság4j-vertx modul
- Dropwizard - rugalmasság4j-metrikák modul
- Prométheusz - ellenálló képesség4j-prometheus modul
10. Következtetés
Ebben a cikkben átnéztük a Resilience4j könyvtár különböző aspektusait, és megtanultuk, hogyan kell használni a különböző hibatűrési problémák kezelésére a szerverek közötti kommunikáció során.
Mint mindig, a fenti minták forráskódja a GitHub oldalon található.