Acest articol se dorește a fi o prezentare despre conceptul cloud, despre modul cum acesta a apărut, a evoluat, cât și despre problemele cu care s-a confruntat programarea în cloud.
Cloud computing a fost definit prima dată de prof. John McCarthy în 1961 ca fiind:
"Folosirea calculatoarelor va fi probabil organizată cândva ca un serviciu public gen telefonul... Unde fiecare abonat trebuie să plătească doar cât a folosit, dar are acces la toate limbajele de programare de care are nevoie... Unii abonați își vor putea oferi serviciile altor abonați... Serviciul public de calculatoare va putea deveni baza unei noi și importante industrii."
În aceeași perioada a început dezvoltarea tehnologiilor care stau la baza cloudului:
Virtualizarea. În 1972 IBM Virtual Machine Facility/370 putea rula pe mainframe câteva mii de mașini virtuale cu sistem de operare gen MVS sau DOS/VSE).
Mulți ani după aceea, o dată cu creșterea masivă a utilizatorilor de Internet (1995-2000) a fost necesară adaptarea la noile probleme (mulți utilizatori, răspândire mare, servicii oferite fără întrerupere, performanță). Astfel au apărut modele computaționale gen:
grid computing. Acesta rezolvă problema folosirii multor calculatoare de performanță medie pentru a soluționa o problemă destinată unui supercalculator.
Internet data center. Centrele de date existau încă din anii 40', doar că acum erau distribuite pe regiuni geografice, iar unele își ofereau serviciile în mod public.
Cloud-ul ca serviciu public a apărut în 2002, o dată cu lansarea de către Amazon a primului cloud comercial. Mai apoi, prin dezvoltarea OpenNebula și OpenStack, alte companii au putut să implementeze soluții de cloud privat în propriile centre de date.
În anii 90', majoritatea paginilor erau statice. Doar în a doua jumătate a anilor 90› debuta dezvoltarea paginilor dinamice simultan cu cererea utilizatorilor de avea conținut personalizat și posibilitatea de a executa funcționalități (gen login, upload de fișiere sau formular de contact), pe care o pagină statică nu le-ar fi putut oferi.
O pagină web în acea perioadă (Ebay) arăta așa:
În mai puțin de 20 de ani s-a ajuns de la a avea propriile servere, la a rula simple funcții în cloud a căror instalare durează sub 1 minut, versus o zi cât putea să dureze compilarea, împachetarea și instalarea pachetului nou la început.
În 1999, costul unei aplicații Java web era aproximativ 400.000 dolari (cheltuiala de capital - server + Weblogic + baza de date + IDE) și cam 80.000 dolari (cheltuiala operațională - mentenanța). Acum se poate ajunge la costuri operaționale lunare de aproximativ 250 dolari pentru funcționalități comparative (sursa cloudorado [47]), folosind tehnologii open source. Aceste reduceri de cost au permis răspândirea utilizării cloudului și implicit scăderea și mai mare a costurilor.
Expunem mai jos cronologia evenimentelor care au marcat evoluția cloudului:
-1990. Apare primul browser web numit WorldWideWeb.
-1993. Apar: HTML, specificații CGI (Common Gateway Interface - servere web sunt executate ca aplicații consolă), browserul NCSA Mosaic (suporta imagini inline) și organizația OASIS (Organization for the Advancement of Structured Information Standards).
-1994. Își face apariția PHP. Este creată World Wide Web Consortium - W3C (printre fondatori Comisia Europeana și DARPA). De notat și apariția Netscape Navigator care suporta HTTP Cookies.
-1995. Apache, IIS, MySQL.
-1996. Java, JavaScript, CSS, Adobe Flash (FutureSplash sau Flash 1.0) sunt definite IFrame și Java servleturile.
-1998. Tomcat, NoSQL. Sunt standardizate XML (W3C), SOAP și XML-RPC (Microsoft), Document Object Model - DOM (W3C), JavaServer Pages - JSP (Sun)
-1999. Apare Linux-HA (high availability), se definește AJAX - Asynchronous JavaScript + XML, Active Directory.
-2000. Sunt definite REST + HATEOAS (Roy Fielding), WSDL (IBM, Microsoft și Ariba), XHTML (W3C), JavaScript Object Notation - JSON (Douglas Crockford ).
-2001. VMware ESXi (hipervizor), Hibernate ORM. Apare HAProxy (load balancer open source). Este definit XSD (W3C) și Scalable Vector Graphics - SVG și se pun bazele Open Web Application Security Project (OWASP).
-2002. Amazon lansează primul cloud comercial, se definește Security Assertion Markup Language - SAML.
-2003. Se definește Advanced Message Queuing Protocol - AMQP (messaging pentru middleware), apare Memcached (caching tip cheie-valoare în memorie).
-2004. Nginx (server web care poate fi folosit și ca reverse proxy, load balancer, caching, media streaming și email server proxy), Selenium (teste automate). Se definește JavaServer Faces - JSF.
-2005. Începe lucrul la OpenNebula (cloud management - primul release public în 2008), apare conceptul de Data Lake, SoapUI, Git și Mercurial (revision control), Django (web framework pentru Python).
-2006. AWS EC2 (servere virtuale în cloud), AWS S3 (serviciu storare obiecte), OAuth (Twitter - protocol open source de securitate), SonarQube (inspecția continuă a calității codului), Liquibase.
-2007. KVM, RabbitMQ, Struts, OpenID Foundation, Neo4j, Bambo, Heroku (PaaS - Cloud Application Platform).
-2008. Apar Google Cloud Platform, Google App Engine, Alibaba cloud (Aliyun), Hadoop, Apache Cassandra, Cucumber.
-2009. cloudflare (servicii CDN), Apache Mesos (management cluster), Node.js, Redis, MongoDB.
-2010. PiCloud (FaaS), OpenStack (cloud management creat de Rackspace Hosting și NASA), CloudFoundry (PaaS - din 2019 suportă AWS, Azure, Google Compute Platform (GCP), OpenStack, VMware vSphere, SoftLayer, etc), apar Microsoft Azure, Elasticsearch, Vagrant (simularea environment-ului din producție pe calculatorul de development), Angular JS și Flask (web framework pentru Python).
-2011. 12 Factor, Parse Platform (MBaaS open sourced în 2016 - folosit de Back4App), AWS Elastic Beanstalk (orchestrator), OpenShift, Vert.X, Dropwizard, Puppet, React, WebSockets (RFC 6455), Bootstrap, NATS, Jenkins, Ansible, Swagger, Netflix SimianArmy/ChaosMonkey.
-2012 . Firebase (platforma de dezvoltare de aplicații mobile), OAuth 2.0, Amazon DynamoDB, Eureka, Zipkin, Netflix Ribbon (load balancer), Thoughtworks (Radar - https://www.thoughtworks.com/radar), Arquillian, Baidu cloud (Wangpan) .
-2013. Spring Boot, Docker, Netflix Scryer outsourcing, JHipster.
-2014. The Reactive Manifesto, Kubernetes (open-source container storage), Terraform (IaaS), Hashicorp Consul (service discovery, DNS), RxJava, HTML5 (World Wide Web Consortium - W3C), AWS Lambda, AWS Aurora, Apache Spark.
-2015. Docker Swarm, Spring cloud Starter Zuul [4], Spring cloud Starter Ribbon [4], Pentaho (business intelligence), gRPC Remote Procedure Calls, HTTP/2, Flyway, Gatling (load testing).
-2016. Netflix Meson outsourcing, Spring cloud Starter Sleuth [4], Back4App (BaaS), Prometheus (monitorizare și alertare), OpenTracing3 (instrumentare pentru tracing distribuit), AWS X-Ray (debugging), IBM cloud .
-2017. Istio (service mesh), Netflix Conductor outsourcing, Squash și Telepresence (debuggere pentru microservicii în Kubernetes), Hapi, Jaeger, Kubernetes Ingress Nginx, AWS IoT Greengrass, Amazon SageMaker.
-2018. SuperGloo (platforma pentru mesh orchestration) [7], Micronaut, Helidon, Firecracker (tehnologie de virtualizare open source), Azure IoT Edge, Google AI Platform, Apache OpenWhisk (serverless), mai multe proiecte Netflix intră în maintenance mode (Hystrix înlocuit de Resilience4j, Hystrix Dashboard/Tubine înlocuit de Micrometer, Ribbon înlocuit de Spring Cloud Load Balancer, Zuul inlocuit de Spring Cloud Gateway, Archaius inlocuit de Spring Cloud Config)
-2019. AWS Outposts (servere on-premise), Quarkus, Outsource Netflix Mantis, Fluentd (data collector).
-2020. Netflix Zuul 2 outsourcing, Kubefed2 (Kubernetes Federation).
Înainte de a discuta despre evoluția cloudului, vom defini tipurile de cloud și servicii oferite.
Amazon Web Service, Google cloud Platform sau Microsoft Azure sunt clouduri publice unde mai mulți utilizatori (mediu multi-tenant) folosesc în comun mai multe resurse fizice, plătind doar pentru serviciile folosite și în funcție de durată, capacitate, viteza la care au fost folosite sau de specificațiile sistemului folosit (de exemplu, hardware, software, distribuire regională).
Aceste servicii au SLA - service level agreement - un contract prin care se garantează disponibilitatea serviciului la parametri conveniți.
Dacă SLA nu oferă ceea ce dorește organizația ca performanță, capabilități sau nivelul de securitate nu este de ajuns, se poate opta pentru un cloud privat.
Marco Meinardi, director de cercetare la Gartner, a publicat un studiu în care migrarea a 2500 servere virtuale proprii migrate în AWS EC2 a dus la o scădere cu 55% a costurilor totale.
Printre alte beneficii ale cloudului public, enumerăm:
Update automat al software-ului / hardware-ului;
Riscuri de securitate - acoperite de furnizor;
Scalabilitate - acoperă inclusiv cererile sezoniere/periodice/automat de resurse de calcul (de exemplu de BlackFriday, în fiecare zi între orele 10-12 sau automat vezi Auto-Scaling Pattern [29]);
Analitics - informații despre cine sunt utilizatorii și cum folosesc serviciul oferit;
Mirroring - acces la diferite regiuni - există țări în care datele trebuie să rămână în acea țară [3];
Cloudul privat este destinat nevoilor unei singure organizații. Poate fi de mai multe tipuri:
virtual - folosind VLAN, se pot folosi resurse din mai multe clouduri publice.
hosted - organizația are propriul centru de date configurat să funcționeze ca un cloud.
Există mai mulți furnizori/aplicații de soluții de cloud privat:
VMware vRealize Suite;
Oracle Private Cloud Appliance X8;
IBM Cloud Managed Services;
OpenStack;
Cloudul hibrid folosește ceea ce este mai bun din cele două soluții - flexibilitatea cloudului privat și costurile reduse ale cloudului public, făcând legătura între cele două.
Tipuri de modele de servicii cloud
Modelele de servicii merg de la a oferi doar infrastructura până la a oferi posibilitatea de a crea o nouă aplicație, doar valorificând servicii existente, gen pipeline.
Lista serviciilor conține [19]:
Infrastructure as a Service (IaaS) - resurse ca rețea, stocarea datelor și servere.
Platform as a Service (PaaS) - un mediu de cloud în care se pot implementa, administra și găzdui aplicații.
securitatea, sistemele de operare, și backupuri sunt responsabilitatea furnizorului.
Software as a Service (SaaS) - aplicații web sau API/web services
Backend as a Service (BaaS sau mBaaS) - backendul pentru aplicație cu suport pentru managementul utilizatorilor, integrare social media, securitate, push notifications, logs, CDN, caching, analytics, stocarea datelor, hosting, posibilitatea definirii de funcții (serverless), uneori funcționalități extinse gen machine learning .
utilizatorul folosește un API pentru accesarea cloudului.
Storage as a service (STaaS) - stocarea datelor (fișier).
Data as a Service (DaaS) - stocarea datelor fie în baze de date sau containere de obiecte.
Containers-as-a-Service (CaaS) - seamănă cu PaaS, diferența este că pachetul de instalare este un container (Docker, de obicei).
Function-as-a-Service (FaaS) - instalare ca funcții (serverless).
Analytics-as-a-Service (AaaS) - soluție BI.
Identity-as-a-Service (IDaaS) - autentificare pentru cloud oferită de un furnizor third-party.
Înainte de prima generație de cloud, programarea aplicațiilor însemna de cele mai multe ori folosirea de editoare text cum ar fi emacs, vi, joe sau notepad (editoare WYSIWYG precum Macromedia Dreamweaver erau scumpe), compilarea și împachetarea aplicației, copierea pe discheta/CD sau ftp/shared folder. Odată creat manual pachetul de instalare, o altă persoană (ITOps) urma să facă instalarea și, de prea multe ori, nu funcționa manifestându-se prin căi către fișiere fixe în cod, pași de instalare incorecți, variabile de sistem diferite, router care trebuia repornit, etc.
Prima generație cloud a făcut trecerea de la centrul de date (care însemnau de obicei unul sau mai multe servere blade/PC) la o arhitectură virtuală (de exemplu, servere care rulau VMware ESXi ca sistem de operare).
Această arhitectură rezolva câteva probleme.
Uneori, apărea nevoia de a obține un calculator pentru o scurtă perioadă de timp. Virtualizarea a rezolvat această problemă pentru că nu mai era nevoie de cerere pentru buget, așteptarea livrării calculatorului și instalarea sistemului de operare dorit. În câteva minute era posibil să se cloneze o imagine deja definită și să se pornească. O altă soluție care a apărut mai târziu - folosirea de imagini Docker (de exemplu, nginx:alpine). În imaginea de mai jos, preluată din articolul [20], se poate observa o comparație între timpul necesar pornirii unei mașini virtuale, container sau o funcție:
Backupul datelor era deja realizat în SAN/NAS/RAID, dar cum se putea face backup la un server în producție cu efecte minime asupra utilizatorilor ?
Virtualizarea a făcut acest lucru posibil prin crearea de snapshoturi (puncte de restaurare). Ca bonus, acestea puteau fi restaurate mai târziu nu numai în caz de probleme, dar și pentru a se ajunge la o stare a sistemului de operare dorită (de exemplu, în cazul reproducerii unui defect mai vechi).
Chiar dacă viteza la Internet a crescut și modemurile de 56kbps sunt istorie, aplicațiile web încep să aibă cerințe mai mari ca performanță și bandwidth. Mai mult, aplicațiile devin globale și pagini web încep să fie accesate simultan din mai multe spații geografice. Pentru a îmbunătăți performanța, au fost implementate câteva tehnici:
progressive rendering - randarea părților din paginile web;
optimizarea codului JavaScript;
optimizarea imaginilor;
AJAX calls;
caching - vezi Cache-Aside Pattern;
mirroring pentru conținut - vezi CDN Pattern;
Înainte de aplicațiile web tip SPA (o singură pagină folosind AJAX pentru schimbările de UI), majoritatea interacțiunilor cu paginile web presupuneau încărcarea de pe server a unor pagini noi. Aplicațiile SPA permit interacțiunea dinamică (încarcă doar ceea ce este necesar), prevenind astfel întreruperile și, bineînțeles, oferind o experiență mai bună pentru utilizator.
Cererea cât mai mare a dus la probleme de conexiune. În modelul client-server tradițional, bazat pe threaduri limitate ca număr de către OS și ineficiente (vezi legea lui Amdahl) se ajunsese deja la maximul conexiunilor posibile.
O primă soluție la această problemă a oferit-o modelul Leaky Bucket (la nivel de network), mai apoi Reactor (servirea clienților în limitele posibile, implementată prin Nginx prin număr fix de workeri - un singur thread și pooling ciclic între procesele client) și versiunea asincronă - modelul Proactor.
O altă soluție se baza pe Websockets și modelul publish/subscribe.
Astfel s-a ajuns în 1999 la 10k conexiuni/secundă, iar în 2010 la 1M conexiuni (WhatsApp) și în 2015 la 10M-20M (MigratoryData).
Deschiderea spre un mediu global a însemnat și mai multe amenințări de securitate. Drept consecință, au apărut standarde noi și moduri de protecție inovate sau readaptate:
gateway - fie prin reverse proxy sau ca model implementat în cod;
headere speciale - Cross-site request forgery, Cross Site Scripting;
schimbări în cod - SQL Injection, ZIP Bomb, XML External Entity;
schimbări în CPU - NX bit.
schimbări în web server sau OS - Distributed denial of service attack (DDoS) gen HTTP Flood, UDP Flood, Ping of Death;
blacklisting/whitelisting;
autentificare (exemple - prin certificat, basic authentication, bearer, SSO, multi factor authentication);
Deoarece într-o organizație mare se ajungea la aceleași tipuri de servicii - de exemplu, mai multe departamente aveau nevoie pentru aplicația lor de un serviciu de conversie a valutei - s-a ajuns la nevoia de a avea un singur serviciu care să servească alte servicii și nu doar aplicații client.
Schimbul de date (în format HTML/XML/JSON/serializare obiecte sau alte formate) se obținea, de obicei, prin apeluri RPC/HTTP/REST/SOAP/WSDL/JMS.
Pentru că serviciile web serveau 24/7, mentenanța peste noapte nu mai era o opțiune, oprirea lor din cauza unor erori sau accidentală însemnând pierderi de bani.
Astfel a apărut necesitatea folosirii unor unelte gen watchdog care să verifice starea sistemului și în caz de probleme, să acționeze într-un mod predictibil. Cele mai simple erau cron jobs care verificau starea serviciilor (init.d). În unele cazuri un simplu restart nu mai era de ajuns, așa că au apărut soluții de high availability gen Linux-HA și Neverfail Heartbeat (dezvoltată și în Cluj-Napoca). Neverfail Heartbeat oferea posibilitatea de redundanță a serverelor și schimbarea serverului primar cu secundarul/terțiarul fără ca utilizatorul să observe o diferență (de exemplu, o interogare SQL începea pe un server/primar, iar alt server/secundar returna rezultatul). Pentru baze de date existau și alte soluții gen failover clustering.
Instalarea unei noi versiuni însemna, în cazul Java, încărcarea unui fișier war pe web server și rularea, de obicei manuală, a scripturilor SQL.
Aceasta însemna că serverul din producție trebuia oprit temporar. Pentru a avea o aplicație care să servească în continuare clienții, se opta fie pentru soluții de mai sus sau se folosea serverul de staging ca server de producție, iar după instalare se făcea schimbul din nou și migrarea datelor.
Acest tip de instalare se numește Blue-Green deployment. Pentru a oferi cât mai repede funcționalități noi unor grupuri de utilizatori, a apărut și noțiunea de canary deployment - instalare doar pentru anumite regiuni/utilizatori/grupuri.
Scalabilitatea a apărut ca necesitate, ca urmare a numărului din ce în ce mai mare de clienți. Scalabilitatea verticală se obținea prin creșterea capacității serverului (mai multe core-uri de CPU, memorie mai mare, etc.) și orizontal, prin folosirea de load balancer gen HAProxy cu o configurație statică (serverele erau adăugate manual, direct în fișierul de configurare sau se folosea o aplicație gen Puppet/Ansible pentru setarea configurării).
Uneori, aceeași bază de date era folosită în comun de mai multe procese - unele cu acces pentru citire, altele pentru citire/scriere.
Distributed Database Sharding (aceeași schemă, date diferite distribuite pe servere diferite) sau CQRS (baze de date separate pentru read și write care se sincronizează) rezolvă această problemă.
Scalabilitatea verticală era limitată, în mare parte, la capabilitățile aplicațiilor care rulau pe acel server. Creșterea performanțelor 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; modelul Horizontally Scaling Compute [29], fiind deja folosit, promitea o creștere mult mai mare a performanțelor, ca sistem și nu ca aplicație singulară. În acest fel a început migrarea în masă 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 în calitate de CQRS - vezi Queue-Centric Workflow [29]).
De asemenea, se observă trecerea cât mai mare de la centru de date propriu la cloud public.
... partea a doua a articolului va fi publicată în următoarea ediție a revistei Today Software Magazine, nr. 94 aprilie/2020
https://medium.com/threat-intel/cloud-computing-e5e746b282f5
https://www.eweek.com/innovation/cloud-2020-canonical-s-six-trends-shaping-the-future-of-cloud
https://www.gartner.com/smarterwithgartner/4-trends-impacting-cloud-adoption-in-2020/
https://medium.com/solo-io/https-medium-com-solo-io-supergloo-ff2aae1fb96f
https://imelgrat.me/cloud/cloud-services-models-help-business/
https://blog.back4app.com/2019/07/24/backend-as-a-service-baas/
https://www.enterpriseintegrationpatterns.com/patterns/conversation/LoadBalancer.html
https://www.toptal.com/software/trunk-based-development-git-flow
https://dzone.com/articles/event-driven-microservices-patterns
https://dzone.com/articles/microservices-quarkus-vs-spring-boot
https://imelgrat.me/cloud/cloud-services-models-help-business/
https://www.cloudflare.com/learning/serverless/serverless-vs-containers/
https://dzone.com/articles/the-future-of-spring-cloud-microservices-after-net
https://medium.com/@priyalwalpita/software-architecture-patterns-layered-architecture-a3b89b71a057
https://medium.com/@SoftwareDevelopmentCommunity/what-is-service-oriented-architecture-fa894d11a7ec
https://dzone.com/articles/monolith-to-microservices-using-the-strangler-patt
Working Effectively with Legacy Code by Michael Feathers
Patterns of Enterprise Application Architecture by Martin Fowler
cloud Native Development Patterns and Best Practices by John Gilbert
cloud Architecture Patterns by Bill Wilder
https://thenewstack.io/nats-rest-alternative-provides-messaging-distributed-systems/
https://thenewstack.io/10-key-attributes-of-cloud-native-applications/
https://www.confluent.io/blog/event-sourcing-cqrs-stream-processing-apache-kafka-whats-connection/
https://devops.com/feature-branching-vs-feature-flags-whats-right-tool-job/
https://cloud.spring.io/spring-cloud-netflix/multi/multi__modules_in_maintenance_mode.html
https://spring.io/blog/2019/03/14/lazy-initialization-in-spring-boot-2-2
https://kubernetes.io/docs/concepts/cluster-administration/federation/#why-federationc
https://docs.microsoft.com/en-us/azure/architecture/patterns/bulkhead
https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html
de Mihai Hulea , Bogdan Bustan