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

E momentul să uitați de REST, pentru că gRPC este aici

Călin Bunea
Software Developer @ UIPath
PROGRAMARE

În ultimii trei ani și jumătate am avut șansa de a vizita frecvent un psiholog, ocazie cu care am reușit să înțeleg mai bine cum funcționează mintea umană, inclusiv a mea. Am învățat multe lucruri interesante despre modelele comportamentale pe care noi oamenii le avem și motivele din spatele acestor modele des întâlnite. Toate acestea au dus la o interacțiune mai bună cu oamenii din jurul meu.

Un lucru interesant pe care l-am învățat a fost acela că oamenii sunt de obicei rezistenți la schimbare. Acest lucru a devenit oarecum natural, deoarece de-a lungul evoluției noastre ca specie, orice schimbare majoră a mediului înconjurător era o adevărată amenințare pentru supraviețuire. Cu toate acestea, avem tendința de a uita că de fapt adaptabilitatea este cea mai mare calitate pe care o avem ca specie. Această calitate a jucat un rol crucial în supraviețuirea noastră ca specie până în ziua de azi.

Procesul decizional

Am vrut să expun această introducere din zona psihologiei evolutive, deoarece sunt convins că dacă mâine am întreba câțiva programatori:

"Dacă ai fi arhitectul unui proiect, ce tip de comunicare ai alege pentru aplicația de fațadă și micro serviciile din backend?"

Probabil că majoritatea ar răspunde REST fără să se gândească prea mult și fără să ceară informații adiționale. În opinia mea, nu există decizii arhitecturale "bune" sau "rele" ci doar decizii care vin cu "avantaje" și "dezavantaje". Cea mai mare provocare este -de fapt- aceea de a pune în balanță, într-un mod obiectiv, avantajele și dezavantaje bazate pe cerințele actuale. Pentru a acest lucru, eu gândesc în termeni de amortizare a investiției (ROI în limbă engleză). Trebuie să ne gândim cât timp adițional necesită o soluție față de cealaltă, care sunt potențialele beneficii aduse de fiecare soluție, și așa mai departe. Am auzit multă lume în jurul meu justificându-și alegerile prin prisma faptului că poate în viitor vor avea nevoie de funcționalitatea oferită de una dintre soluții.

Lumea în care trăim azi este într-o continuă schimbare produsă într-un ritm alert, drept urmare nu cred că este eficient să gândim astfel. Nu știm exact cum va arata viitorul, așa că nu are sens să investim mult timp în construcția unei mașini pregătită special pentru scenariul puțin probabil în care ar trebui să aselenizeze.

Detaliile tehnice din spatele cortinei

Revenind la REST, haideți să vedem care este, cu adevărat, problema? Discuția se învârte în jurul protocolului HTTP 1.1, folosit de obicei în comunicațiile de tip REST, la care se adaugă tipul de serializare a datelor, utilizând, de obicei, un serializator JSON. Conform Wikipedia, protocolul HTTP 1.1 a fost prima dată definit în anul 1997, în RFC 2068. Simplul fapt că un protocol de comunicare are o vechime de peste douăzeci de ani, nu ar trebui să fie un argument în alegerile tehnice pe care le facem. În schimb, viteza și cantitatea de resurse utilizate, ar trebui să fie luate în considerare atunci când cântărim opțiunile pe care le avem.

În rândurile următoare, realizăm o analiză sumară a modului cum funcționează protocolul HTTP 1.1. Clientul inițiază o conexiune TCP/IP cu serverul, de obicei pe portul 80 în cazul HTTP, respectiv 443 în cazul HTTP Securizat. Pentru inițializarea conexiunii TCP/IP există inițial un schimb de mesaje "syn" între client și server, în vederea confirmării conexiunii, schimb de mesaje care necesită timp. După ce conexiunea este stabilită, clientul poate să trimită o singură cerere către server, fiind apoi nevoit să aștepte răspunsul de la server înainte de a trimite următoarea cerere. Așadar, în perioada în care clientul așteaptă răspunsul de la server, conexiunea existentă nu poate fi (re)folosită pentru a transmite o altă cerere. E drept că, din punct de vedere tehnic, clientul poate să trimită mai multe cereri consecutive în cadrul unei conexiuni, fără să aștepte neapărat răspunsul de la server, dar serverul este obligat să răspundă cererilor în ordinea în care ele au fost trimise. Drept urmare, nu există un beneficiu real în a folosi această tehnică. În timp ce așteaptă un răspuns, clientul trebuie să inițializeze o nouă conexiune cu serverul de fiecare dată când dorește să facă o nouă cerere și deci, să treacă prin procesul inițial de schimb de mesaje de tip "syn".

Ar mai fi de menționat faptul că fiecare socket aferent unei conexiuni are nevoie de memorie alocată pentru bufferul de trimitere a datelor, memorie pentru bufferul de recepționare a datelor, un identificator prin care Sistemul de Operare să poată să gestioneze acel socket, informații despre conexiune cum ar fi IP-ul serverului, portul și așa mai departe. Ținând cont de faptul că în ziua de azi există telefoane mobile care au 12 GB memorie RAM, cantitatea de resurse/memorie folosită de către un socket este nesemnificativă. Dar ce se întâmplă atunci când pentru aplicația noastră web avem în spate zece microservicii cu care trebuie să comunicăm pentru fiecare cerere care vine de la un browser client? În cazul în care se folosește HTTP 1.1, aplicația noastră web e nevoită să deschidă în total zece conexiuni cu microserviciile din spate pentru a putea servi o cerere venită de la un client browser. În cazul în care există 500 de cerere simultane de la clienți browser, făcând un calcul matematic simplu, ajungem la concluzia că aplicația noastră web va avea 5000 conexiuni deschise cu microserviciile din spate, la care se adaugă încă 500 conexiuni cu clienții browser. În sistemul de operare Windows (sau în cazul aplicațiilor web din cloud-ul Azure), cel mai probabil aplicația noastră web va fi terminată de către sistemul de operare datorită atingerii limitei de 5000 de socketuri folosite. În plus, trebuie să adăugăm și timpul petrecut de către aplicația web pentru stabilirea conexiunilor (schimbul inițial de mesaje "syn").

Sursa: https://medium.com/@EmperorRXF/evaluating-performance-of-rest-vs-grpc-1b8bdf0b22da

Soluția pentru problema enunțată mai sus este să se facă multiplexarea cererilor folosind o singură conexiune TCP/IP. Folosind protocolul HTTP 2.0, această facilitate ne este oferită automat. În cadrul HTTP 2.0, mai multe cereri pot fi transmise către server folosind o singură conexiune, fără să fie nevoie să se aștepte un răspuns după fiecare cerere. Astfel, clientul va trimite mai multe cereri către server, iar acesta va răspunde în ordinea în care termină de procesat fiecare cerere. În momentul în care clientul primește un răspuns de la server, acel răspuns conține informații cu privire la cererea pentru care s-a transmis răspunsul. Deducem astfel că e cererea căreia îi aparține răspunsul, semnalând mai departe în aplicație faptul că răspunsul de la server a ajuns pentru cererea X.

Trebuie reținut faptul că din punct de vedere hardware, există un singur canal fizic pentru transmiterea datelor și un singur canal pentru recepționare. Prin urmare, dacă avem mai multe conexiuni deschise simultan cu un server, nu înseamnă că vom avea o viteză mai mare de transfer pe rețea a datelor, deoarece datele se trimit fizic bit cu bit. Atunci când există mai multe conexiuni, kernelul sistemului de operare împreună cu driverul, se ocupă de sincronizarea accesului la canalul fizic de transmisie/recepție a datelor.

Rapid, mai rapid, cel mai rapid

Motivul principal pentru care gRPC este mai rapid decât REST este dat de faptul că gRPC funcționează valorificând protocolul HTTP 2.0, pe când REST folosește în majoritatea cazurilor protocolul HTTP 1.1.

Un alt beneficiu oferit de gRPC este dat de serializatorul protobuf care este mai rapid decât orice alt serializator JSON/XML.

Probabil că în acest moment vă întrebați cum rămâne cu compatibilitatea între mai multe platforme și/sau limbaje de programare, compatibilitate care este oferită în mod tradițional de REST. Nu este cazul să vă faceți griji, deoarece gRPC oferă posibilitatea definirii unui fișier manifest, pe baza căruia se poate genera cu ajutorul unui utilitar, cod specific limbajului de programare dorit. Acel cod conține clasele proxy care facilitează interacțiunea cu serverul gRPC.

Un alt avantaj major la gRPC pe care aș dori să-l menționez este funcționalitatea de streaming. Desigur, funcționalitatea de streaming poate fi implementată și în comunicarea de tip REST, doar că implică muncă extra și cel mai probabil va fi nevoie să se intervină în componența care efectuează serializarea/deserializarea.

O veste bună este că gRPC este suportat deja în AKS (Azure Kubernetes Services). Așa că acei care utilizează sau plănuiesc să utilizeze în viitor infrastructura Azure Kubernetes, vor fi plăcut surprinși de faptul că pot să configureze cu ușurință politicile de failover și load balancing pentru gRPC în infrastructura AKS.

Concluzii

În încheiere, aș dori să menționez faptul că nu putem afirma că este bine sau rău să folosim gRPC în loc de REST sau invers, dar putem, totuși, spune că este greșit să folosim o tehnologie doar pentru că este azi în tendințe sau pentru că este mai populară decât cealaltă. În cele din urmă, trebuie să puneți în balanță cele doua opțiuni și să luați decizia care oferă cele mai multe avantaje din punct de vedere al returnării investiției (ROI) pentru problema pe care o aveți de rezolvat.

Nu trebuie să fii un adept al tendințelor, încearcă să fii un inovator.

LANSAREA NUMĂRULUI 90

Prezentări articole și
Panel: Mobility Services

Miercuri, 11 Decembrie, ora 18:00
sediul Accenture

Înregistrează-te

Facebook Meetup

Sponsori

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