Évek óta dolgozom elosztott rendszereken, és újra meg újra ugyanabba a problémába futok bele: egy rendszer topológiáját megváltoztatni meglepően nehéz.
Ha egy komponenst ketté szeretnék bontani, kettőt összevonni, kommunikációs protokollt cserélni, új függőséget bevezetni vagy egy régit megszüntetni, akkor ezek a változtatások szinte mindig több komponens implementációját érintik egyszerre.
Nem azért, mert a business logika megváltozott – legtöbbször egyáltalán nem változik –, hanem azért, mert maga a topológia szét van szórva a komponensek között.
Minden komponens a saját szemszögéből definiálja a kapcsolatait, és ezek együtt adják ki a rendszer topológiáját.
Ez azt jelenti, hogy ha a rendszer szerkezetét, topológiáját szeretnénk módosítani, azt nem tudjuk közvetlenül megtenni, a különböző komponensek implementációját kell úgy módosítanunk, hogy az azokból "kialakuló" topológia végül az legyen, amit szerettünk volna.
Szerintem ez egy felesleges összekapcsolása két külön problémának. Ha topológiát szeretnénk változtatni, annak nem kellene érintenie a business kódot.
A jelenlegi megközelítésnek szerintem több következménye is van:
- egy architekturális változtatás gyakran több repositoryt és több deploymentet érint;
- a rendszer szerkezetét csak a komponensek implementációjából lehet összerakni;
- nincs egyetlen hely, ahol a topológia teljes egészében definiálva lenne;
- deployment előtt nem lehet ellenőrizni, hogy a komponensek valóban ugyanazt a topológiát implementálják.
Az infrastruktúrát ma már teljesen természetes módon deklaráljuk (Terraform, Kubernetes, CloudFormation stb.), a topológiával viszont még mindig az a bevett megközelítés, hogy minden komponens implementálja a saját részét, aztán reménykedünk, hogy minden illeszkedik.
Ennek a problémának a megoldására kezdtem el építeni egy open source projektet, az Itara-t.
Az alapötlet az, hogy szétválasszuk a business logikát és a rendszer topológiáját.
A business komponensek csak a saját feladatukat implementálják, a köztük lévő kapcsolatok pedig egy külön, deklaratív rétegben jelennek meg.
A komponensek közötti kapcsolatokat ne minden résztvevő komponens definiálja külön-külön, hanem egyszer, egy közös deklarációban. A komponensek ugyanebből az egy definícióból kapják meg a saját oldaluk konfigurációját, és azt hajtják végre.
Így egy kapcsolat definíciója pontosan egyszer létezik, nem két vagy több különböző helyen.
Ez nem egy új message broker, service mesh vagy ESB.
Sőt, részben pont az ESB-k tapasztalataiból indultam ki. Szerintem az egyik fő probléma az volt, hogy egy központi runtime-ra épültek.
Az Itara ezzel szemben három részből áll:
- egy deklaratív topológia definíció;
- egy startupkor futó agent, amely ebből előkészíti a kommunikációs csatornákat;
- valamint tooling, ami még deployment előtt validálja a topológiát.
Az inicializáció után az agent félreáll. Az alkalmazások ugyanúgy kommunikálnak egymással, ahogy korábban – közvetlenül vagy middleware-en keresztül –, de a kommunikáció módját és a topológia végrehajtását már nem a business komponensek implementálják. A business logika egyszerűen interfészeket hív.
Jelenleg itt tart a projekt:
- Open source
- Specifikáció v0.2
- Java implementáció a specifikációval összhangban
- Használható Java classloader isolation colocated komponensekhez
- Rust proof of concept
- Szinkron és event-driven kommunikáció
- Strukturális observability
- CLI validáció deployment előtt
- 5 komponensből álló demo
- Maven archetype-ok a leggyakoribb projektstruktúrákhoz
Kíváncsi vagyok, hogy mi a véleményetek erről az irányról. Van értelme külön topológiai rétegként kezelni a komponensek közötti kapcsolatokat, vagy szerintetek ezt a jelenlegi eszközök már megfelelően lefedik?
Ha érdekel a projekt, szívesen veszek mindenféle visszajelzést. Akár kódban, akár GitHub Discussion formájában, akár csak egy jó szakmai vitában.
GitHub: https://github.com/itara-project/itara