Események a Spring Modulith-ban

Következő videóm témája, hogy egy modularizált alkalmazás felépítésekor az eseménykezelés segít nekünk abban, hogy a modulok lazán kapcsolódjanak egymáshoz. A Spring Modulith ezt kiegészíti, biztosabbá teszi a hiba- és tranzakciókezelést, valamint képes ezeket az eseményeket más service-ek felé is elküldeni valamilyen message brokeren keresztül.

Lesz szó modularizált alkalmazásról, eseménykezelésről, Spring Modulithról, tranzakciókezelésről, Testcontainersről, Kafkáról.

A példa alkalmazás forráskódja megtalálható a GitHubon.

A Spring Modulit modulkezeléséről írtam korábban egy posztot Modularizált alkalmazás fejlesztése a Spring Modulith-tal címmel.

A poszt végén a videóhoz képest extra tartalom is van.

OAuth 2.0 támogatás a Spring Boot 3.3-ban és a Pécs IT Meetup

A Spring Boot 3.3 verzióban tovább egyszerűsítették az OAuth 2.0 integrációt. Az előző verziók esetén, amennyiben a JWT tokenben a felhasználónév nem a sub claim alatt szerepelt, saját magunk kellett ezt kiolvasni, pl. egy saját JwtDecoder bean megadásával. Amennyiben a JWT token tartalmazta a szerepköröket is, saját JwtAuthenticationConverter beant kellett felvennünk, mely képes volt a szerepkörök kiolvasására.

Erre a Spring Boot 3.3 verziótól kezdve nincs szükség, hiszen beállíthatjuk ezt az application.properties állományban, és a Spring Boot automatikusan konfigurál egy JwtAuthenticationConverter (vagy reaktív esetben egy ReactiveJwtAuthenticationConverter beant).

Ezt is említettem a XV. Pécs IT Meetupon. A meghívást ezennel is köszönöm a Kovács Bálintnak, a meetup egyik szervezőjének, aki többedmagával a Webstar céget is képviselte.

XV. Pécs IT Meetup

Telemetria és a Java

Napjainkban a telemetria egy nagyon fejlődő terület, napról napra jelennek meg új eszközök és szabványok, melyeket igen nehéz nyomonkövetni. Ez a poszt ebben szeretne egy kis rendet tenni, hiszen úgy lehet valamit a legjobban megismerni, hogyha másoknak elmagyarázod.

A telemetria (telemetry) klasszikusan egy rendszer különböző elemein mérési adatok előállítása és továbbítása egy központi helyre. Ennek célja, hogy a múltbéli és jelenlegi adatok elemzésével meg lehessen bizonyosodni a rendszer helyes működéséről, észlelni, esetleg előre jelezni lehessen annak hibáit. Erre különböző eszközöket és folyamatokat használunk, melyek biztosítják a rendszer folyamatos megfigyelhetőségét (observability).

Szoftverrendszer esetén is pontosan erről van szó, különböző mérési adatokat állítunk elő különböző szinteken, pl. operációs rendszer szinten mérjük a CPU, memória és lemezhasználatot, de alkalmazás/szolgáltatás szinten mérhető a bejelentkezett felhasználók, beérkező kérések, tranzakciók száma, válaszidők. Ezen adatokból kinyert információkból következtethetünk a szoftver állapotára, hibára. A túl magas válaszidő biztos valami problémára utal, de az rossz jel lehet, ha hirtelen lecsökken a tranzakciószám.

AWS Lambda és a Spring Cloud Function

Az AWS Lambda egy AWS szolgáltatás, mely lehetővé teszi, hogy a különböző programozási nyelven megírt alkalmazásainkat (függvényeinket) anélkül tudjuk futtatni, hogy gondunk lenne az azt kiszolgáló infrastruktúrára. A szolgáltatás a serverless computing kategóriába tartozik, ami kicsit megtévesztő, hiszen itt is van futtató környezet, azonban ez számunkra láthatatlan. A másik ismert megnevezése a Function as a Service (FaaS). Természetesen más cloud szolgáltatóknak is van hasonló megoldásuk, a Microsoftnál az Azure Functions, a Google-nél a Cloud Functions.

A függvények tipikusan valamilyen beérkező eseményre reagálnak, ami lehet egy felhasználói kérés, valamilyen üzenet más szolgáltatás (pl. S3) felöl, vagy üzenet brókeren keresztül beérkező üzenet, pl. valamilyen IoT eszköz, vagy alkalmazás irányából. Miután megírjuk a választott programozási nyelven a függvényünket, azt össze kell csomagolni, és telepíteni. Ez lehet akár egy tömörített fájl, akár egy container image. A szolgáltatás rugalmassága miatt ma akár bármilyen programozási nyelven írhatunk ilyen függvényeket.

A futtatókörnyezettel nem kell foglalkozni, azt a szolgáltatás önmaga kezeli. Ez magában foglalja a hardvert és az operációs rendszert, annak frissítését, erőforrás kezelést, automatikus skálázást és naplózást. És fizetnünk is csak annyit kell, amennyit futott a függvényünk, idő alapján (ezredmásodperc alapon).

A kód futtatása természetesen konténerekben történik, melyek tartalmazzák az adott programozási nyelv futtatókörnyezetét. Azonban a szolgáltatás nem mindig indít minden bejövő eseményhez új konténert, hanem megpróbálja azokat újrahasznosítani. Ennek egyik következménye, hogy bizonyos kérések kiszolgálása tovább tart, mikor a konténert el kell indítani (ún. cold start). Bizonyos kérések kiszolgálása azonban nagyon gyorsan megtörténik (ún. warm start). A nem használt konténereket a szolgáltatás automatikusan leállítja. Másrészt mivel a kérések kiszolgálása ugyanabban a konténerben futhat, lehet ezeknek egymásra hatása (pl. ha használják a fájlrendszert).

Egy AWS Lambda konténer rendelkezésére álló memória konfigurálható 128 és 10240 MB között, természetesen egy ezredmásodperc ára is annál nagyobb, minél több memóriát használ a konténer. Valamint 512 MB és 10240 MB között tudunk hozzá tárhelyet is rendelni, minél többet, annál nagyobb felárral.

Amennyiben saját image-t állítunk elő, először a Amazon Elastic Container Registry (Amazon ECR) szolgáltatásba kell feltöltenünk.

Ha a Lambda függvényünket REST-en akarjuk meghívni, akkor még az API Gateway szolgáltatást kell használnunk.

Architektúra

Ezek alapján mikor érdemes az AWS Lambdát használni? Olyan funkciók megvalósítására ideális, amik eseményekre reagálnak, nincs rá folyamatosan szükségünk, nem kell azonnali választ adnunk, és az üzenetek beérkezése nem egyenletes. Ilyen lehet pl. a kép- és videófeldolgozás, bejövő események adatainak aggregálása, (PDF) dokumentumok generálása.

Vannak azonban esetek, amelyeknél el kell gondolkodnunk, hogy tényleg az AWS Lambda-e a jó választás. Ilyenek például a klasszikus webes alkalmazások. Itt egy gyenge forgalom esetén lehet, hogy a cold start miatt nagyobb lesz a válaszidő. Valamint egy nagyon nagy terhelésű alkalmazás esetén pedig lehet, hogy az idő alapú számlázás nem a legkedvezőbb.

A Spring Cloud Function egy olyan projekt, mely a Spring ökoszisztéma tagja, Spring Boothoz illeszkedik, és segítségével az üzleti logikát Java 8 funkcionális interfészek implementálásával tudjuk megvalósítani. Ezáltal teljesen leválasztja az infrastruktúrális elemekről. Azonban adapterekkel, konfigurációt használva össze tudjuk kapcsolni az üzleti logikát különböző szolgáltatásokkal, pl. AWS Lambdaval is. A Spring Cloud Stream használatával pedig különböző message brokerrekkel, mint pl. RabbitMQ-val vagy Apache Kafkával.

Mivel nem mindegy, hogy a function mennyi memóriát használ, és mennyi idő alatt indul el, ezért a Java bytekód nem feltétlenül a legjobb választás. Azonban a Spring Boot alkalmazásokat könnyű natívvá fordítani.

Ebben a posztban azt mutatom be, hogyan lehet egy natívra fordított, Spring Cloud Functiont használó alkalmazást AWS Lambda függvényként futtatni.

(A példa ingyenesen kipróbálható az AWS Free Tier használatával. Bankkártya adatok megadása szükséges.)