ABONAMENTE VIDEO REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 94
Abonament PDF

Poveste despre cloud (II)

Lucian Torje
Senior Java Developer @ Siemens
PROGRAMARE


Continuăm cu partea a doua a acestui articol despre istoria cloudului.

Cloud (2012 - 2016) - platforma

Scalabilitatea verticală era limitată, în mare parte, la capabilitățile aplicațiilor care rulau pe acel server. Creșterea performanțelor la nivelul unei singure aplicații începea să coste din ce în ce mai mult, pentru rezultate modeste (o creștere de 1-2%). Era timpul pentru o schimbare de concepție. Fiind deja folosit, modelul Horizontally Scaling Compute [29] promitea o creștere mult mai mare a performanțelor, ca sistem și nu ca aplicație singulară. Astfel a început migrarea în masa de la arhitecturi gen monolit la microservicii. Acest lucru era deja posibil și înainte, prin event-driven development realizat de obicei cu RabbitMQ cluster drept coadă de mesaje (uneori implementat ca remote procedure call, în cazuri mai complicate ca și CQRS - vezi Queue-Centric Workflow [29]).

De asemenea, se observă trecerea cât mai mare de la centru propriu de date la cloud public.

Arhitectura Monolit

Este o aplicație monolit, după cum sugerează și numele, care conține toate piesele într-un singur loc/proces (totul sau nimic).

Conform [17] o astfel de soluție oferă beneficii:

Din păcate, o astfel de arhitectură este statică și nu poate evolua independent. Nu este posibil să se folosească o versiune mai nouă sau un cu totul alt limbaj de programare doar pentru un anumit layer/zona din cod [vezi 22 pentru Layered Software Architecture]. De exemplu:

Cu cât aplicația devine mai mare, mentenanța devine mai greoaie deoarece este din ce în ce mai mult cod de analizat, schimbat, compilat și împachetat. Un singur defect într-un modul poate afecta alte zone (de exemplu, un memory leak într-un modul care este folosit rar, poate afecta toată aplicația).

Microservicii

Ideea din spatele microserviciilor este de a crea un serviciu prin agregarea mai multor servicii independente, fără stare (de preferat) și predictibile (același input, același output), care lucrează împreună.

Fiecare serviciu are propriile responsabilități, care, fiind independente, pot fi implementate, testate și instalate în mod independent.

Echipele care se ocupă de ele pot lucra, de asemenea, independent, o dată ce au convenit asupra interfețelor și modului de versionare - de exemplu, pentru REST[24]:

O astfel de arhitectură necesită coordonare atât între echipele care se ocupă de implementare, testare și instalare/release, dar și între microservicii (de exemplu, pentru scalare dinamică).

Problema 11 - migrarea de la monolit la microservicii

Folosind modelul Strangler, o aplicație monolit poate fi transformată într-o aplicație bazată pe microservicii, fără rescriere completă (în cazul aplicațiilor mari ar fi imposibilă din motive de business), rescriind ca microserviciu funcționalitățile noi. În timp, aplicația veche va avea din ce în ce mai puțin cod, iar microserviciile nou scrise vor prelua toată funcționalitatea aplicației vechi.

Acest procedeu seamănă cu transformarea codului legacy fără teste, în cod rescris și testat [vezi 26].

Problema 12 - localizarea

Deoarece în arhitectura monolit toate obiectele erau disponibile în memorie (același proces), viteza lor de obținere era foarte mare. Într-o arhitectură bazată pe microservicii, localizarea serviciilor care comunică des este foarte importantă pentru că apar întârzieri cauzate și de rețea.

Această problemă a fost rezolvată prin Colocate Pattern [29] - microserviciile care comunică des sunt localizate cât mai aproape unul de altul.

Problema 13 - traceability

Dat fiind că microserviciile sunt separate, este greu, uneori, de observat care serviciu și/sau utilizator a făcut o anumită acțiune și când. Pentru debugging/tracing/monitoring se folosesc sisteme de tracing distribuite ( de exemplu, Zipkin) sau unelte APM ( precum, Raygun. Iar pentru auditul datelor se folosesc implementări ale Event Sourcing Pattern (de exemplu, AWS CloudTrail) - salvarea schimbărilor suferite de date și inferarea valorii finale din acele schimbări. De exemplu , pentru un cont în bancă se salvează operațiunile efectuate asupra contului cum ar fi retragere de bani, iar balanța curentă se calculează pe baza acestor operațiuni. De asemenea, este importantă persoana care a efectuat operațiunea și când a fost făcută operațiunea. Acest patern este, de obicei, folosit de CQRS și poate fi implementat cu Kafka Streams (out-of-the-box fault-tolerance, scalabilitate și availibilitate [35]).

Problema 14 - scalare dinamică (auto/elastic scaling)

Pentru a minimiza costurile și a avea capacitate de calcul la cerere, este nevoie de scalare dinamică. Aceasta se poate obține aplicând Registry Pattern la nivel de microservicii [10] - utilizat de către alte obiecte/servicii pentru a găsi obiecte/servicii. Este folosit de către load balancer pentru a scala în mod dinamic un serviciu - noul serviciu pornit automat se înregistrează în registrul load balancer-ul, ca în cazul Netflix Eureka [36].

Problema 15 - "design for failure"

Cu cât sunt mai multe microservicii, cu atât șansele ca unul dintre ele să nu funcționeze cresc. Se dorește a avea un sistem care să continue să funcționeze, uneori chiar parțial. CircuitBreaker [13] propune o rezolvare a acestei probleme înlocuind rezultatul de la serviciul care nu funcționează cu valori implicite. De exemplu, dacă serviciul cu filmele favorite nu funcționează, în locul lor se prezintă clientului o colecție fixă (aceeași pentru toți utilizatori), de filme preferate, de multe ori clienții nesesizând diferența.

Problema 16 - caching

Distribuirea microserviciilor/serverelor și nevoia de performanță a aplicațiilor a dus la apariția folosirii cachingului pentru date/cereri și fișier. Cache-Aside Pattern [11] propune o rezolvare prin obținerea datelor din baza de date doar după verificarea propriului cache (implementările de ORM au de obicei mai multe nivele de caching) și CDN Pattern - caching distribuit cum ar fi cloudflare.com pentru fișiere rezolvă această problemă.

Problema 17 - comutarea dinamica a funcționalităților

A/B testing (utilizatorul A, ales arbitrar, primește un set de funcționalități, utilizatorul B un alt set) și canary releases (funcționalități pentru grupe de utilizatori/ zone geografice) au apărut din necesitatea de a obține feedback cât mai repede de la utilizatori asupra noilor funcționalități. De asemenea, detectează și dacă vechile funcționalități merită păstrate.

Feature Toggles Pattern [14] rezolvă această problemă permițând schimbarea funcționalității codului fără schimbări de cod, prin comutarea on/off a unor felii verticale (complete) de funcționalități. De exemplu, pentru o aplicație gen cumpărare/vânzare de acțiuni căreia i se adaugă în backend și frontend , suport pentru predicția de preț a acțiunilor: scoaterea acestei funcționalități trebuie să se poată face dintr-un singur loc (cel mai probabil din baza de date).

Acest tip de patern poate modifica inclusiv modul de lucru cu sistemele revision control gen Git, deoarece pe lângă modurile de lucru trunk based development sau gitflow [15], se poate lucra direct în trunk, release-ul însemnând doar comutarea funcționalității noi (până nu este gata, funcționalitatea rămâne oprită) [37].

Problema 18 - migrarea la cloud

În această perioadă a început migrarea către cloudul public a aplicațiilor vechi. Apare necesitatea definirii a ceea ce înseamnă o aplicație cloud, așa că în 2011 cei de la Heroku au definit o metodologie pentru crearea de aplicații SaaS (cloud native) care se numește Twelve-Factor App.

12 factori

O aplicație care respectă următoarele puncte nu va avea probleme în a rula în cloud [30][39]:

Atribute ale aplicațiilor Cloud Native

Conform [34][40], aplicațiile cloud-native au următoarele atribute:

Modele Cloud Native

Conform [28][45], se identifică următoarele modele:

Service mesh

Service mesh poate părea o generalizare a API Gateway în sensul că oferă servicii asemănătoare (criptare, autentificare, autorizare, load balancing, rutare, monitorizare, analitice și tracing), doar că face aceasta la un alt nivel. Service mesh funcționează la comunicarea între servicii, pe când API gateway la comunicarea dintre client și servicii.

Pe lângă aceste servicii, mai oferă descoperirea serviciilor și suport pentru circuit breaker. Reușește să implementeze aceste funcționalități folosind un proxy pentru fiecare serviciu, numit sidecar. Acest serviciu poate fi configurat independent de serviciu propriu-zis.

Printre furnizorii de soluții service mesh se află Istio, Lyft, Linkerd și Hashicorp Consul.

Alternative REST - NATS [33] și gRPC [42]

NATS este un sistem de mesaje cloud native, IoT și arhitectura microservicii (bus de mesaje). Suportă publish/subscribe, competing consumers și request /reply , iar mesajele sunt text [41].

Exemplu de mesaj:

PUB FOO 11NATS!

gRPC este o librărie construită peste HTTP2 și care ajută la load balancing, tracing, la verificarea sănătății și la autentificare. Mesajele sunt schimbate în format binar pe TCP, utilizându-se optimizări HTTP2 pentru multiplexare și streaming.

Sursa - https://landscape.cncf.io/images/landscape.png

CNCF Cloud Native Interactive Landscape

În imaginea de mai jos se pot observa multitudinea de aplicaţii dezvoltate în jurul conceptului de cloud native applications [52].

Problema 19 - Frontend monolit (Micro Frontends)

Odată cu schimbările din backend a apărut și nevoia optimizării frontendului - încercarea unor tehnologii mai noi, deployment independent, împărțirea implementării între mai multe echipe autonome. Astfel a apărut necesitatea de a trece de la o aplicație frontend monolit la ceva asemănător cu microserviciile. Rezultatul a fost micro frontends [32]; mai multe aplicații frontend care împreună să se comporte ca o singură aplicație frontend.

Micro Frontends se poate implementa în mai multe moduri, vom aminti câteva:

Cloud (2017 - acum) - funcții

O dată cu simplificarea folosirii platformelor și diversificarea lor, a apărut posibilitatea de a rula direct în cloud cod/funcții (FaaS) sau de a folosi API care folosește un cloud (BaaS).

Acest tip de arhitectură se numește serverless computing și are câteva beneficii importante:

Dar și câteva dezavantaje:

Cold start / Warm start

Cold start înseamnă că a fost făcută o cerere, iar containerul, care trebuie să răspundă, este oprit, ceea ce adaugă la timpul de răspuns și timpul necesar downloadului și pornirii containerului și al microserviciului adăugat la răspunsul propriu-zis de la microserviciu.

Warm start înseamnă că deja este pornit containerul și poate să răspundă. Dacă timp de câteva minute containerul nu mai primește cereri, se va opri singur. Pentru AWS Lambda există posibilitatea de a elimina cold-starts folosind Provisioned Concurrency [49].

Mikhail Shilkov, în articolul său [31], a prezentat un grafic în legătură cu timpul cold start în funcție de limbajul de programare.Conform măsurătorilor sale, funcțiile scrise în Node.js au cel mai mic cold-start, depinzând bineînțeles și de dimensiunea codului.

Pornirea unei aplicații Spring Boot obișnuite poate să dureze între 10 și 20 secunde în funcție de complexitate. Există interes în a reduce acest timp - Spring Boot 2.2 a introdus lazy initialization [43] tocmai pentru a reduce din timpul de start al aplicațiilor bazate pe Spring Framework (pe lângă suportul pentru directivele ComponentScan (lazyInit = true) și Import.

Quarkus vs Spring

Quarkus la fel ca Micronaut sau Helidon este un framework lightweight pentru microservicii.

Conform [18], o aplicație bazată pe Quarkus nativă/JVM comparabilă cu o versiune bazată pe Spring Boot, consumă de 50/1.5 de ori mai puțină memorie (2.1 MB, 74 MB versus 115 MB) și pornește de 500/250 ori mai repede (0.01/0.018 sec versus 5.27 sec).

O aplicație bazată pe Quarkus va economisi bani, folosind mai puține resurse și pornind mai repede.

Viitorul

Conform [5][6] se observă următoarele tendințe în adoptare soluțiilor de cloud:

Edge computing

Edge computing redefinește cloudul prin faptul că unele capacități de calcul se mută din centrul de date, cât mai aproape de utilizator, device, senzori etc, creându-se, astfel, o structură distribuită de cloud. International Data Corporation (IDC) o descrie ca: "o plasă/mesh peste micro centrele de data care procesează și stochează date locale esențiale și le trimit către un centru de date central sau DaaS, colocate în 10 metri pătrați."

Acest mod de lucru este important pentru IoT, unde este nevoie de procesarea unor cantități uriașe de date, cât mai local posibil, încât să nu fie pierderi de performanță cauzate de transferul prin rețea. De asemenea, datele de la senzori fiind prelucrate parțial, doar rezultatele/agregările trebuie trimise către centru, reducându-se astfel și costurile de rețea și stocare.

Încheiere

În acest articol am urmărit evoluția cloudului: de la definirea sa ca idee și expunerea primelor sale implementări la menționarea problemelor apărute și a soluțiilor de rezolvare a acestora. De asemenea, am enumerat câteva dintre tendințele de schimbare a cloud computing-ului.

Bibliografie

  1. https://medium.com/threat-intel/cloud-computing-e5e746b282f5

  2. https://blogs.gartner.com/marco-meinardi/2018/11/30/public-cloud-cheaper-than-running-your-data-center/

  3. https://itif.org/publications/2017/05/01/cross-border-data-flows-where-are-barriers-and-what-do-they-cost

  4. https://mvnrepository.com/

  5. https://www.eweek.com/innovation/cloud-2020-canonical-s-six-trends-shaping-the-future-of-cloud

  6. https://www.gartner.com/smarterwithgartner/4-trends-impacting-cloud-adoption-in-2020/

  7. https://medium.com/solo-io/https-medium-com-solo-io-supergloo-ff2aae1fb96f

  8. https://imelgrat.me/cloud/cloud-services-models-help-business/

  9. https://blog.back4app.com/2019/07/24/backend-as-a-service-baas/

  10. https://www.martinfowler.com/eaaCatalog/index.html

  11. https://blog.cdemi.io/design-patterns-cache-aside-pattern/

  12. https://www.enterpriseintegrationpatterns.com/patterns/conversation/LoadBalancer.html

  13. https://martinfowler.com/bliki/CircuitBreaker.html

  14. https://martinfowler.com/articles/feature-toggles.html

  15. https://www.toptal.com/software/trunk-based-development-git-flow

  16. https://dzone.com/articles/event-driven-microservices-patterns

  17. https://microservices.io/patterns/monolithic.html

  18. https://dzone.com/articles/microservices-quarkus-vs-spring-boot

  19. https://imelgrat.me/cloud/cloud-services-models-help-business/

  20. https://www.cloudflare.com/learning/serverless/serverless-vs-containers/

  21. https://dzone.com/articles/the-future-of-spring-cloud-microservices-after-net

  22. https://medium.com/@priyalwalpita/software-architecture-patterns-layered-architecture-a3b89b71a057

  23. https://medium.com/@SoftwareDevelopmentCommunity/what-is-service-oriented-architecture-fa894d11a7ec

  24. https://restfulapi.net/versioning/

  25. https://dzone.com/articles/monolith-to-microservices-using-the-strangler-patt

  26. Working Effectively with Legacy Code by Michael Feathers

  27. Patterns of Enterprise Application Architecture by Martin Fowler

  28. cloud Native Development Patterns and Best Practices by John Gilbert

  29. cloud Architecture Patterns by Bill Wilder

  30. https://12factor.net/

  31. https://mikhail.io/serverless/coldstarts/aws/

  32. https://www.martinfowler.com/articles/micro-frontends.html

  33. https://thenewstack.io/nats-rest-alternative-provides-messaging-distributed-systems/

  34. https://thenewstack.io/10-key-attributes-of-cloud-native-applications/

  35. https://www.confluent.io/blog/event-sourcing-cqrs-stream-processing-apache-kafka-whats-connection/

  36. https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance

  37. https://devops.com/feature-branching-vs-feature-flags-whats-right-tool-job/

  38. https://cloud.spring.io/spring-cloud-netflix/multi/multi__modules_in_maintenance_mode.html

  39. https://youtu.be/jufe_sHejXc

  40. https://pivotal.io/cloud-native

  41. https://docs.nats.io/nats-protocol/nats-protocol

  42. https://grpc.io/

  43. https://spring.io/blog/2019/03/14/lazy-initialization-in-spring-boot-2-2

  44. https://kubernetes.io/docs/concepts/cluster-administration/federation/#why-federationc

  45. https://docs.microsoft.com/en-us/azure/architecture/patterns/bulkhead

  46. https://www.networkworld.com/article/3224893/what-is-edge-computing-and-how-it-s-changing-the-network.html

  47. https://www.cloudorado.com/cloud_hosting_comparison.jsp

  48. https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html

  49. https://aws.amazon.com/blogs/compute/new-for-aws-lambda-predictable-start-up-times-with-provisioned-concurrency/

  50. https://mashable.com/2010/08/07/ebay-facts/?europe=true

  51. https://www.bcs.org/content-hub/history-of-the-cloud/

Sponsori

  • comply advantage
  • ntt data
  • 3PillarGlobal
  • Betfair
  • Telenav
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • MetroSystems
  • BoatyardX
  • Colors in projects

VIDEO: NUMĂRULUI 95