API-ul REST a fost un pilon de programare web pentru o lungă perioadă de timp. Dar recent gRPC a început să încalce teritoriul său. Se pare că există câteva motive foarte bune pentru asta. În acest tutorial, veți afla despre intrarea și ieșirea din gRPC și cum se compară cu REST.
Una dintre cele mai mari diferențe dintre REST și gRPC este formatul încărcăturii utile. Mesajele REST conțin în mod obișnuit JSON. Aceasta nu este o cerință strictă, iar teoretic poți trimite orice ca răspuns, dar în practică întregul ecosistem REST - inclusiv instrumente, cele mai bune practici și tutoriale - se concentrează pe JSON. Este sigur să spunem că, cu foarte puține excepții, API-urile REST acceptă și returnează JSON.
gRPC, pe de altă parte, acceptă și returnează mesajele Protobuf. Voi discuta despre tipărirea puternică mai târziu, dar doar din punct de vedere al performanței, Protobuf este un format foarte eficient și ambalat. JSON, pe de altă parte, este un format textual. Puteți comprima JSON, dar atunci pierdeți beneficiul unui format textual pe care îl puteți aștepta cu ușurință.
Să comparăm protocoalele de transfer pe care REST și gRPC le folosesc. REST, așa cum am menționat mai devreme, depinde în mare măsură de HTTP (de obicei HTTP 1.1) și de modelul de solicitare-răspuns. Pe de altă parte, gRPC utilizează protocolul HTTP / 2 mai recent.
Există câteva probleme care afectează HTTP 1.1 pe care HTTP / 2 le remediază. Iată câteva dintre cele mai importante.
HTTP 1.0 RFC 1945 este o RFC de 60 de pagini. HTTP 1.1 a fost descris inițial în RFC 2616, care a alimentat până la 176 de pagini. Cu toate acestea, ulterior IETF a împărțit-o în șase documente diferite - RFC 7230, 7231, 7232, 7233, 7234 și 7235 - cu un număr mai mare de pagini combinate. HTTP 1.1 permite multe părți opționale care contribuie la dimensiunea și complexitatea acestuia.
Tendința paginilor web este de a mări atât dimensiunea totală a paginii (1,9 MB în medie) cât și numărul de obiecte de pe pagină care necesită solicitări individuale. Deoarece fiecare obiect necesită o cerere separată HTTP, această multiplicare de obiecte separate crește semnificativ sarcina pe serverele web și încetinește timpul de încărcare a paginilor pentru utilizatori.
HTTP 1.1 este sensibil la latență. Este necesară o strângere de mână TCP pentru fiecare solicitare individuală, iar un număr mai mare de solicitări au o taxă semnificativă în timpul necesar pentru încărcarea unei pagini. Îmbunătățirea continuă a lățimii de bandă disponibile nu rezolvă aceste probleme de latență în majoritatea cazurilor.
Restricționarea numărului de conexiuni la același domeniu (folosit pentru a fi doar 2, astăzi 6-8) reduce în mod semnificativ capacitatea de a trimite mai multe solicitări în paralel.
Cu configurarea HTTP, puteți trimite o solicitare în așteptarea răspunsului la o cerere anterioară, creând în mod eficient o coadă. Dar asta introduce alte probleme. Dacă solicitarea dvs. rămâne blocată în spatele unei solicitări lente, timpul dvs. de răspuns va suferi.
Există alte preocupări, cum ar fi performanțele și sancțiunile de resurse atunci când comutarea liniilor. În prezent, configurarea HTTP nu este activată pe scară largă.
HTTP / 2, care a ieșit din SPDY-ul Google, menține premisele și paradigmele de bază ale HTTP:
http: //
și https: //
Schemele de adrese URLDar părțile opționale ale HTTP 1.1 au fost eliminate.
Pentru a aborda protocolul de negociere din cauza schemei de adrese URL partajate, există un antet de actualizare. De asemenea, aici este un șoc pentru dvs.: protocolul HTTP / 2 este binar! Dacă ați fost în jurul protocoalelor de internet atunci știți că protocoalele textuale sunt considerate rege, deoarece acestea sunt mai ușor pentru oameni pentru a depana și construi cererile manual. Dar, în practică, majoritatea serverelor de astăzi folosesc oricum criptarea și comprimarea. Cadrul binar merge mult spre reducerea complexității manipulării cadrelor în HTTP 1.1.
Cu toate acestea, îmbunătățirea majoră a HTTP / 2 este că utilizează fluxuri multiplexate. O singură conexiune HTTP / 2 TCP poate suporta multe fluxuri bidirecționale. Aceste fluxuri pot fi intercalate (fără așteptare), iar mai multe solicitări pot fi trimise în același timp, fără a fi nevoie să se stabilească noi conexiuni TCP pentru fiecare dintre acestea. În plus, serverele pot împinge acum notificări către clienți prin conexiunea stabilită (push HTTP / 2).
REST este un interesant API. Este construit foarte bine pe partea de sus a HTTP. Acesta nu folosește doar HTTP ca transport, ci cuprinde toate caracteristicile sale și construiește un cadru conceptual consistent pe lângă acesta. În teorie, sună minunat. În practică, a fost foarte dificilă implementarea corectă a REST.
Nu mă înțelege greșit - REST a fost și are mare succes, dar majoritatea implementărilor nu respectă pe deplin filozofia REST și utilizează doar un subset al principiilor sale. Motivul este că, de fapt, este destul de dificilă să cartografiați logica de afaceri și operațiunile în lumea REST strictă.
Modelul conceptual folosit de gRPC este acela de a avea servicii cu interfețe clare și mesaje structurate pentru cereri și răspunsuri. Acest model se traduce direct din concepte de limbaj de programare, cum ar fi interfețe, funcții, metode și structuri de date. Acesta permite, de asemenea, gRPC să genereze automat biblioteci de clienți pentru dvs..
REST acceptă numai modelul de cerere-răspuns disponibil în HTTP 1.x. Dar gRPC profită din plin de capacitățile HTTP / 2 și vă permite să transmiteți în mod constant informații. Există mai multe tipuri de streaming.
Serverul trimite un flux de răspunsuri după ce a primit un mesaj de solicitare client. După trimiterea tuturor răspunsurilor sale, detaliile de stare ale serverului și metadatele opționale de urmărire sunt trimise înapoi pentru a fi completate pe partea de server. Clientul completează odată ce are toate răspunsurile serverului.
Clientul trimite un flux de solicitări multiple către server. Serverul trimite un răspuns unic, de obicei, dar nu neapărat după ce a primit toate solicitările clientului, împreună cu detaliile de stare și metadatele opționale.
În acest scenariu, clientul și serverul trimit informații reciproc într-o formă destul de liberă (cu excepția faptului că clientul inițiază secvența). În cele din urmă, clientul închide conexiunea.
Paradigma REST nu mandatează nicio structură pentru sarcina utilă schimbată. Este de obicei JSON. Consumatorii nu dispun de un mecanism formal pentru a coordona formatul cererilor și răspunsurilor. JSON trebuie serializat și convertit în limbajul de programare țintă atât pe partea de server, cât și pe partea clientului. Serializarea este un alt pas în lanț care introduce posibilitatea erorilor, precum și a cheltuielilor de performanță.
Contractul de servicii gRPC a introdus mesaje puternice care sunt transformate automat din reprezentarea lor Protobuf în limbajul de programare ales atât pe server, cât și pe client.
JSON, pe de altă parte, este teoretic mai flexibilă deoarece puteți trimite date dinamice și nu trebuie să aderați la o structură rigidă.
Suportul pentru gRPC în browser nu este la fel de matur. Astăzi, gRPC este utilizat în principal pentru servicii interne care nu sunt expuse direct lumii.
Dacă doriți să consumați un serviciu gRPC dintr-o aplicație web sau dintr-o limbă care nu este acceptată de gRPC, atunci gRPC oferă un gateway REST API pentru a vă expune serviciul. Pluginul gateway-ului gRPC generează un server complet REST API cu o proiecție inversă și documentație Swagger.
Cu această abordare, pierdeți cele mai multe beneficii ale gRPC, dar dacă aveți nevoie să furnizați acces la un serviciu existent, puteți face acest lucru fără a vă implementa serviciul de două ori.
În lumea microservicii, gRPC va deveni dominantă foarte curând. Beneficiile de performanță și ușurința de dezvoltare sunt doar prea bune pentru a trece. Cu toate acestea, nu face nici o greșeală, REST va fi încă în jur pentru o lungă perioadă de timp. Ea încă excelează pentru API expuse public și pentru motive de compatibilitate înapoi.