Microservicii sau monoliți, arhitecturi serverless sau orientate pe servicii, MACH, blocuri fundamentale ale arhitecturii aplicațiilor Java, containerizare, aplicații 12 factor și multe altele - toate reprezintă soluții pe care le avem la dispoziție, însă niciuna care să răspundă tuturor provocărilor. Prin urmare apare întrebarea: "Contează cu adevărat tipul de arhitectură? Este o arhitectură bazată pe microservicii superioară uneia monolitice?"
În loc să ne concentrăm pe imaginea de ansamblu, propun examinarea detaliilor mărunte, deoarece știți că diavolul se află în detalii. Cred cu fermitate că, indiferent de arhitectura aleasă sau dacă sistemul tău este bazat pe cloud sau on-premise, succesul depinde de anumite aspecte cruciale ale aplicației tale. De aceea, implementează aceste componente eficient și vei crea un mediu în care aplicația ta poate înflori.
În acest articol îmi propun să împărtășesc aceste elemente arhitecturale eficiente și de succes.
Să începem! Primul lucru despre care vom discuta sunt opțiunile de framework. Cum acesta este un ghid rapid și nu un tutorial, voi încerca să vă prezint doar lucrurile esențiale.
Pentru aplicațiile tradiționale care înclină spre o structură monolitică, Jakarta EE este o alegere bună. Nu mai trebuie să îți faci griji cu privire la adăugarea funcționalităților sau la alegerea bibliotecilor și a tehnologiilor. Majoritatea funcțiilor de care ai nevoie sunt integrate în serverele de aplicații. Wildfly și Glassfish sunt o alegere excelentă.
Dacă preferi structuri ușoare sau microservicii, dar apreciezi totuși Jakarta EE, ia în considerare MicroProfile. Este un framework mai ușor cu funcții încorporate, precum verificările de sănătate, metricile și toleranța la erori. Deși este promovat pentru microservicii, este util și pentru alte tipuri.
Dacă Jakarta EE nu este pe gustul tău, încearcă Spring Boot. Este versatil, bogat în funcții și un competitor solid pentru Jakarta EE și MicroProfile împreună.
Pentru cei mai aventuroși, Quarkus merită explorat. Este rapid, ușor și orientat spre performanță, conceput pentru suport nativ, deși are unele dezavantaje, cum ar fi timpii de construcție mai lungi și eventuala incompatibilitate cu reflexia.
Articolul se concentrează pe aplicațiile backend și pe microservicii, iar subiectul UI va fi omis. Indiferent de tehnologia aleasă, există mai multe aspecte esențiale de reținut, pe care le vom discuta în continuare. Și reține că nu există o soluție perfectă - totul depinde de context și de nevoile tale.
Un framework eficient necesită un management robust al configurărilor. Deși ar putea părea banal, managementul configurărilor este de o importanță deosebită din două motive (evident mai multe însă menționez doar două):
Este una dintre primele reguli ale aplicațiilor 12 factor.
Când proiectezi, ia în considerare cerințele potențiale de business, frecvența modificărilor, necesitatea repornirilor, interfața cu utilizatorul încorporată și, mai presus de toate, considerentele de securitate pentru stocarea datelor sensibile. Iată câteva îndrumări care vor ajuta la menținerea unui design robust:
Anticipează nevoile de business și evaluează frecvența modificărilor. Acest lucru va spori capacitatea de răspuns și stabilitatea aplicației.
Limitează nevoia de repornire a serverului atunci când o configurare se modifică.
Ia în considerare interfața cu utilizatorul, mai ales în cazul în care clientul trebuie să facă schimbări frecvent.
Ia în considerare o soluție practică, precum Spring Cloud Config pentru o abordare concretă.
Explorarea serviciilor REST ar putea umple un articol întreg, dar iată câteva reguli simple, bune practici pentru un design coerent:
Prioritizează contractele API consistente - consideră-le coloana vertebrală a API-ului tău.
Folosește Open API pentru documentație pentru că, să recunoaștem, cu toții preferăm să scriem cod, nu documentație.
Pe lângă testarea cu Postman (pe care toți îl iubim), folosește sisteme automate de testare, precum Rest Assured.
Adoptă un format de eroare standardizat pentru gestionarea erorilor - un simplu obiect JSON cu coduri de eroare și descrieri poate face minuni.
Pentru a gestiona seturi mari de date, nu uita de filtrare și paginare.
Tip | Metoda HTTP | Descriere |
---|---|---|
Create | POST | Crete a new entity (IN) The new entity |
in request body (OUT) 201 + "Location" | ||
header with entity URI (OUT) 400 + | ||
Invalid entity error as response (OUT) | ||
500 + Internal server error as response | ||
Read | GET | Read entity by ID (IN) entity ID as path |
param (OUT) 200 + The entity in the | ||
response body (OUT) 404 + Entity not | ||
found as response (OUT) 500 + Internal | ||
server error as response | ||
Query | GET/POST | Search for entities (IN) The search |
criteria as query param or request body | ||
(OUT) 200 + The search result as | ||
response (OUT) 400 + Invalid search | ||
criteria as response (OUT) 500 + | ||
Internal server error as response | ||
Update | PUT | Update an existing entity (IN) The id of |
the entity as query param and entity to | ||
update in the request body (OUT) 200 + | ||
found entities as response body (OUT) | ||
400 + Invalid entity error as response | ||
(OUT) 404 + Entity not found as response | ||
(OUT) 500 + Internal server error as | ||
response | ||
Delete | DELETE | Delete entity by ID (IN) Entity ID as |
path param (OUT) 200 + Entity deleted | ||
successfully (OUT) 404 + Entity not | ||
found as response (OUT) 500 + Internal | ||
server error as response |
Simplifică securitatea aplicației tale cu OIDC și Oauth2, folosind un furnizor de identitate preferat, cum ar fi KeyCloak. Această combinație acoperă majoritatea fluxurilor/tipurilor de granturi necesare.
Dacă aplicația ta utilizează SAML și nu poate fi schimbată ușor, IDP-ul tău poate converti de obicei tokenul din bătrânul SAML în Oauth2 token.
Evită autentificarea "basic" și nu-ți crea niciodată propriul framework de securitate, cu excepția cazului în care ești expert în securitate.
Loggingul este vital și, fără îndoială, monitorizarea cu atât mai mult. Fără un logging coerent, poți pierde timp prețios vânând buguri, timp pe care l-ai putea petrece într-un bar sau cu familia ta. Respectă aceste reguli:
Evită loggingul pe mai multe linii pentru a simplifica monitorizarea și urmărirea.
Utilizează formatul JSON, deoarece se împerechează bine cu instrumentele de vizualizare a datelor.
Adaugă context logurilor: ID de utilizator, trace ID sau orice date relevante pentru contextul de business.
Utilizează niveluri de log adecvate și evită debug în producție.
Pentru stack-ul tău:
Utilizează SLF4j.
Alege un colector de loguri, precum Logstash, Splunk sau FluentID.
Utilizează o bază de date distribuită, precum Elasticsearch sau Splunk pentru stocarea logurilor.
Utilizează instrumente de vizualizare, precum Splunk, Kibana sau Grafana.
Nu subestima funcțiile native de monitorizare ale frameworkului tău. Adnotările oferite de Microprofile, de exemplu, pot facilita monitorizarea ușoară a metricilor:
@Timed
- surprinde cât timp se execută o metodă.
@Counted
- calculează de câte ori este invocată o metodă.
@Gauge
- monitorizează valorile fluctuante și poate furniza un snapshot al sistemului; util pentru a monitoriza valori precum dimensiunea cozii sau utilizatorii activi.
@Metered
- urmărește cât de des este invocată o metodă, adesea reprezentată drept "apeluri pe secundă".Astfel de adnotări sunt disponibile în diferite frameworkuri, inclusiv Spring. În loc să-ți creezi propriile metrici, profită de instrumentele existente ale frameworkului tău pentru a optimiza fluxul de lucru și pentru a standardiza procesele.
Într-o aplicație monolitică, urmărirea apelurilor metodelor în scopul localizării zonelor lente este destul de simplă, deoarece toate acțiunile au loc într-un singur context. Adăugarea de măsurători pentru a culege date, cum ar fi timpii de obținere a datelor din baza de date, este relativ simplă. Cu toate acestea, într-un mediu de microservicii în care ele sunt interconectate, identificarea blocajelor devine o sarcină complexă.
Există două soluții obișnuite pentru a urmări apelurile de metode și interacțiunile dintre servicii: implementarea personalizată și utilizarea de API-uri.
Implementarea personalizată implică, de obicei, adăugarea unui trace ID în liniile de log, nume de servicii sau metode și, eventual, starea sau durata. Aceste loguri pot fi căutate folosind instrumente precum Splunk. Această abordare, deși simplă și realizabilă prin Spring Aspect sau JEE Interceptor, prezintă riscuri precum standardizarea și instrumente limitate de UI.
Abordarea API implică soluții precum OpenTracing și Jaeger, primul furnizând standardul și API-ul, iar cel de-al doilea oferind implementarea. Deși configurarea este mai complexă, poate fi utilă pentru proiecte în creștere și în ecosisteme mai mari.
Ambele metode îți permit să vizualizezi și să înțelegi interacțiunile din ecosistemul tău.
Reziliența în microservicii Java implică funcționalități cheie, cum ar fi întrerupătoarele de circuit, timeout-uri și failover .
Un întrerupător de circuit previne, într-un ecosistem de microservicii, eșecurile de serviciu în cascadă. MicroProfile oferă o adnotare @CircuitBreaker în acest scop. De exemplu:
@CircuitBreaker(requestVolumeThreshold = 4,
failureRatio = 0.75, delay = 1000)
public Connection serviceConnect() { ... }
Acest fragment de cod activează întrerupătorul dacă 75% dintre solicitări eșuează într-o fereastră continuă de patru solicitări, după care așteaptă 1000 ms înainte de a reîncerca.
Timeout-urile împiedică sistemul să rămână blocat în operațiuni care au puține șanse de reușită. Acest lucru este realizabil folosind adnotarea @Timeout din MicroProfile.
Timeout(500)
public Connection serviceConnect() { ... }
În acest exemplu, dacă metoda serviceConnect depășește 500 de milisecunde pentru a răspunde, aceasta este întreruptă automat.
Funcțiile de failover permit redirecționarea automată a cererilor de la un serviciu defect la unul funcțional.
Combinând aceste strategii, ne putem menține reziliența aplicației, putem gestiona și ne putem recupera cu eleganță după eșecuri.
Deși un design arhitectural poate oferi avantaje semnificative pentru proiectul tău, este ca și cum te-ai aștepta să câștigi o cursă doar pentru că ai o mașină nouă și strălucitoare!
Să luăm ca exemplu arhitectura MACH (bazată pe Microservicii, cu API-first, nativă în Cloud și Headless). În ciuda numelui său impresionant, a flexibilității și a scalabilității pe care le oferă, aceasta vine și cu provocări. Gestionarea mai multor microservicii poate deveni complexă. Aceasta necesită echipe tehnice competente, pricepute în sisteme bazate pe cloud, microservicii și API-uri. Menținerea consistenței datelor ar putea prezenta dificultăți din cauza bazelor de date separate pentru fiecare microserviciu. Eventuala latență de comunicare între servicii cauzată de rețea, modificările complexe ale relațiilor dintre servicii, precum și nevoia de securitate la nivel înalt, se adaugă, de asemenea, la provocări. În cele din urmă, costurile operaționale pot crește în funcție de dimensiunea proiectului și de furnizorul de servicii cloud selectat.
Principiile pe care le-am conturat aici sunt aplicabile universal, indiferent de arhitectură sau de mediu. Concentrându-te pe un design de API corespunzător, vei implementa o monitorizarea și trasabilitate eficientă. În acest fel îți vei consolida aplicația împotriva eșecurilor, vei deschide calea pentru o aplicație robustă și ușor de gestionat în producție. Concentrându-te pe aceste aspecte, vei garanta identificarea și rezolvarea rapidă a problemelor și vei asigura că sistemul tău poate face față provocărilor neașteptate fără perturbări semnificative.
Reține că acestea sunt doar puncte de pornire și că fiecare subiect pe care l-am abordat aici ar putea necesita propriul său articol.
În speranța că am subliniat suficient semnificația acestor subiecte, voi încheia cu o colecție de resurse pentru a-ți permite să le aprofundezi.
Prima recomandare este să citești regulile 12 factor apps. Vei găsi un set complet de reguli de urmat.
Am menționat The ELK Stack - dacă dorești să afli mai multe, accesează linkul.
Spring Boot și JakartaEE se bucură de o recunoaștere mai largă, în timp ce Microprofile și Quarkus zboară pe sub radar. Am inclus aceste două linkuri către tutoriale pentru a le prezenta potențialul.
Consider că MACH devine mainstream, așa că ar putea fi o idee bună să te uiți la acest tip de arhitectură.
de Peter Leeson
de Denisa Lupu