Când arhitectura bazată pe microservicii a devenit populară, vechile proiecte au început să fie treptat migrate sau rescrise ca microservicii. De asemenea, majoritatea noilor proiecte au fost construite în jurul microserviciilor. Dat fiind că în ultimul timp, se poate observa o reîntoarcere la arhitectura monolitică, dorim să explicăm cauza, efectele, avantajele și dezavantajele acestei tranziții.
Mai întâi, trebuie definite arhitectura monolitică și cea bazată pe microservicii:
Arhitectura monolitică este o bază de cod singulară, unificată ce include toate funcționalitățile unei aplicații.
Putem observa un tipar când vorbim de adopția de noi tehnologii și tehnici unde se învață un nou instrument, să zicem un ciocan, astfel încât subit toate problemele încep să semene cu niște cuie. Când microserviciile au început să se dezvolte acum un deceniu, pentru mulți, microserviciile au reprezentat soluția la toate problemele. Așa cum s-a putut observa, în unele cazuri, microserviciile doar au creat multiple alte probleme.
Avantaje:
Ușor de dezvoltat, testat, instalat și depanat (debugged).
Dezavantaje:
Probleme de scalabilitate.
Dificultăți în implementarea livrării continue.
Avantaje:
Principiul responsabilității unice.
Fiecare serviciu poate fi dezvoltat, instalat și scalat independent.
Dezavantaje:
Complexitate crescută la nivel de dezvoltare, testare și instalare.
Latență crescută pe rețea și comunicare întârziată.
Uneori, adevărul este undeva la mijloc și nu putem declara cert că o abordare este superioară alteia, deoarece ambele au avantaje și dezavantaje. Trebuie să evaluăm fiecare proiect de la caz la caz și să decidem care arhitectură este mai potrivită.
În ultimii ani, s-a putut observa o modificare în tendințe, astfel încât unele organizații au reconsiderat arhitecturile monolitice sau abordările hibride.
Motive pentru schimbare:
Complexitate operațională: Microserviciile introduc un volum operațional semnificativ, ceea ce necesită orchestrare complexă, monitorizare și depanare (debugging).
Costuri: Mentenanța mai multor servicii aduce costuri suplimentare în ceea ce privește infrastructura și resursele umane.
Productivitatea programatorilor: Programatorii pot avea productivitate mai mare în cadrul unei baze de cod unificate.
Arhitectura modulară monolitică păstrează simplitatea monoliților, dar încorporează modularitatea necesară pentru gestionarea complexității.
Un monolit modular include module slab cuplate. Modulele reprezintă seturi de funcționalități coezive. Modulele sunt, de asemenea, independente unele față de altele.
Monoliții modulari au multe beneficii:
Instalare simplificată. Spre deosebire de microservicii care necesită strategii complexe de instalare, un monolit modular poate fi instalat ca unitate singulară.
Performanță îmbunătățită. Comunicarea între module are loc în timpul proceselor. Prin urmare, nu există latență de rețea sau volum mărit generat de serializarea și deserializarea datelor.
Viteză mărită de dezvoltare. Se gestionează o singură bază de cod, ceea ce simplifică depanarea și întreaga experiență de dezvoltare.
Management facil de tranzacții. Gestionarea tranzacțiilor într-un sistem distribuit reprezintă o provocare. Monoliții modulari simplifică acest aspect, din moment ce modulele pot partaja aceeași bază de date.
Complexitate operațională redusă. Monoliții modulari reduc complexitatea operațională care apare în contextul gestiunii și instalării unui sistem distribuit de microservicii.
Cea mai mare diferență între monoliții modulari și microservicii o reprezintă strategia de instalare. Microserviciile elevează limitele logice din cadrul unui monolit modular la rangul de limite fizice.
Microserviciile oferă o strategie clară pentru modularitate și pentru descompunerea contextelor auto-limitate. Se poate obține acest obiectiv și fără a construi un sistem distribuit. Problema este că programatorii folosesc microserviciile pentru a implementa limita până la care funcționează o bucată de cod.
În schimb, ați putea construi un monolit modular pentru a obține aceleași beneficii. Monoliții modulari oferă coeziune înaltă, cuplare slabă, încapsulare de date, accent pe funcționalitățile de business și nu numai.
Microserviciile oferă toate aceste beneficii, dar, suplimentar, oferă instalări independente, scalabilitate independentă și posibilitatea de a folosi tehnologii diferite per serviciu.
"Alegeți microserviciile pentru beneficii, nu pentru că baza de cod monolitică este un dezastru." - Simon Brown
Primul și cel mai ușor tipar de comunicare este cel realizat prin method calls (apelare de metode) între module. Method calls sunt sincrone și foarte rapide, deoarece acestea au loc in memory (în memorie).
Modulul A apelează o metodă declarată în API-ul public al Modulului B și așteaptă să primească un rezultat.
Fiecare modul expune un API public ce poate funcționa precum o interfață.
Modulele depind de interfață la compilare. La runtime, dependency injection (injecția de depedințe) oferă baza respectivei implementări.
Beneficiile acestei abordări sunt:
Viteza apelărilor in-memory;
Implementarea facilă;
Dezavantajul acestei abordări îl reprezintă cuplarea puternică: Comunicarea sincronă presupune că modulele vor fi puternic cuplate. Dacă unul din aceste module este indisponibil, modulele dependente vor fi afectate. Puteți introduce un mecanism de retry (reîncercare), dar nu veți ajunge departe.
Al doilea tipar de comunicare este mesageria asincronă între module.
Modulul A trimite un mesaj unui broker de mesaje în manieră fire-and-forget. Modulul B se abonează la mesajele relevante și le gestionează corespunzător.
Modulele nu trebuie să fie conștiente unele de altele, dar trebuie să cunoască contractele mesajelor. În scenariul nostru, contractul este API-ul public al unui modul.
Beneficiile acestei abordări sunt:
Disponibilitatea crescută;
Comunicarea asincronă oferă cuplare slabă, deoarece modulele comunică folosind mesaje. Modulul B nu trebuie să fie disponibil pentru ca Modulul A să trimită un mesaj.
Dezavantajul evident al acestei abordări este complexitatea crescută.
Alegerea corectă a arhitecturii pentru organizația voastră ține de echilibru. Puteți implementa principiul separării obiectivelor de lucru și să scalați API-uri diferite, folosind o arhitectură monolitică modulară, bucurându-vă în același timp de unele din beneficiile microserviciilor.
Pentru a decide dacă este benefic să treceți la o arhitectură monolitică ori să reparați problemele în cadrul unui monolit distribuit, luați în calcul compromisurile și timpul avut la dispoziție. Analizați efortul necesar și productivitatea deficitară ce derivă din utilizarea microserviciilor în timp, iar apoi comparați aceste aspecte cu costurile migrării la un monolit. De asemenea, luați în calcul factori precum mărimea echipei, expertiza disponibilă și structura organizațională.
Înainte de a tranziționa spre o arhitectură monolitică, să aveți în vedere următoarele aspecte:
Evaluați dacă un monolit se potrivește cel mai bine cu mărimea echipei voastre, cu structura acesteia, cu competențele sale și cu capacitatea operațională.
Asigurați-vă că migrarea se aliniază cu obiectivele de business și că aceasta aduce plus-valoare.
Nu subestimați timpul și resursele necesare migrării; poate dura mai mult decât ați anticipat.
Dacă doriți să dezvoltați un sistem nou, în special aplicații web, trebuie să începeți de la monoliți.
de Mihai Darie
de Vlad Petrean