Útmutató a mikroszolgáltatások közötti tranzakciókhoz

1. Bemutatkozás

Ebben a cikkben megvitatjuk a tranzakciók mikroszolgáltatások közötti megvalósításának lehetőségeit.

A tranzakciók alternatíváit is megvizsgáljuk egy elosztott mikroszolgáltatási forgatókönyvben.

2. Kerülje a tranzakciókat a mikroszolgáltatások között

Az elosztott tranzakció nagyon összetett folyamat, sok mozgó alkatrésszel, amelyek meghibásodhatnak. Továbbá, ha ezek az alkatrészek különböző gépeken vagy akár különböző adatközpontokban futnak, akkor a tranzakció végrehajtásának folyamata nagyon hosszúvá és megbízhatatlanná válhat.

Ez komolyan befolyásolhatja a felhasználói élményt és a rendszer teljes sávszélességét. Így Az elosztott tranzakciók problémájának egyik legjobb megoldása az, ha teljes mértékben elkerüljük azokat.

2.1. Példa tranzakciót igénylő architektúrára

Általában a mikroszolgáltatást úgy tervezik meg, hogy független és önmagában is hasznos legyen. Képesnek kell lennie valamilyen atomi üzleti feladat megoldására.

Ha feloszthatnánk rendszerünket ilyen mikropiacokon, akkor jó eséllyel egyáltalán nem lesz szükségük tranzakciók végrehajtására közöttük.

Vizsgáljuk meg például a felhasználók közötti sugárzott üzenetküldés rendszerét.

A felhasználó A mikroszolgáltatás a felhasználói profillal (új felhasználó létrehozása, profiladatok szerkesztése stb.) foglalkozna, a következő mögöttes tartományi osztállyal:

@Entity public class A felhasználó végrehajtja a Serializable {@Id @GeneratedValue (strategy = GenerationType.AUTO) privát hosszú azonosítót; @Basic private String név; @Basic private String vezetéknév; @Basic private Instant lastMessageTime; }

A üzenet a mikroszolgáltatás a műsorszolgáltatással foglalkozna. Beépíti az entitást Üzenet és minden körülötte:

@Entity public class Message végrehajtja a Serializable {@Id @GeneratedValue (strategy = GenerationType.AUTO) privát hosszú azonosítót; @Basic private long userId; @Basic private String tartalom; @Basic privát azonnali üzenetTimestamp; }

Mindegyik mikroszolgáltatásnak saját adatbázisa van. Figyelje meg, hogy nem hivatkozunk az entitásra Felhasználó az entitástól Üzenet, mivel a felhasználói osztályok nem érhetők el a üzenet mikroszolgáltatás. Csak azonosító szerint hivatkozunk a felhasználóra.

Most a Felhasználó entitás tartalmazza a lastMessageTime mezőbe, mert a profiljában szeretnénk megjeleníteni az utolsó felhasználói tevékenység idővel kapcsolatos információkat.

Új üzenet hozzáadásához a felhasználóhoz és frissítéséhez lastMessageTime, most tranzakciót kell végrehajtanunk a mikroszolgáltatások között.

2.2. Alternatív megközelítés tranzakciók nélkül

Megváltoztathatjuk a mikroszolgáltatási architektúránkat és eltávolíthatjuk a mezőt lastMessageTime tól Felhasználó entitás.

Akkor ezt az időt megjeleníthetjük a felhasználói profilban úgy, hogy külön kérést adunk ki az üzenetek mikroszolgáltatásának, és megtaláljuk a maximumot messageTimestamp érték a felhasználó összes üzenetéhez.

Valószínűleg, ha a üzenet A mikroszolgáltatás nagy terhelés alatt áll, vagy akár le is áll, nem tudjuk megjeleníteni a felhasználó utolsó üzenetének idejét a profiljában.

De ez elfogadhatóbb lehet, mint egy elosztott tranzakció elmulasztása az üzenet mentése érdekében, csak azért, mert a felhasználói mikroszolgáltatás nem válaszolt időben.

Természetesen vannak bonyolultabb forgatókönyvek, amikor üzleti folyamatot kell végrehajtanunk több mikroszolgáltatáson keresztül, és nem akarjuk megengedni az ellentmondást e mikroszolgáltatások között.

3. Kétfázisú protokoll

A kétfázisú protokoll (vagy 2PC) egy tranzakció végrehajtásának mechanizmusa a különböző szoftver-összetevők (több adatbázis, üzenetsorok stb.) Között

3.1. A 2PC építészete

Az elosztott tranzakció egyik fontos résztvevője a tranzakció-koordinátor. Az elosztott tranzakció két lépésből áll:

  • Felkészülés fázisa - ebben a szakaszban a tranzakció minden résztvevője felkészül a kötelezettségvállalásra, és értesíti a koordinátort arról, hogy készen áll a tranzakció teljesítésére
  • Végrehajtás vagy visszagörgetés szakasz - ebben a szakaszban a tranzakció-koordinátor kiad egy végrehajtási vagy egy visszagörgetési parancsot az összes résztvevő számára

A 2PC-vel az a probléma, hogy meglehetősen lassú ahhoz, hogy egyetlen mikroszolgáltatást működtessünk.

A mikroszolgáltatások közötti tranzakció összehangolása, még akkor is, ha ugyanazon a hálózaton vannak, valóban lelassíthatja a rendszert, ezért ezt a megközelítést általában nem alkalmazzák nagy terhelés esetén.

3.2. XA szabvány

Az XA szabvány specifikáció a 2PC elosztott tranzakciók lebonyolítására a támogató erőforrások között. Bármely JTA-kompatibilis alkalmazásszerver (JBoss, GlassFish stb.) Már alapértelmezés szerint támogatja.

Az elosztott tranzakciókban részt vevő erőforrások lehetnek például két különböző mikroszolgáltatás két adatbázisa.

Ennek a mechanizmusnak a kihasználásához azonban az erőforrásokat egyetlen JTA platformra kell telepíteni. Ez nem mindig valósítható meg egy mikroszolgáltatási architektúra esetében.

3.3. REST-AT Normál huzat

Egy másik javasolt szabvány a REST-AT, amelyet a RedHat némi fejlesztésen esett át, de még mindig nem került ki a tervezetből. Ezt azonban a WildFly alkalmazásszerver már a dobozon kívül támogatja.

Ez a szabvány lehetővé teszi az alkalmazáskiszolgáló tranzakció-koordinátorként való használatát egy adott REST API-val az elosztott tranzakciók létrehozásához és csatlakozásához.

Azoknak a RESTful webszolgáltatásoknak, amelyek részt kívánnak venni a kétfázisú tranzakcióban, egy adott REST API-t is támogatniuk kell.

Sajnos az elosztott tranzakció áthidalásához a mikroszolgáltatás helyi erőforrásaihoz továbbra is vagy egy JTA platformra kell telepítenünk ezeket az erőforrásokat, vagy meg kell oldanunk egy nem triviális feladatot, hogy ezt a hidat mi magunk írjuk meg.

4. Végső következetesség és kompenzáció

A mikroszolgáltatások közötti konzisztencia kezelésének egyik legmegvalósíthatóbb modellje a következetesség.

Ez a modell nem kényszeríti ki az elosztott ACID-tranzakciókat a mikroszolgáltatások között. Ehelyett javasol bizonyos mechanizmusok alkalmazását annak biztosítására, hogy a rendszer végül a jövőben valamikor konzisztens legyen.

4.1. Az esetleges következetesség esete

Tegyük fel például, hogy meg kell oldanunk a következő feladatot:

  • regisztráljon felhasználói profilt
  • végezzen néhány automatizált háttérellenőrzést arról, hogy a felhasználó valóban hozzáférhet-e a rendszerhez

A második feladat például annak biztosítása, hogy ezt a felhasználót valamilyen okból nem tiltották ki a szervereinkről.

De ehhez időbe telhet, és szeretnénk külön egy mikroszolgáltatásba kivonni. Nem lenne ésszerű olyan hosszú ideig várakozni a felhasználót, hogy tudják, sikeresen regisztrálták.

Megoldásának egyik módja az üzenetvezérelt megközelítés lenne, beleértve a kompenzációt is. Vegyük figyelembe a következő architektúrát:

  • a felhasználó mikroszolgáltatás, amelynek feladata felhasználói profil regisztrálása
  • a érvényesítés mikroszolgáltatás, amelynek feladata háttérellenőrzés
  • a tartós sorokat támogató üzenetküldő platform

Az üzenetküldő platform biztosíthatja, hogy a mikroszolgáltatások által küldött üzenetek továbbra is fennmaradjanak. Ezután később szállítanák őket, ha a vevő jelenleg nem lenne elérhető

4.2. Boldog forgatókönyv

Ebben az architektúrában egy boldog forgatókönyv lenne:

  • a felhasználó A microservice regisztrálja a felhasználót, és információkat tárol róla a helyi adatbázisában
  • a felhasználó A microservice jelöli ezt a felhasználót. Jelezheti, hogy ezt a felhasználót még nem hitelesítették, és nincs hozzáférése a rendszer teljes funkcionalitásához
  • a regisztráció megerősítését elküldik a felhasználónak azzal a figyelmeztetéssel, hogy a rendszer nem minden funkciója érhető el azonnal
  • a felhasználó A microservice üzenetet küld a érvényesítés mikroszolgáltatás a felhasználó háttérellenőrzésének elvégzéséhez
  • a érvényesítés A microservice futtatja a háttérellenőrzést és üzenetet küld a felhasználó mikroszolgáltatás az ellenőrzés eredményeivel
    • ha az eredmények pozitívak, a felhasználó A mikroszolgáltatás letiltja a felhasználót
    • ha az eredmények negatívak, a felhasználó A microservice törli a felhasználói fiókot

Miután elvégeztük ezeket a lépéseket, a rendszernek következetes állapotban kell lennie. Úgy tűnik azonban, hogy egy ideig a felhasználói entitás hiányos állapotban van.

Az utolsó lépés, amikor a felhasználói mikroszolgáltatás eltávolítja az érvénytelen fiókot, egy kompenzációs szakasz.

4.3. Bukási forgatókönyvek

Most vegyünk figyelembe néhány meghibásodási forgatókönyvet:

  • ha a érvényesítés a mikroszolgáltatás nem érhető el, akkor az üzenetküldő platform a tartós sorfunkcióival biztosítja, hogy a érvényesítés A microservice ezt az üzenetet később kapja meg
  • tegyük fel, hogy az üzenetküldő platform meghibásodik, akkor a felhasználó A microservice megpróbálja újra elküldeni az üzenetet később, például a még nem ellenőrzött felhasználók ütemezett kötegelt feldolgozásával
  • ha a érvényesítés A microservice megkapja az üzenetet, érvényesíti a felhasználót, de az üzenetküldő platform meghibásodása, a érvényesítés A mikroszolgáltatás később megkísérli az üzenet elküldését is
  • ha az egyik üzenet elveszett, vagy más hiba történt, akkor a felhasználó A mikroszolgáltatás ütemezett kötegelt feldolgozással megtalálja az összes nem érvényesített felhasználót, és újra elküldi az érvényesítés iránti kérelmeket

Még ha az üzenetek egy részét többször is kiadták, ez nem befolyásolja a mikroszolgáltatások adatbázisaiban lévő adatok konzisztenciáját.

Minden lehetséges meghibásodási forgatókönyv alapos megfontolásával biztosíthatjuk, hogy rendszerünk kielégítse az esetleges következetesség feltételeit. Ugyanakkor nem kellene foglalkoznunk a költséges elosztott tranzakciókkal.

De tisztában kell lennünk azzal, hogy az esetleges következetesség biztosítása összetett feladat. Nincs egyetlen megoldása minden esetre.

5. Következtetés

Ebben a cikkben megvitattuk a mikroszolgáltatások közötti tranzakciók végrehajtásának néhány mechanizmusát.

És megvizsgáltunk néhány alternatívát is ennek a tranzakcióstílusnak az elvégzéséhez.