Megosztás a következőn keresztül:


Mikroszolgáltatások (integrációs események) közötti eseményalapú kommunikáció megvalósítása

Tipp.

Ez a tartalom egy részlet a .NET-alkalmazásokhoz készült .NET-alkalmazásokhoz készült eBook, .NET Microservices Architecture című eBookból, amely elérhető a .NET Docs-on vagy egy ingyenesen letölthető PDF-fájlként, amely offline módban is olvasható.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

A korábban leírtak szerint az eseményalapú kommunikáció használatakor egy mikroszolgáltatás közzétesz egy eseményt, amikor valami jelentős esemény történik, például amikor frissíti az üzleti entitást. Más mikroszolgáltatások feliratkoznak ezekre az eseményekre. Amikor egy mikroszolgáltatás eseményt kap, frissítheti saját üzleti entitásait, ami további események közzétételéhez vezethet. Ez a végleges konzisztencia koncepció lényege. Ezt a közzétételi/előfizetési rendszert általában egy eseménybusz implementálásával hajtják végre. Az eseménybusz úgy tervezhető, hogy interfészként szolgáljon az API-val, amely az eseményekre való feliratkozáshoz és leiratkozáshoz, valamint az események közzétételéhez szükséges. Egy vagy több implementációval is rendelkezhet, amely bármilyen folyamatközi vagy üzenetküldési kommunikáción alapul, például üzenetsoron vagy az aszinkron kommunikációt támogató service buson, valamint egy közzétételi/előfizetési modellen.

Események használatával több szolgáltatásra kiterjedő üzleti tranzakciókat valósíthat meg, amelyek végső konzisztenciát biztosítanak a szolgáltatások között. Egy végül konzisztens tranzakció elosztott műveletek sorozatából áll. A mikroszolgáltatás minden műveletnél frissíti az üzleti entitást, és közzétesz egy eseményt, amely elindítja a következő műveletet. Vegye figyelembe, hogy a tranzakció nem terjed ki az alapul szolgáló adatmegőrzésre és eseménybuszra, ezért az idempotenciát kezelni kell. Az alábbi 6–18. ábra egy eseménybuszon keresztül közzétett PriceUpdated eseményt jelenít meg, így az árfrissítést a kosárba és más mikroszolgáltatásokba propagálja a rendszer.

Diagram of asynchronous event-driven communication with an event bus.

6–18. ábra. Eseményvezérelt kommunikáció eseménybuszon alapuló

Ez a szakasz azt ismerteti, hogyan valósítható meg ez a fajta kommunikáció a .NET-tel egy általános eseménybusz-interfész használatával, ahogyan az a 6–18. ábrán látható. Több lehetséges implementáció létezik, amelyek mindegyike más technológiát vagy infrastruktúrát használ, például a RabbitMQ-t, az Azure Service Bust vagy bármely más külső nyílt forráskódú vagy kereskedelmi szolgáltatásbuszt.

Üzenetközvetítők és szolgáltatásbuszok használata éles rendszerekhez

Az architektúra szakaszban leírtak szerint több üzenetkezelési technológia közül választhat az absztrakt eseménybusz implementálására. Ezek a technológiák azonban különböző szinteken vannak. A RabbitMQ például egy üzenettovábbító átvitele alacsonyabb szinten van, mint az olyan kereskedelmi termékek, mint az Azure Service Bus, az NServiceBus, a MassTransit vagy a Brighter. Ezeknek a termékeknek a többsége a RabbitMQ vagy az Azure Service Bus használatával is használható. A termék kiválasztása attól függ, hogy hány funkcióra és mennyi beépített méretezhetőségre van szüksége az alkalmazáshoz.

Ahhoz, hogy csak egy event bus proof-of-concept for your fejlesztői környezet, mint az eShopOnContainers minta, egy egyszerű implementáció tetején RabbitMQ futó tároló lehet elég. A kritikus fontosságú és a nagy méretezhetőséget igénylő éles rendszerek esetében azonban érdemes lehet kiértékelni és használni az Azure Service Bust.

Ha magas szintű absztrakciókra és gazdagabb funkciókra van szüksége, mint például a Sagas a hosszú ideig futó folyamatokhoz, amelyek megkönnyítik az elosztott fejlesztést, más kereskedelmi és nyílt forráskódú szolgáltatásbuszokat, például az NServiceBust, a MassTransitet és a Brightert érdemes kiértékelni. Ebben az esetben a használni kívánt absztrakciók és API-k általában közvetlenül azok, amelyeket ezek a magas szintű szolgáltatási buszok biztosítanak saját absztrakciók helyett (például az eShopOnContainers egyszerű eseménybusz absztrakciói). Ebben az esetben az elágazott eShopOnContainereket az NServiceBus használatával (az adott szoftver által implementált további származtatott mintával) lehet keresni.

Természetesen mindig létrehozhat saját service bus-funkciókat az alacsonyabb szintű technológiákra, például a RabbitMQ-ra és a Dockerre, de a "kerék újra feltalálásához" szükséges munka túl költséges lehet egy egyéni vállalati alkalmazáshoz.

Megismétlendő: az eShopOnContainers mintában bemutatott eseménybusz-absztrakciók és megvalósítási minta csak a koncepció bizonyítékaként használható. Miután úgy döntött, hogy aszinkron és eseményvezérelt kommunikációt szeretne, ahogyan az a jelenlegi szakaszban is szerepel, válassza ki azt a service bus terméket, amely a legjobban megfelel az éles környezet igényeinek.

Integrációs események

Az integrációs események a tartományállapot szinkronizálására szolgálnak több mikroszolgáltatásban vagy külső rendszerben. Ez a funkció a mikroszolgáltatáson kívüli integrációs események közzétételével érhető el. Ha egy eseményt több fogadó mikroszolgáltatásban tesznek közzé (annyi mikroszolgáltatásra, amennyit előfizetnek az integrációs eseményre), az eseményt az egyes fogadó mikroszolgáltatások megfelelő eseménykezelője kezeli.

Az integrációs esemény alapvetően adattartó osztály, ahogyan az alábbi példában is látható:

public class ProductPriceChangedIntegrationEvent : IntegrationEvent
{
    public int ProductId { get; private set; }
    public decimal NewPrice { get; private set; }
    public decimal OldPrice { get; private set; }

    public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice,
        decimal oldPrice)
    {
        ProductId = productId;
        NewPrice = newPrice;
        OldPrice = oldPrice;
    }
}

Az integrációs események az egyes mikroszolgáltatások alkalmazásszintjén határozhatók meg, így leválaszthatók más mikroszolgáltatásokról, a ViewModels kiszolgálón és ügyfélben való definiálásának módjához hasonló módon. Nem ajánlott közös integrációs események tárának megosztása több mikroszolgáltatásban; ez egyetlen eseménydefiníciós adattárral kapcsolná össze ezeket a mikroszolgáltatásokat. Ezt nem szeretné megtenni ugyanazért az okból, hogy nem szeretne közös tartománymodellt megosztani több mikroszolgáltatás között: a mikroszolgáltatásoknak teljesen autonómnak kell lenniük. További információkért tekintse meg ezt a blogbejegyzést az eseményekbe helyezendő adatok mennyiségéről. Ügyeljen arra, hogy ezt ne vegye túl messzire, mivel ez a másik blogbejegyzés leírja , hogy milyen problémákat okozhatnak az adathiányos üzenetek. Az események tervezésekor arra kell törekednie, hogy a fogyasztók igényeinek megfelelően legyen "helyes".

Csak néhányféle kódtárat kell megosztania a mikroszolgáltatások között. Az egyik olyan kódtárak, amelyek végső alkalmazásblokkok, például az Event Bus-ügyfél API, mint az eShopOnContainersben. A másik olyan kódtárak, amelyek olyan eszközöket alkotnak, amelyek NuGet-összetevőkként is megoszthatók, például JSON szerializálókként.

Az eseménybusz

Az eseménybuszok lehetővé teszik a mikroszolgáltatások közötti közzétételi/előfizetési típusú kommunikációt anélkül, hogy az összetevőknek explicit módon tisztában kellene lenniük egymással a 6–19. ábrán látható módon.

A diagram showing the basic publish/subscribe pattern.

6–19. ábra. Alapismeretek közzététele/előfizetése eseménybusz használatával

A fenti ábrán az látható, hogy az A mikroszolgáltatás az Event Busban tesz közzé, amely a B és C mikroszolgáltatások előfizetésére osztja el az előfizetőket anélkül, hogy a közzétevőnek ismernie kellene az előfizetőket. Az eseménybusz a Megfigyelő mintához és a közzétételi-feliratkozási mintához kapcsolódik.

Megfigyelői minta

A Megfigyelő mintában az elsődleges objektum (más néven Megfigyelhető) értesíti a többi érdekelt objektumot (más néven Megfigyelőket) a releváns információkkal (eseményekkel).

Publish/Subscribe (Pub/Sub) minta

A közzétételi/előfizetési minta célja megegyezik a Megfigyelő mintával: bizonyos események esetén értesíteni szeretne más szolgáltatásokat. De van egy fontos különbség a Megfigyelő és a Pub/Sub minták között. A megfigyelői mintában a közvetítés közvetlenül a megfigyeltektől a megfigyelőkig történik, így "ismerik" egymást. Pub/Al minta használata esetén azonban létezik egy harmadik összetevő, az úgynevezett közvetítő, az üzenetközvetítő vagy az eseménybusz, amelyet a közzétevő és az előfizető is ismer. Ezért a Pub/Al minta használata esetén a közzétevő és az előfizetők pontosan el vannak választva az említett eseménybusznak vagy üzenetközvetítőnek köszönhetően.

A közvetítő vagy eseménybusz

Hogyan érheti el az anonimitást a közzétevő és az előfizető között? Egy egyszerű módja annak, hogy egy közvetítő gondoskodik az összes kommunikációt. Az eseménybusz egy ilyen közvetítő.

Az eseménybusz általában két részből áll:

  • Az absztrakció vagy a felület.

  • Egy vagy több implementáció.

A 6–19. ábrán látható, hogy alkalmazás szempontjából az eseménybusz nem más, mint pub/alcsatorna. Az aszinkron kommunikáció megvalósítása eltérő lehet. Több implementációval is rendelkezhet, így a környezeti követelményektől függően (például az éles környezet és a fejlesztési környezetek) válthat közöttük.

A 6–20. ábrán egy olyan eseménybusz absztrakciója látható, amely több implementációval rendelkezik infrastruktúra-üzenetkezelési technológiákon, például a RabbitMQ-on, az Azure Service Buson vagy egy másik esemény-/üzenetközvetítőn.

Diagram showing the addition of an event bus abstraction layer.

6–20. ábra. Eseménybusz több implementációja

Jó, ha az eseménybuszt egy interfészen keresztül definiáljuk, hogy több technológiával is implementálható legyen, például a RabbitMQ-val, az Azure Service Bus-tal vagy másokkal. Azonban, és ahogy korábban említettük, a saját absztrakciók (az event bus interfész) használata csak akkor jó, ha az absztrakciók által támogatott alapvető eseménybusz-funkciókra van szüksége. Ha gazdagabb service bus-funkciókra van szüksége, a saját absztrakciói helyett valószínűleg az előnyben részesített kereskedelmi szolgáltatásbusz által biztosított API-t és absztrakciókat kell használnia.

Eseménybusz-interfész definiálása

Kezdjük néhány implementációs kóddal az event bus interfészhez és a lehetséges implementációkhoz feltárási célokra. Az interfésznek általánosnak és egyszerűnek kell lennie, mint az alábbi felületen.

public interface IEventBus
{
    void Publish(IntegrationEvent @event);

    void Subscribe<T, TH>()
        where T : IntegrationEvent
        where TH : IIntegrationEventHandler<T>;

    void SubscribeDynamic<TH>(string eventName)
        where TH : IDynamicIntegrationEventHandler;

    void UnsubscribeDynamic<TH>(string eventName)
        where TH : IDynamicIntegrationEventHandler;

    void Unsubscribe<T, TH>()
        where TH : IIntegrationEventHandler<T>
        where T : IntegrationEvent;
}

A Publish módszer egyszerű. Az eseménybusz az adott eseményre előfizetett bármely mikroszolgáltatásnak vagy akár egy külső alkalmazásnak is közvetíti a neki átadott integrációs eseményt. Ezt a módszert az eseményt közzétevő mikroszolgáltatás használja.

A Subscribe metódusokat (az argumentumoktól függően több implementációval is rendelkezhet) az eseményeket fogadni kívánt mikroszolgáltatások használják. Ennek a metódusnak két argumentuma van. Az első az integrációs esemény, amelyre elő kell fizetnie (IntegrationEvent). A második argumentum az integrációs eseménykezelő (vagy visszahívási módszer), IIntegrationEventHandler<T>amelyet akkor kell végrehajtani, amikor a fogadó mikroszolgáltatás megkapja az integrációs eseményüzenetet.

További erőforrások

Néhány éles használatra kész üzenetkezelési megoldás: