Modulárny webový systém pre Katedru informatiky
Microservices platforma, ktorá spája nezávisle vyvíjané moduly do jedného katedrového portálu - od architektúry a integrácie cez automatizované nasadzovanie až po monitoring v produkcii.
Microservices platforma, ktorá spája nezávisle vyvíjané moduly do jedného katedrového portálu - od architektúry a integrácie cez automatizované nasadzovanie až po monitoring v produkcii.
Existujúci portál Katedry informatiky bol roky iba statickou vizitkou - bez prihlásenia, bez správy obsahu, bez možnosti rozšírenia. Cieľom nebola len výmena vizuálu, ale postaviť platformu, ktorú možno rozširovať o nové moduly bez zásahu do jadra.
Nová funkčnosť vzniká ako samostatný modul. Každý modul je nezávislý - jeho pridanie či úprava sa nedotkne ostatných modulov ani jadra systému.
Prihlasovanie cez univerzitné účty Microsoft Entra ID aj lokálne pozvánkové účty zabezpečuje jadro systému. Ostatné moduly tak autentifikáciu ani roly neriešia, len ich využívajú.
Projekt vznikol v rámci projektovej výučby a slúži ako základ, na ktorom môžu študenti v ďalších semestroch stavať vlastné rozširujúce moduly.
Práca sa delí na dve oblasti: integrácia rieši, ako moduly spolupracujú, a orchestrácia, ako sa automatizovane dostanú na produkciu.
Návrh microservices architektúry a implementácia kľúčových modulov tak, aby boli technologicky nezávislé, no spoľahlivo spolupracovali - so spoločným prihlásením, dátami a udalosťami.
Kontajnerizácia a CI/CD pipelines, ktoré automatizujú build, testy, doručenie na produkčné prostredia a sledovanie systému v reálnom čase.
V rámci práce sú implementované tri moduly - správa používateľov, obsah katedrového portálu a študijné materiály. Dopĺňa ich zdieľaný servis, ktorý prináša sémantické vyhľadávanie naprieč celým systémom.
Jednotné prihlásenie a správa používateľov
Prihlásenie cez univerzitné účty (Microsoft Entra ID) aj lokálne účty na pozvánku. Správa používateľov a ich globálnych aj modulových rolí vrátane verejných profilov.
Obsah katedrového portálu
Aktuality s WYSIWYG editorom a podporou vyhľadávania, zoznam pracovníkov katedry synchronizovaný z LDAP, predmety a výskumné projekty.
Študijné materiály
Študijné materiály k predmetom usporiadané do kapitol. Ukazuje, ako sa do systému pridávajú nové rozširujúce moduly.
Používateľ nemusí poznať presné slová - stačí opísať, čo hľadá, a systém nájde obsah, ktorý zodpovedá významu jeho dotazu. V pozadí servis vytvára vektorové reprezentácie obsahu (embeddingy) cez lokálny ONNX model a ukladá ich do Qdrant DB. Takto ho využíva portál aj študijné materiály.
Pohľad na jednotlivé komponenty a ich vzťahy v rámci systému
Modulárny systém pozostáva z webového klienta, štyroch servisov, vlastných databáz a infraštruktúry pre messaging a observability. Servisy sú nasadené ako kontajnery cez Docker Compose.
Jednotné používateľské rozhranie postavené v Angulari. So všetkými modulmi komunikuje cez Nginx API gateway, ktorý smeruje požiadavky na príslušné servisy - klient tak vystupuje ako jeden portál.
IdentityService vydáva JWT tokeny podpísané RSA asymetrickou kryptografiou, spravuje globálne a modulové roly a publikuje udalosti o používateľoch cez Event Bus. Prepája systém s Microsoft Entra ID a FRI LDAP.
PortalService spravuje aktuality, zamestnancov, predmety a výskumné projekty. Cez Event Bus si udržiava shadow tabuľku používateľov a synchronizuje pracovníkov z FRI LDAP.
Rozširujúci modul pre študijné materiály usporiadané do kapitol. Ukazuje, ako sa do systému pridávajú nové moduly - bez zásahu do jadra a ostatných modulov.
Univerzálny servis pre generovanie embeddingov a sémantické vyhľadávanie - využíva lokálny ONNX model a Qdrant vektorovú databázu. Portal aj Courses ho používajú synchrónne cez gRPC pri vyhľadávaní v aktualitách a študijných materiáloch.
RabbitMQ Management UI a Grafana Observability stack (Grafana + Loki + Tempo). Slúžia administrátorom na monitoring a vývojárom na diagnostiku - prístupné iba cez UNIZA VPN.
Dve vlastné knižnice používané naprieč .NET servismi systému.
Publikované cez GitHub Packages.
Vlastná implementácia mediator patternu - oddeľuje API vrstvu od biznis logiky cez IMediator.SendAsync(). Vznikla ako náhrada za MediatR po zmene jeho licencie.
// Controller - IMediator cez DI (primary ctor) public class ArticlesController(IMediator mediator) : ControllerBase { [HttpGet("{slug}")] public async Task<IActionResult> Get(string slug) { var article = await mediator.SendAsync( new GetArticleQuery(slug)); return Ok(article); } }
// Request + handler (.Business projekt) public record GetArticleQuery(string Slug) : IRequest<ArticleDto>; public class GetArticleHandler(AppDbContext db) : IRequestHandler<GetArticleQuery, ArticleDto> { public Task<ArticleDto> HandleAsync( GetArticleQuery q, CancellationToken ct) { // načítanie článku + mapovanie na ArticleDto } }
// Program.cs // AddMediator nájde a zaregistruje všetky // IRequest + IRequestHandler v danom assembly builder.Services.AddMediator( typeof(GetArticleQuery).Assembly);
Abstrakcia nad RabbitMQ - jeden servis udalosti publikuje, iné ich konzumujú, pričom o detaily komunikácie s message brokerom sa stará knižnica. Servisy tak medzi sebou komunikujú asynchrónne.
// IdentityService - IEventBus cez DI public class AuthService(IEventBus eventBus) { public async Task Register(UserProfile user) { // ... uloženie používateľa await eventBus.Publish( new UserRegisteredEvent(user)); } }
// Event + consumer (PortalService) [Exchange(prefix: "IdentityService")] public record UserRegisteredEvent(UserProfile User); public class UserRegisteredConsumer(AppDbContext db) : IConsumer<UserRegisteredEvent> { public Task Consume(UserRegisteredEvent msg) { // synchronizácia shadow tabuľky } }
// Program.cs // AddEventBus pripojí RabbitMQ a auto-registruje // všetky IConsumer<T> v danom assembly builder.Services.AddEventBus( typeof(UserRegisteredConsumer).Assembly);
Hotový systém je potrebné po vývoji spoľahlivo doručiť na produkčné prostredie pre koncových používateľov a následne monitorovať prevádzku, aby sa včas zachytili prípadné chyby. Druhá oblasť práce automatizuje tieto fázy - od zmien v kóde až po upozornenia o chybách.
Systém je rozdelený do repozitárov podľa modulov, sústredených v jednej privátnej GitHub organizácii - celý tím tak má na jednom mieste prehľad o všetkých častiach systému a o ich existencii. Každý repozitár má vlastné CI/CD pipeliny, citlivé údaje sú vďaka GitHub Secrets držané mimo kódu a vlastné knižnice sa publikujú do privátneho NuGet feedu cez GitHub Packages.
WebClient, IdentityService, PortalService a infraštruktúra - RabbitMQ a Grafana stack. Servisy jadra sa nasadzujú spolu.
CoursesService - modul študijných materiálov. Demonštruje, ako sa systém rozšíri o nezávisle nasaditeľný modul.
VectorIndexerService - interný gRPC servis pre sémantické vyhľadávanie (embedding cez ONNX + Qdrant). Nepatrí žiadnemu modulu.
NuGet balík MIS.Mediator - in-process CQRS mediator. Publikovaný do GitHub Packages.
NuGet balík MIS.EventBus - abstrakcia nad RabbitMQ. Publikovaný do GitHub Packages.
Kostra pre tvorbu nových modulov - pripravená štruktúra, konfigurácia a pipeliny na štart.
Interná technická dokumentácia pre celý vývojový tím - architektúra, onboarding nových členov, konvencie a postupy pri integrácii modulov.
Vlastná GitHub Action - počas nasadzovania nahradí placeholdery v .env reálnymi hodnotami zo Secrets.
Štyri typy GitHub Actions workflows automatizujú validáciu zmien, nasadzovanie do produkcie, databázové migrácie a publikovanie nových verzií vlastných knižníc.
.nupkgManuálne spustenie cez GitHub UI rozbehne štyri na seba nadväzujúce joby. Build (ci) aj deploy (cd) sú vyčlenené do znova použiteľných workflowov, takže sa dajú spustiť aj samostatne.
vYY.MM.DD.Ndocker compose build.env (replace-tokens-action).env na serverdocker compose up/healthBeží na self-hosted runneri - build aj deploy na tom istom serveri.
Každý servis posiela logy a distribuované traces cez OpenTelemetry do centrálneho monitorovacieho systému. Detail tracu ukáže, ktorými servismi požiadavka prešla. Vďaka korelácii cez Trace ID sa k danému tracu zobrazia len súvisiace logy.
Jedna požiadavka, jeden Trace ID - naprieč všetkými servismi.
V Grafana dashboarde stačí kliknúť na požiadavku zo zoznamu tracov a zobrazí sa jej timeline so spanmi aj všetky súvisiace logy skorelované podľa Trace ID. To výrazne uľahčuje hľadanie príčin chýb v distribuovanom systéme.
Pri error logu Grafana automaticky upozorní administrátorov. Cez Power Automate webhook príde do Teamsu notifikácia so zoznamom chýb a tlačidlom priamo na trace v Grafane.
Vybrané ukážky funkcií nasadeného systému, zoskupené podľa modulov.
Ukážky zachytávajú stav systému v čase obhajoby práce.
Software Engineer
Som absolvent Fakulty riadenia a informatiky na Žilinskej univerzite v Žiline, kde som obhájil diplomovú prácu na tému Modulárny webový systém - integrácia a orchestrácia modulov.
Vďaka nej som získal cenné skúsenosti nielen s vývojom, ale najmä so system designom a architektonickými rozhodnutiami na úrovni celého systému - od návrhu microservices architektúry cez automatizovaný deployment až po monitoring a alerting v produkcii. Tento pohľad na softvér ako celok ma baví a motivuje posúvať sa ďalej.
V minulosti som obhájil aj bakalársku prácu na tému Webová časť systému First Responder.