Najino izkušnje pri ustvarjanju API Gateway

Nekatere podjetja, vključno z našim naročnikom, razvijajo izdelek prek partnerske mreže. Na primer, veliki spletni trgovci so integrirani s storitvijo dostave — naročite izdelek in kmalu prejmete številko za sledenje paketu. Drug primer — skupaj z letalsko vozovnico kupite zavarovanje ali vozovnico za letališki ekspres.

Za to se uporablja en API, ki ga je treba izdati partnerjem prek API Gateway. To nalogo smo rešili. V tem članku bomo podali podrobnosti.

Dano: ekosistem in API portal z vmesnikom, kjer so uporabniki registrirani, prejemajo informacije itd. Moramo ustvariti udoben in zanesljiv API Gateway. Med postopkom smo morali zagotoviti

  • registracijo,
  • nadzor nad povezavo z API,
  • monitoring, kako uporabniki uporabljajo končni sistem,
  • računanje poslovnih kazalnikov.

Najino izkušnje pri ustvarjanju API Gateway

V članku bomo govorili o našem načinu ustvarjanja API Gateway, pri čemer smo reševali naslednje naloge:

  • avtentifikacija uporabnika,
  • avtorizacija uporabnika,
  • modifikacija izvirnega zahtevka,
  • posredovanje zahtevka,
  • obdelava odgovora.


Obstajata dve vrsti upravljanja API:

1. Standardno, ki deluje takole. Pred povezovanjem uporabnik testira zmožnosti, nato plača in integrira na svojo spletno stran. Najpogosteje ga uporabljajo v malem in srednjem podjetništvu.

2. Veliko B2B API Management, kjer podjetje najprej sprejme poslovno odločitev o povezavi, postane partner podjetja s pogodbenimi obveznostmi, nato se poveže z API. In šele po urednih formalnostih podjetje pridobi testni dostop, opravi testiranje in preide v produkcijo. Vendar to ni mogoče brez upravljalske odločitve o povezavi.

Najino izkušnje pri ustvarjanju API Gateway

Naša rešitev

V tem delu bomo govorili o ustvarjanju API Gateway.

Končni uporabniki ustvarjenega API Gateway-a so partnerji našega naročnika. Za vsakega od njih že hranimo potrebne pogodbe. Potrebno bo le razširiti funkcionalnosti, ob tem pa označiti dodeljen dostop do gateway-a. Zato je potreben kontroliran proces povezovanja in upravljanja.

Seveda bi bilo mogoče uporabiti kakšno pripravljeno rešitev za nalogo upravljanja API in ustvarjanje API Gateway. Na primer, takšna bi lahko bila Azure API Management. Ni nam ni odgovaralo, jer smo već imali API portal i ogromni ekosistem izgrađen oko njega. Svi korisnici su već bili registrovani, znali su gde i kako mogu da dobiju potrebne informacije. U API portalu su već postojali potrebni interfejsi, samo nam je bio potreban API Gateway. Sotv, njime smo se i bavili.

Ono što nazivamo API Gateway — svojevrsni je proxy. Ponovo smo imali izbor — možemo napisati svoj proxy ili odabrati nešto već postojeće. U ovom slučaju, otišli smo drugim putem i izabrali kombinaciju nginx+Lua. Zašto? Bio nam je potreban pouzdan, testiran softver koji podržava skalabilnost. Nismo želeli nakon implementacije da proveravamo i tačnost poslovne logike i funkcionalnost proxy-a.

Svaki veb server ima proces obrade zahteva. U slučaju nginx-a, izgleda ovako:

Najino izkušnje pri ustvarjanju API Gateway

(shema iz GitHub Lua Nginx)

Naš cilj je bio da se uklopimo u ovaj proces u onom trenutku kada možemo da modifikujemo izvorni zahtev.

Želimo da stvorimo transparentni proxy, tako da funkcionalno zahtev ostane onakav kakav je i došao. Mi samo kontrolišemo pristup krajnjem API-ju, pomažemo zahtevu da do njega stigne. U slučaju da je zahtev bio neispravan, grešku bi trebao prikazati krajnji API, a ne mi. Jedini razlog zašto možemo odbiti zahtev — zbog nedostatka pristupa klijenta.

Za nginx već postoji razširitev na Lua. Lua — je skriptni jezik, veoma je lagan i lako se uči. Tako smo potrebnu logiku realizovali pomoću Lua.

Konfiguracija nginx-a (analogija rute aplikacije), gde se obavlja sav posao, prilično je jasna. Posebna je poslednja direktiva — post_action.

location /middleware {
      more_clear_input_headers Accept-Encoding;
      lua_need_request_body on;
      rewrite_by_lua_file 'middleware/rewrite.lua';
      access_by_lua_file 'middleware/access.lua';
      proxy_pass https://someurl.com;
      body_filter_by_lua_file 'middleware/body_filter.lua';
      post_action /process_session;
}

Pogledajmo šta se dešava u ovoj konfiguraciji:
more_clear_input_headers — čisti vrednost navedenih nakon direktive headera.
lua_need_request_body — reguliše da li treba da pročita izvorno telo zahteva pre nego što izvrši rewrite/access/access_by_lua direktive ili ne. Podrazumevano nginx ne čita telo zahteva klijenta, i ako vam je potrebno da mu pristupite, ova direktiva treba da ima vrednost on.
rewrite_by_lua_file — pot do skripte, v katerem je opisana logika za modifikacijo poizvedbe
access_by_lua_file — pot do skripte, v katerem je opisana logika, ki preverja dostop do vira.
proxy_pass — url, na katerega bo posredovana poizvedba.
body_filter_by_lua_file — pot do skripte, v katerem je opisana logika za filtriranje poizvedbe pred vračanjem stranki.
In, končno, post_action — uradno nedokumentirana direktiva, s pomočjo katere lahko izvedemo še nekatere druge akcije po tem, ko je odgovor dan stranki.

Nato bomo po vrsti opisali, kako smo reševali svoje naloge.

Avtorizacija/audit in modifikacija poizvedbe

Avtorizacija

Avtorizacijo in avtentifikacijo smo zgradili s pomočjo dostopov na podlagi certifikata. Obstaja korenski certifikat. Vsakemu novemu naročniku naročnika se ustvari njegov osebni certifikat, s katerim lahko dostopa do API. Ta certifikat se nastavi v razdelku server nastavitev nginx.

ssl on;
ssl_certificate /usr/local/openresty/nginx/ssl/cert.pem;
ssl_certificate_key /usr/local/openresty/nginx/ssl/cert.pem;
ssl_client_certificate /usr/local/openresty/nginx/ssl/ca.crt;
ssl_verify_client on;

Modifikacija

Lahko se postavi upravičeno vprašanje: kaj storiti s certificiranim strankam, če nenadoma želimo onemogočiti dostop do sistema? Ne moremo ponovno izdajati certifikatov za vse ostale stranke.

Tako smo gladko prešli na naslednjo nalogo — modifikacijo izvorne poizvedbe. Izvorna poizvedba stranke ni veljavna za končni sistem. Ena od nalog je dodati manjkajoče dele v poizvedbo, da postane veljavna. Čar je v tem, da so manjkajoči podatki različni za vsako stranko. Vemo, da k nam pride stranka s certifikatom, iz katerega lahko vzamemo odtis in potegnemo potrebne podatke o stranki iz baze.

Če bomo v nekem trenutku potrebovali onemogočiti stranko iz naše storitve, bodo njeni podatki izginili iz baze in ne bo mogla ničesar storiti.

Delo s podatki stranke

Morali smo zagotoviti visoko razpoložljivost rešitve, zlasti glede načina pridobivanja podatkov strank. Težava je v tem, da je izvor teh podatkov zunanja storitev, ki ne zagotavlja nemotenega in dovolj visoke hitrosti delovanja.

Zato smo morali zagotoviti visoko razpoložljivost podatkov strank. Kot orodje smo izbrali Hazelcast, ki nam nudi:

  • hitri dostop do podatkov,
  • možnost organizacije gruče več vozlišč z replikiranimi podatki na različnih vozliščih.

Izbrali smo najpreprostejšo strategijo dostave podatkov v predpomnilnik:

Najino izkušnje pri ustvarjanju API Gateway

Delo z končnim sistemom poteka v okviru sej in obstaja omejitev na največje število. Če stranka ne zapre seje, moramo to narediti mi.

Podatki o odprti seji prihajajo od končnega sistema in se prvotno obdelujejo na strani Lua. Odločili smo se uporabiti Hazelcast za shranjevanje teh podatkov s pomočjo opravila, napisanega v .NET. Nato občasno preverjamo pravico do življenja odprtih sej in zapiramo potekle.

Dostop do Hazelcasta tako iz Lua kot iz .NET

Strank za Lua za delo z Hazelcastom ni, vendar Hazelcast ponuja REST API, ki ga nameravamo uporabiti. Za .NET pa imamo stranko, prek katere smo načrtovali dostop do podatkov Hazelcast na strani .NET. Ampak ni šlo po načrtih.

Najino izkušnje pri ustvarjanju API Gateway

Pri shranjevanju podatkov prek REST in pridobivanju prek .NET stranke se uporabljajo različni serializerji in deserializerji. Zato ni mogoče shraniti podatkov prek REST, jih pa pridobiti prek .NET stranke in obratno.

Če bodo zainteresirani, bomo podrobneje predstavili to težavo v ločenem članku. Spoiler — na shemi.

Najino izkušnje pri ustvarjanju API Gateway

Dnevnik in ogledovanje

Naš korporativni standard za dnevnikovaje prek .NET — Serilog, vsi dnevniki na koncu pridejo v Elasticsearch, njihovo analizo pa izvajamo prek Kibanе. Nekaj podobnega smo želeli doseči tudi v tem primeru. Edina stranko stranka za delo z Elasticom na Lua, ki je bila najdena, se je porušila takoj pri prvem require. In uporabili smo Fluentd.

Fluentd — je odprtokodna rešitev za zagotavljanje enotnega sloja dnevnikov aplikacije. Omogoča zbiranje dnevnikov z različnih slojev aplikacije in njihovo prenos v enoten vir.

API Gateway deluje v K8S, zato smo se odločili dodati kontejner s fluentd v isto pod, da bi pisali dnevnike na obstoječem odprtem tcp portu fluentd.

Raziskali smo tudi, kako se bo fluentd obnašal, če ne bo imel povezave z Elasticsearchom. Čez dva dni so v vrata neprekinjeno prihajali zahtevki, v fluentd so se pošiljali dnevniki, vendar je imel fluentd IP Elastica blokiran. Po obnovitvi povezave je fluentd brez težav prenesel vse dnevnike v Elastic.

Zaključek

Izbrani pristop k implementaciji nam je omogočil, da smo dostavili dejansko delujoč izdelek v produkcijsko okolje v samo 2.5 mesecih.

Če se kdaj ukvarjate s podobnimi stvarmi, priporočamo, da najprej jasno razumete, katero nalogo želite rešiti in katere vire že imate na voljo. Bodite pozorni na zapletenost integracije z obstoječimi sistemi za upravljanje API.

Razumite, kaj točno nameravate razviti — samo poslovno logiko obdelave zahtevkov ali, kot je bilo v našem primeru, celoten proxy. Ne pozabite, da mora biti vse, kar sami razvijete, pozneje temeljito testirano.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster