de Suhas Chatekar

Cum să echilibrați chunkiness-ul atunci când vă proiectați API-ul REST

Cum sa echilibrati chunkiness ul atunci cand va proiectati API ul REST

Una dintre provocările de a construi orice API este că nu știți cine va folosi API-ul dvs. sau cum îl vor folosi.

Este posibil să aveți un consumator intern care vă apelează API-ul printr-o conexiune LAN. Acestui consumator nu i-ar păsa să facă răspunsuri masive API (gros) sau să efectueze mai multe apeluri API pentru a obține toate bucățile de date pe care le doresc (vorbărețe).

Sau este posibil să aveți un consumator extern care să se conecteze prin internet. Acest consumator ar dori să efectueze un număr mic de apeluri de rețea. Astfel de consumatori doresc, de asemenea, ca API să returneze doar suficiente date.

Cum sa echilibrati chunkiness ul atunci cand va proiectati API ul REST

Consumatorii care se conectează dintr-o rețea mobilă sunt deosebit de interesați de apelurile de rețea. Pentru ei, apelurile de rețea determină taxe de la operator pentru utilizatorii lor. Cantitatea mare de date returnate de API-uri nu este ideală pentru acestea, deoarece poate duce la utilizarea multă baterie în timpul procesării.

În calitate de dezvoltator API, nu trebuie să decideți dacă API-ul dvs. trebuie să fie vorbăreț, gros sau nu. Consumatorii API-ului dvs. vor să decidă acest lucru. Adevărul este că majoritatea API-urilor au consumatori din ambele tabere. Deci, cum faceți față acestor cereri? Răspunsul ușor este oferind mai multă putere consumatorilor API-urilor dvs. Lăsați consumatorii să fie pe scaunul conducătorului auto și lăsați-i să spună API-ului dvs. ce vor.

În acest articol, voi vorbi despre trei tehnici care vă permit să faceți acest lucru.

Tehnica nr. 1: Utilizați Lazy Get pentru a controla dimensiunea sarcinii dvs. utile

Majoritatea instrumentelor Object Relational Mapper (ORM) au o caracteristică numită Lazy Loading. ORM-urile folosesc această caracteristică pentru a returna doar entitatea de nivel superior atunci când execută un script SQL. Orice entități asociate nu sunt încărcate complet, ci doar identificatorii lor sunt încărcați. Când aplicația încearcă să acceseze entitatea asociată, ORM începe. Încarcă acea entitate folosind identificatorul pe care îl încărcase anterior. Acest lucru este inteligent, deoarece ORM nu presupune când aplicația are nevoie de ce. În schimb, oferă aplicației posibilitatea de a prelua la cerere ceea ce este necesar când.

Lazy Get este similar. Cu Lazy Get, nu returnați în mod implicit o resursă legată. În schimb, întoarceți o versiune superficială cu numai atribute de nivel superior populate. Consumatorul API poate

  1. Instruiți serverul să returneze resursele legate în același răspuns
  2. Recuperați resursele conectate ulterior folosind linkul returnat în răspunsul original

Acest lucru este cel mai bine explicat cu un exemplu. Să presupunem că construim o platformă de întâlnire. Oamenii pot crea grupuri de interese și găzdui întâlniri utilizând platforma noastră. Membrii platformei pot

  1. Alăturați-vă grupurilor care le plac
  2. Conectați-vă cu alți membri ai platformei
  3. RSVP pentru evenimentele găzduite de diferite grupuri

Acesta este un set de caracteristici de bază pe care le poate avea orice platformă de întâlnire.

Această platformă este activată API și avem o metodă API pentru a prelua un member resursă care arată ca mai jos.

Pentru scurtă durată, codul de mai sus nu arată reprezentarea completă a memberships, rsvps și friends resurse. În realitate, aceste resurse vor avea mai multe atribute decât ceea ce arăt aici. Ar putea chiar să aibă propriile resurse legate.

Este posibil ca un consumator al acestui API să nu aibă nevoie de toate aceste date tot timpul. Un consumator care se conectează prin LAN ar accepta cu bucurie o mulțime de date returnate. Dar un dezvoltator de aplicații mobile care se conectează printr-o conexiune lentă la internet nu ar dori acest lucru. Ghici ce? Puteți implementa Lazy Get pe această metodă API și lăsați consumatorul să decidă ce date doresc să fie returnate. Faceți acest lucru acceptând un nou parametru de interogare numit expand. Acest parametru acceptă nume separate de virgule ale resurselor legate pe care consumatorul dorește să le returneze serverul. De exemplu, dacă URL-ul pentru recuperarea resursei membre de mai sus a fost

https://myapi.com/v1/member/34234

Dacă un consumator dorește să se returneze doar informații despre abonament, atunci acesta poate trimite o cerere la următoarea adresă URL

https://myapi.com/v1/member/34234?expand=memberships

Este bun. Acum, consumatorul are un control asupra a ceea ce returnează serverul de date. Dar ce se întâmplă cu alte resurse, adică rsvps și friends? Serverul îi va exclude doar din răspuns? Dacă serverul le exclude, cum obține consumatorul resursele respective atunci când are nevoie de ele?

În schimb, ceea ce face serverul este exact același cu ceea ce face orice ORM cu funcția sa de încărcare leneșă. Serverul returnează un identificator al resursei în locul resursei complete.

În acest fel, dacă consumatorul decide să aducă rsvps sau friends resurse, tot ce trebuie să facă este să emită o solicitare GET pe adresele URL corespunzătoare.

Folosind hipermedia pentru a îmbunătăți acest lucru

În exemplul anterior, cum ar putea un client să preia un friend resursă cu ID 5678? De unde ar obține adresa URL reală pentru a prelua această resursă? Putem folosi hipermedia să ne ajute aici. Dacă ați folosit hipermedia anterior, este posibil să fi ghicit despre ce vorbesc.

Puteți utiliza una dintre specificațiile hipermedia cum ar fi Sirenă, HAL sau Colecție + JSON pentru a returna adresa URL reală pentru resursă în loc doar de id. Dacă sunteți încă la Modelul de maturitate Richardson – Nivelul 2 sau inferior, nu-ți face griji. Puteți face ceea ce am făcut noi în astfel de cazuri. Nu returnăm identificatorul resursei conectate. Pentru clienții externi, nu înseamnă nimic. În schimb, returnăm un atribut href. Acest atribut conține adresa URL pe care clienții pot trimite o solicitare GET pentru a prelua resursa respectivă. Mai jos este modul nostru member resursa arată cu href atribut returnat.

Și returnăm acest atribut în mod implicit pentru toate resursele noastre.

Tehnica # 2: utilizați o metodă API hash pentru a deveni mai puțin vorbăreți

Lazy Get este bun pentru a controla dimensiunea sarcinii utile a răspunsului. Nu ar fi bine să nu trebuiască să apeleze acel API din nou și din nou? Este, dacă consumatorul ascunde în cache răspunsul primit.

Un neajuns evident al memorării în cache este că nu ați ști când memoria cache devine depășită. Serverul poate returna informații de expirare cache în antetele de răspuns. Consumatorul poate elimina memoria cache pe baza acestor informații. Dar tot ce faceți aici este mutarea problemei de la client la server. Serverul încă ghicește care este ultima dată până la care trebuie să expire memoria cache. Și mai rău este că majoritatea implementărilor ar seta aceasta la o valoare implicită.

Metoda Hash API oferă o alternativă pentru aplicațiile care

  1. Nu se poate baza pe cache, deoarece trebuie întotdeauna să lucreze la o copie nouă a datelor
  2. Nu pot efectua apeluri API frecvente și grele din cauza mediului în care operează în aplicații mobile.

O implementare a metodei Hash API va avea următoarele

  1. Fiecare resursă care trebuie să accepte o metodă API Hash trebuie să includă un atribut hash
  2. Valoarea este a acestui atribut este hashul reprezentării șirului (JSON / XML) a resursei
  3. Serverul recalculează hash-ul de fiecare dată când se schimbă starea resursei.
  4. O nouă metodă API pentru a returna cea mai recentă valoare hash pentru fiecare resursă

Să presupunem că vrem să acceptăm metoda API hash pentru resursa membru din exemplul nostru anterior. Deci, mai întâi adăugăm un atribut hash ca mai jos

Serverul folosește un mecanism la alegere pentru a calcula valoarea atributului hash. Ar putea fi, de asemenea, un șir aleatoriu. Serverul trebuie să-și actualizeze valoarea de fiecare dată când se schimbă starea resursei.

Apoi, adăugăm următoarea nouă metodă API care returnează cea mai recentă valoare hash pentru resursa membru

https://myapi.com/v1/member/{memberid}/hash

Această metodă API returnează un răspuns cu starea de 200 OK. Corpul de răspuns conține valoarea atributului hash al resursei membre. Cheia aici este de a face acest API cât mai rapid posibil. Serverul poate memora în cache o hartă a ID-ului resursei și a valorii hash pentru a reduce timpul de răspuns.

Tot ce trebuie să facă acum un consumator conștient de lățimea de bandă este să apeleze la Metoda Hash API. Apoi poate compara valoarea hash returnată cu valoarea hash pe care o are din recuperarea anterioară a resursei. Dacă valorile hash sunt aceleași, atunci este sigur să presupunem că resursa nu s-a schimbat de la ultima recuperare a consumatorului. Dacă valorile hash sunt diferite, atunci este timpul să preluați cea mai recentă valoare a resursei.

Menținerea hash-ului actualizat tot timpul

Pe măsură ce tot mai mulți consumatori încep să folosească hash API Method, devine important să ne asigurăm că hash-urile sunt întotdeauna actualizate. Acest lucru necesită o gândire adecvată și un design optim. Luați în considerare următoarele situații

  1. Când o resursă este actualizată parțial / complet, hash-ul trebuie actualizat
  2. Dacă hashul include resursele legate, de fiecare dată când o resursă este actualizată, toate celelalte resurse care leagă această resursă trebuie să-și actualizeze hash-ul.
  3. Când o resursă este ștearsă, metoda hash pentru resursa respectivă trebuie să returneze un 404 Not Found și fiecare aplicație de consum ar trebui să gestioneze acest răspuns pentru a șterge copia cache a resursei

Dacă decideți să utilizați metoda API Hash, gândiți-vă la aceste situații din ziua 1. Gestionarea acestor situații ca o gândire ulterioară poate fi costisitoare.

Tehnica nr. 3: Utilizați GraphQL pentru a obține exact ceea ce aveți nevoie

GraphQL este un proiect Facebook Open Source. A început ca o idee în urmă cu câțiva ani, dar a progresat într-o specificație bine definită acum. Există o mână de biblioteci pentru platforma majoră de programare care acceptă GraphQL. Conform Site-ul GraphQL:

„GraphQL este un limbaj de interogare pentru API-uri și un timp de execuție pentru îndeplinirea acelor interogări cu datele dvs. existente. GraphQL oferă o descriere completă și ușor de înțeles a datelor din API-ul dvs., oferă clienților puterea de a cere exact ceea ce au nevoie și nimic mai mult, facilitează evoluția API-urilor în timp și permite instrumente puternice pentru dezvoltatori.

Acest lucru arată similar cu Lazy Get, dar în realitate, este chiar mai puternic decât atât. Vom vedea într-un pic cum. De asemenea, GraphQL facilitează acceptarea Metodei Hash API fără a fi nevoie să adăugați un punct final special. Înainte de a intra în aceste detalii, să analizăm un exemplu rapid de ceea ce oferă GraphQL.

Dacă un consumator API are nevoie de o copie superficială a resursei membre fără resurse legate, atunci ar trebui să trimită interogarea GraphQL de mai jos

Să ignorăm câteva detalii precum adresa URL de destinație pentru această interogare și gestionarea interogării pe server. Această interogare returnează atributele specificate ale resursei membre cu id 34342.

Dacă un alt consumator dorește numai firstname și lastname apoi specifică aceste două atribute în interogarea lor. Serverul va returna aceste atribute. Vedeți cât de puternic poate fi acest lucru. Cu Lazy Get, veți obține toate resursele legate complet hidratate sau niciuna. Dar nu a fost posibil să se elimine unele atribute.

Abilitatea GraphQL de a specifica exact ce atribute dorim să fie returnate, ne permite să acceptăm Hash API Method din cutie. Un consumator care dorește să obțină cea mai recentă valoare a hashului resursei membre din exemplul de mai sus ar trimite doar interogarea de mai jos

Amintiți-vă, este încă același punct final API pe server care gestionează aceste interogări. Acest lucru oferă un control foarte granular consumatorilor API. Consumatorii se pot echilibra între răspunsurile grosiere și apelurile API vorbitoare de unul singur.

Un lucru demn de menționat este performanța metodei Hash API folosind GraphQL. O premisă esențială a metodei API Hash este că trebuie să revină cât mai repede posibil. Dacă avem propria noastră implementare a Metodei Hash API, atunci avem un control total pentru a face orice reglaj fin de care avem nevoie. Cu GraphQL, suntem limitați de ceea ce oferă biblioteca GraphQL pe care o folosim. Dacă utilizați versiunea GraphQL a metodei Hash API, asigurați-vă că performanța este optimizată pentru cazul de utilizare.

GraphQL se referă la a da control consumatorilor API-ului dvs.

Am arătat două exemple simple despre ceea ce este posibil cu GraphQL. Dar GraphQL nu se limitează la interogări simple. Poti sa faci

  1. Specificați filtre suplimentare pentru atribute precum primele 10, ultimele 30 sau conține
  2. Specificați filtre pentru mai multe atribute
  3. Grupul a returnat de obicei atribute în fragmente
  4. Validarea interogării
  5. Parametrează interogările folosind variabile
  6. Modificarea dinamică a comportamentului interogării folosind directivelor
  7. Mutații de date după preluare

Un API care acceptă pe deplin GraphQL, oferă consumatorului control total asupra datelor pe care le preluează în ce moment.

Happy API consumer == Happy API developer == Great API

Una dintre modalitățile de a oferi o bună experiență dezvoltatorului este de a le oferi un anumit control asupra API-urilor cu care interacționează. Lazy Get, Hash API Method și GraphQL oferă un mecanism prin care dezvoltatorii API pot oferi acel control consumatorilor lor.

☞ Dacă îți place articolul meu, te rog nu uitați să faceți clic pe ❤ pentru a recomanda altora.

De asemenea, pentru a fi informat despre noile mele articole și povești, urmează-mă Mediu și Stare de nervozitate. Mă puteți găsi pe LinkedIn de asemenea. Noroc!

De ce ar trebui să utilizați metode HTTP standard în timp ce proiectați API-urile REST?
Una dintre caracteristicile unui API REST bun este că folosește metodele HTTP standard într-un mod în care ar trebui să …medium.comVizualizarea API-urilor complexe folosind API Map
O imagine merită o mie de cuvinte …medium.com