Mikroservisni gateway: od poređenja do izbora, od teorije do prakse
Priredio: Chenmo Wang Er, pogledajte link za preštampavanje, autor: Lou Zai, pogledajte originalni link.
Mikroservisi su poslednjih godina veoma popularni, a tehnički ekosistem koji ih okružuje je prilično bogat — tu su mikroservisni gateway, Docker, Kubernetes i slično.
Počeo sam da se bavim mikroservisnim gateway-om 2019. godine, kada sam sa jednim kolegom iz kompanije razvijao takav sistem. Zbog ograničenih tehničkih sposobnosti, bio sam zadužen samo za pozadinski deo gateway-a, i zapravo nisam učestvovao u kasnijim iteracijama. Međutim, kasnije sam u slobodno vreme pregledao kod za prednji deo gateway-a, tako da principi implementacije ovog mikroservisnog gateway-a smatram da sam u osnovi savladao.
Ovih dana pišem članke vezane za tehnološki stek i baš sam stigao do mikroservisnog gateway-a, pa sam odlučio da jednostavno sumiram prethodno stečeno znanje. Istovremeno sam pregledao uobičajene mikroservisne gateway-e dostupne na tržištu — delimično radi lakšeg budućeg izbora tehnologije, a delimično kao svojevrsno personalno poređenje. Ispod je sadržaj članka:

Osnove API gateway-a
Šta je API gateway
API gateway je server, odnosno jedinstveni ulaz u sistem. Sa stanovišta objektno-orijentisanog dizajna, sličan je Facade (Front) obrascu.
API gateway enkapsulira internu arhitekturu sistema i pruža prilagođeni API za svakog klijenta. Može imati i druge odgovornosti, kao što su autentifikacija, nadzor, balansiranje opterećenja, keširanje, konverzija protokola, ograničavanje protoka i prekid kola (rate limiting i circuit breaking), obrada statičkih odgovora.
Ključna tačka pristupa API gateway-a je da svi klijenti i potrošači pristupaju mikroservisima putem jednog objedinjenog gateway-a, pri čemu se sve ne-poslovne funkcije obrađuju na nivou gateway-a. Obično gateway takođe pruža REST/HTTP API pristup.
Glavne funkcije gateway-a
Mikroservisni gateway, kao jedinstveni ulaz za pozadinske mikroservise, može objedinjeno upravljati pozadinskim servisima. Glavna podela je na ravan podataka i kontrolnu ravan:
- Glavna funkcija ravni podataka je prihvatanje HTTP zahteva korisnika i agregacija razdvojenih mikroservisa. Mikroservisni gateway objedinjeno izlaže API i ugovore pozadinskih servisa, pri čemu su funkcije rutiranja i filtriranja osnovni moduli gateway-a. Pored toga, mikroservisni gateway može implementirati mehanizme presretanja i fokusirati se na poprečne (cross-cutting) funkcije, uključujući konverziju protokola, bezbednosnu autentifikaciju, prekid kola i ograničavanje protoka, kanarno (gray) objavljivanje, upravljanje logovima, nadzor protoka itd.
- Glavna funkcija kontrolne ravni je objedinjeno upravljanje i konfiguracija pozadinskih servisa. Na primer, može kontrolisati elastično skaliranje gateway-a; može objedinjeno dostavljati konfiguraciju; može dodavati oznake (tagove) gateway servisima; može putem konfiguracije Swagger funkcije na mikroservisnom gateway-u objedinjeno izložiti API ugovore pozadinskih servisa korisnicima, čime se obezbeđuje servis dokumentacije, povećava efikasnost rada i smanjuju troškovi komunikacije.

- Funkcija rutiranja: rutiranje je osnovna sposobnost mikroservisnog gateway-a. Pomoću funkcije rutiranja, mikroservisni gateway može proslediti zahtev ciljnom mikroservisu. U mikroservisnoj arhitekturi, gateway se može kombinovati sa dinamičkim otkrivanjem servisa iz registra centara, čime se omogućava otkrivanje pozadinskih servisa — pozivaoc je potrebno samo da zna API servisa koji gateway izlaže kako bi transparentno pristupio pozadinskim mikroservisima.
- Balansiranje opterećenja: API gateway, u kombinaciji sa tehnikama balansiranja opterećenja i alatima za otkrivanje servisa kao što su Eureka ili Consul, ostvaruje balansiranje opterećenja nizvodnih servisa putem mehanizama poput round-robin, specificiranja težina i heširanja IP adresa.
- Objedinjena autentifikacija: uopšteno, bilo za interne ili eksterne interfejse potrebno je izvršiti autentifikaciju korisnika, a autentifikacija korisnika u sistemima većeg obima uglavnom koristi objedinjeni sistem jedinstvene prijave (Single Sign On). Ako svaki mikroservis pojedinačno mora da se poveže sa sistemom jedinstvene prijave, to je očigledno rasipanje resursa i smanjuje efikasnost razvoja. API gateway je odlično mesto za objedinjeno upravljanje bezbednošću — deo za autentifikaciju se može izdvojiti na nivo gateway-a, tako da mikroservisni sistem ne mora da brine o logici autentifikacije već se fokusira isključivo na sopstveni biznis.
- Konverzija protokola: jedna od važnih uloga API gateway-a jeste izgradnja heterogenih sistema. API gateway, kao jedinstveni ulaz, putem konverzije protokola integriše pozadinske mikroservise zasnovane na različitim stilovima i tehnologijama (REST, AMQP, Dubbo itd.) i pruža objedinjene servise specifičnim klijentima kao što su Web, Mobile i otvorene platforme.
- Nadzor metrika: gateway može brojati zahteve ka pozadinskim servisima i može u realnom vremenu ažurirati trenutno zdravstveno stanje protoka. Može vršiti statistiku kašnjenja na nivou URL-a, a može se koristiti i Hystrix Dashboard za pregled stanja protoka pozadinskih servisa i da li je došlo do prekida kola (circuit breaker).
- Ograničavanje protoka i prekid kola: u određenim scenarijima potrebno je kontrolisati broj i učestalost pristupa klijenata, a neki sistemi sa visokim paralelizmom povremeno imaju potrebu za ograničavanjem protoka. Na gateway-u se može konfigurisati prag — kada broj zahteva premaši prag, vraća se greška bez nastavka pristupa pozadinskim servisima. Kada se pojavi vrhunac protoka ili kašnjenje/kvar pozadinskih servisa, gateway može aktivno izvršiti prekid kola, čime štiti pozadinske servise i održava dobro korisničko iskustvo na prednjoj strani.
- Crne i bele liste: mikroservisni gateway može koristiti crnu listu sistema, filtrirati karakteristike HTTP zahteva i blokirati zahteve abnormalnih klijenata — na primer, napade poput DDoS-a koji zauzimaju propusni opseg ili resurse i prisiljavaju servis na prekid. Ova filtracija se može obaviti na nivou gateway-a. Prilično uobičajena strategija blokiranja je dodavanje IP adrese na crnu listu. U rutingskim servisima koji imaju upravljanje autentifikacijom, postavljanjem bele liste se može preskočiti autentifikacija i direktno pristupiti resursima pozadinskih servisa.
- Kanarna (gray) objavljivanje: mikroservisni gateway može kontrolisati protok na osnovu specijalnih oznaka u HTTP zahtevima i metapodataka liste pozadinskih servisa, čime se omogućava završetak kanarne objave bez da korisnik to primeti.
- Obojenje protoka (traffic tagging): slično principu kanarne objave, gateway može obojiti (tagovati) zahteve na osnovu identifikatora kao što su Host, Header i Agent u HTTP zahtevima. Zahvaljujući funkciji obojenja protoka gateway-a, možemo pratiti naknadne lance poziva servisa i sprovesti detaljniju analizu lanca radi kašnjenja servisa i stanja rada.
- Centar za dokumentaciju: gateway, u kombinaciji sa Swagger-om, može izložiti pozadinske mikroservise gateway-u. Kao objedinjeni ulaz, gateway pruža potrošačima interfejsa mogućnost pregleda API specifikacija pozadinskih servisa, bez potrebe da znaju adresu Swagger-a za svaki pojedinačni pozadinski mikroservis — na taj način gateway ostvaruje efekat agregacije pozadinskih API-ja.
- Revizija logova: mikroservisni gateway može poslužiti kao objedinjeni zapisivač i sakupljač logova, presrećući informacije o zahtevima i odgovorima na nivou URL-a servisa.
Izbor API gateway-a
Uobičajeni API gateway-ovi
Hajde da najpre kratko pogledamo uobičajene API gateway-e na tržištu:

Nginx
Nginx je visoko-performantni HTTP i obrnuti-proksi server. Nginx s jedne strane može služiti kao obrnuti proksi, a s druge strane kao server statičkih resursa; korišćenjem Lua dinamičkog jezika za interfejse može se ostvariti fleksibilna prilagođena funkcionalnost.
Nakon pokretanja, Nginx ima jedan Master proces i više Worker procesa. Master i Worker procesi komuniciraju putem međuprocesne komunikacije, kao što je prikazano na slici. Tačka blokiranja Worker procesa je u pozivima funkcija za I/O multipleksiranje, kao što su select() i epoll_wait(), gde se čeka na događaje spremne za čitanje/pisanje podataka. Nginx koristi asinhroni neblokirajući način obrade zahteva, što znači da Nginx može istovremeno obraditi na hiljade ili desetine hiljada zahteva.
Zuul
Zuul je komponenta API gateway-a koju je Netflix otvorio kao open-source; može se koristiti zajedno sa komponentama kao što su Eureka, Ribbon i Hystrix. Zajednica je aktivna, integrisana je u kompletan Spring Cloud ekosistem i predstavlja jedan od najboljih izbora za izgradnju gateway servisa na ulazu u mikroservisni sistem.
Jezgro Zuul-a čini niz filtera koji mogu ostvariti sledeće funkcije:
- Objedinjena autentifikacija + dinamičko rutiranje + balansiranje opterećenja + testiranje pod opterećenjem
- Nadzor i praćenje: praćenje smislenih podataka i statističkih rezultata na graničnoj lokaciji, čime se dobija precizan pregled produkcionog okruženja.
- Elastičnost u više regiona: rutiranje zahteva kroz AWS regije, sa ciljem diverzifikacije korišćenja ELB (Elastic Load Balancing) i približavanja ivica sistema korisnicima sistema.
Zuul trenutno ima dve glavne verzije: Zuul 1 i Zuul 2.
Zuul 1 je izgrađen na okviru Servlet-a. Kao što je prikazano na slici, koristi blokirajući i višenisni pristup — jedan obrađuje jednu konekciju zahteva. Ovaj pristup, u slučaju ozbiljnih internih kašnjenja i učestalih kvarova uređaja, može dovesti do povećanja broja aktivnih konekcija i niti.

Zuul 2, koji je Netflix objavio, ima značajna poboljšanja — radi na asinhronom i neblokirajućem okviru, sa jednom niti po CPU jezgru koje obrađuje sve zahteve i odgovore. Životni ciklus zahteva i odgovora se obrađuje putem događaja i povratnih poziva (callback), što smanjuje broj niti i samim tim i režijske troškove.

Spring Cloud Gateway
Spring Cloud Gateway je potpuno novi API gateway projekat iz Spring Cloud ekosistema, sa ciljem da zameni Zuul 1. Razvijen je na osnovu Spring 5.0 + Spring Boot 2.0 + WebFlux (zasnovanog na visoko-performantnom Reactor obrascu i responsivnom komunikacionom okviru Netty — asinhroni neblokirajući model) i drugih tehnologija. Performanse su više nego kod Zuul-a; prema zvaničnim testovima, Spring Cloud Gateway je 1.6 puta brži od Zuul-a, sa ciljem da mikroservisnoj arhitekturi pruži jednostavan i efikasan objedinjeni način upravljanja API rutiranjem.
Spring Cloud Gateway se može koristiti zajedno sa Spring Cloud Discovery Client (kao što je Eureka), Ribbon, Hystrix i drugim komponentama, čime se ostvaruju prosleđivanje rutiranja, balansiranje opterećenja, prekid kola, autentifikacija, prepisivanje putanja, nadzor logova itd. Gateway takođe ima ugrađen filter za ograničavanje protoka, čime implementira funkcionalnost rate limiting-a.

Kong
Kong je visoko-dostupan i lako proširivi API Gateway projekat zasnovan na OpenResty (Nginx + Lua modulu), koji je kompanija Mashape objavila kao open-source. Kong je izgrađen na bazi NGINX-a i Apache Cassandra ili PostgreSQL, a pruža lako upotrebljiv RESTful API za upravljanje i konfiguraciju sistema, što omogućava horizontalno skaliranje na više Kong servera. Uz konfiguraciju prednjeg balansera opterećenja, zahtevi se ravnomerno raspoređuju na pojedinačne servere kako bi se izborili sa velikim obimom mrežnih zahteva.

Kong se uglavnom sastoji od tri komponente:
- Kong Server: server zasnovan na Nginx-u, koji prima API zahteve.
- Apache Cassandra/PostgreSQL: služi za skladištenje operativnih podataka.
- Kong dashboard: zvanično preporučeni UI alat za upravljanje; takođe je moguće upravljati admin API-jem na RESTful način.
Kong koristi mehanizam dodatka (plugin) za prilagođavanje funkcija. Skup dodataka (koji može biti 0 ili N) se izvršava u životnom ciklusu zahtev-odgovor API-ja. Dodaci su pisani na Lua jeziku, a trenutno već postoji nekoliko osnovnih funkcija: osnovna HTTP autentifikacija, autentifikacija ključem, CORS (Cross-Origin Resource Sharing — deljenje resursa između različitih izvora), TCP, UDP, logovanje u fajl, ograničavanje broja API zahteva, prosleđivanje zahteva i Nginx nadzor.

Kong gateway ima sledeće karakteristike:
- Skalabilnost: dodavanjem još servera se lako postiže horizontalno skaliranje, što znači da vaša platforma može obraditi bilo koji zahtev pri nižem opterećenju;
- Modularnost: može se proširiti dodavanjem novih dodataka, koji se lako konfigurišu putem RESTful Admin API-ja;
- Izvršavanje na bilo kojoj infrastrukturi: Kong gateway može raditi bilo gde — možete ga rasporediti u oblaku ili u internom mrežnom okruženju, uključujući podešavanja sa jednim ili više data centara, kao i za javne, privatne ili pozivom-rezervisane API-je.
Traefik
Træfɪk je moderan HTTP obrnuti proksi i alat za balansiranje opterećenja, nastao da bi se olakšalo raspoređivanje mikroservisa. Podržava različite pozadinske sisteme (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) radi automatizovanog i dinamičkog primenjivanja konfiguracionih fajlova.

Važne karakteristike:
- Veoma je brz, bez potrebe za instalacijom drugih zavisnosti — jedinstvena izvršna datoteka pisana na Go jeziku;
- Podrška za više pozadinskih sistema: Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd;
- Podrška za REST API, Websocket, HTTP/2, Docker slike;
- Sluša promene na pozadini i automatski primenjuje nova podešavanja konfiguracionih fajlova;
- Vruće ažuriranje konfiguracionih fajlova, bez potrebe za restartom procesa;
- Pozadinski prekidači kola (circuit breaker), balansiranje opterećenja, mehanizmi tolerancije grešaka;
- Pregledan prednji interfejs za nadzor metrika servisa.
Za više sadržaja o Traefik-u, pogledajte zvanični sajt: https://traefik.cn/
Poređenje API gateway-ova



Gore su prikazani snimci ekrana sa poređenjem gateway-a. Da uštedim vreme, fokusirajte se uglavnom na Kong, Traefik i Zuul:
- Sa stanovišta aktivnosti open-source zajednice, Kong i Traefik su nesumnjivo bolji;
- Sa stanovišta zrelosti, bolji su Kong, Tyk i Traefik;
- Sa stanovišta performansi, Kong je malo ispred ostalih;
- Sa stanovišta proširivosti arhitektonske prednosti, Kong i Tyk imaju bogat skup dodataka; Ambassador takođe ima dodataka, ali ne mnogo, dok Zuul u potpunosti zahteva samostalni razvoj. Međutim, pošto je Zuul duboko integrisan sa Spring Cloud-om, nivo korišćenja je takođe visok. Poslednjih godina, sa porastom popularnosti Istio service mesh-a, Ambassador ima prilično veliku prednost jer se može neprimetno integrisati sa Istio-om.
Ispod su zaključci razmišljanja drugih čitalaca, koje možete uzeti u obzir:
- Performanse: Nginx + Lua pristup je nužno iznad gateway-a implementiranih na Java jeziku. U okviru Java tehnološkog steka, Zuul 1.0 je zasnovan na Servlet-u, dok su preostali zasnovani na WebFlux-u — performanse su iznad onih zasnovanih na Servlet-u. Što se tiče performansi, mislim da izbor gateway-a možda nije tako bitan — dodavanjem još nekoliko mašina se problem rešava.
- Održivost i proširivost: Nginx + Lua ovu kombinaciju nevlada veliki broj ljudi. Ako vaš tim ima stručnjaka, onda vas slobodno puštamo da radite šta želite — možete ignorisati ovaj pasus. Za prosečan tim, važnije je odabrati jezik u kom vaš tim vlada. Od tri gateway-a u Java tehnološkom stomaku, Zuul i Spring Cloud Gateway zahtevaju manje-više izradu određenih integracionih i konfiguracionih stranica za održavanje, dok za Soul mogu bezbrižno da čitam članke i uzimam šta mi treba — naročito je zgodno što se može bezbrižno integrisati sa Dubbo. Pored toga, verzije Soul-a od 2.0 nadalje mogu da se odvoje od ZK-a, što u mom mišljenju otklanja sve nedostatke — volim pristup bez komplikacija.
- Visoka dostupnost: za visoku dostupnost gateway-a strategija je uglavnom ujednačena — koristi se raspored na više mašina, sa balanserom opterećenja ispred, a obratite pažnju na komponente koje su vam potrebne za dodatne potrebe.
Samostalno razvijeni mikroservisni gateway zasnovan na Traefik-u
Ovo je mikroservisni gateway koji je naša kompanija samostalno razvila, zasnovan na Traefik-u. U nastavku ću ga obraditi kroz izbor tehnologije, okvir gateway-a, pozadinu gateway-a i konverziju protokola — iskreno, prava poslastica!
Izbor tehnološkog steka
- Traefik: open-source alat za obrnuti proksi i balansiranje opterećenja. Njegova najveća prednost je sposobnost direktne integracije sa uobičajenim mikroservisnim sistemima i automatske dinamičke konfiguracije. Traefik je prilično lagan, veoma je lako koristiti i podesiti, a performanse su dobre — koristi se u produkcionom okruženju širom sveta.
- Etcd: distribuirani, visoko-dostupan sistem za skladištenje parova ključ-vrednost (key-value) pisani na Go jeziku, koji pruža pouzdano distribuirano skladištenje ključeva, deljenje konfiguracije i otkrivanje servisa.
- Go: jaka sposobnost paralelizma, performanse uporedive sa C-om, četvorostruko veća procesna snaga od PHP-a; efikasan, sa jednostavnom sintaksom, lako se uči, a efikasnost razvoja bliska je PHP-u.

Okvir gateway-a
Čitav okvir gateway-a se deli u 3 dela:
- Pozadina gateway-a (hal-fe i hal-admin): služi za konfiguraciju aplikacija, servisa i dodataka, a zatim se konfiguracione informacije objavljuju u ETCD.
- Traefik: čita ETCD konfiguraciju i na osnovu nje rutira zahteve. Ako je potrebna autentifikacija, direktno se vrši putem hal-agent modula za objedinjenu autentifikaciju. Nakon autentifikacije, ako je HTTP zahtev, šalje se direktno nizvodnom servisu; ako su u pitanju gRPC i Thrift protokoli, vrši se konverzija protokola putem hal-proxy modula.
- Modul za konverziju protokola: čita ETCD konfiguraciju i za zahteve koje prosledi Traefik vrši konverziju gRPC i Thrift protokola. Putem mehanizma otkrivanja servisa dobija nizvodne mašine servisa i, koristeći balansiranje opterećenja, šalje konvertovane podatke na nizvodne mašine servisa.

Pozadina gateway-a
Sastoji se uglavnom od 3 velika modula:
- Aplikacija: uglavnom obuhvata ime aplikacije, domen, prefix putanje, pripadnost grupi, status itd. — na primer, indijski inostrani mall, indijska zajednica.
- Servis: uglavnom obuhvata ime servisa, način registracije, tip protokola, pripadnost grupi, status itd. — na primer, servis za komentare, servis za adrese, servis za pretragu.
- Dodatak (plugin): uglavnom obuhvata ime dodatka, tip dodatka, konfiguraciju svojstava dodatka itd. — na primer, dodatak za zamenu prefixa putanje, dodatak za autentifikaciju.

Jedna aplikacija se može vezati samo za jedan servis, ali može biti vezana za više dodataka. Nakon završetka konfiguracije gateway-a na pozadini, te se konfiguracione informacije pretvaraju u Config fajl i objavljuju u ETCD. Config fajl mora slediti strogi format podataka — na primer, Traefik konfiguracija mora slediti zvanični format konfiguracionog fajla da bi je Traefik prepoznao.

Modul za konverziju protokola
hal-proxy modul je najkompleksniji deo čitavog mikroservisnog gateway-a, ujedno i modul sa najvišim tehničkim sadržajem, pa ću vam ga detaljno objasniti.
Uvođenje problema
Pre nego što pređemo na ovaj modul, hajde da prvo pogledamo sledećih nekoliko pitanja:
- Kada zahtev dođe sa uzvodnog Traefik-a, potrebno je znati IP i port nizvodne mašine kako bi se zahtev poslao nizvodno — kako se te mašine dobijaju?
- Nakon što se dobiju mašine, potrebno je uspostaviti vezu sa nizvodnim mašinama. Ako se veza nakon jednog korišćenja odmah oslobodi, to bi svakako izazvalo veliki pritisak na servis — potrebno je uvesti Client pool za keširanje. Kako taj Client pool za keširanje implementirati?
- Na kraju, potrebno je izvršiti konverziju protokola, jer različiti nizvodni servisi podržavaju različite tipove protokola — kako ovaj gateway to dinamički podržava?

Princip implementacije

Hajde da najpre pogledamo koje module ima hal-proxy interno. Prvi je Resolver modul — koja je njegova uloga? Ovde ću ukratko objasniti: trenutno postoje različiti načini za dobijanje liste mašina preko servisa unutar kompanije, kao što su MIS platforma, stablo servisa itd. — neki se konfigurišu preko platforme, dok su drugi direktno prikačeni ispod stabla servisa. Bilo koji od ovih pristupa, mi putem imena servisa na određeni način pronalazimo sve hostove ispod tog servisa.
Dakle, uloga Resolver modula je zapravo da preko imena servisa pronađe sve IP adrese i portove servisa mašina ispod tog servisa, zatim ih trajno uskladišti u memoriji i povremeno ih ažurira.
Modul za protokole podržava različite konverzije protokola. Svaki tip konverzije protokola zahteva posebnu implementaciju — te konverzije protokola se u suštini svode na to da se prvo putem IP adrese i porta mašine inicijalizuje Client, a zatim se podaci konvertuju i pošalju direktno nizvodnoj mašini.
Na kraju, to je pool veza. Ranije smo zapravo koristili ugrađeni go pool, ali kada je bilo potrebno ažurirati podatke u pool-u, moralo se zaključati (lock), tako da performanse nisu mogle da se podignu. Kasnije smo prešli na kružni red (ring queue), a zatim se sve operacije nad podacima obavljaju isključivo putem atomskih operacija, čime je realizovana operacija bez brava (lock-free), što je značajno poboljšalo performanse paralelizma.
Logika implementacije
Ovo je dijagram logičke implementacije hal-proxy-a. Radio sam na njemu dva dana; obuhvata sve načine interakcije ključnih objekata. Neću ulaziti u detalje — koliko ćete iz toga izvući zavisi od vas. Ako imate bilo kakvih pitanja (ili ne možete jasno da vidite sliku), slobodno stupite u kontakt.

Priredio: Chenmo Wang Er, pogledajte link za preštampavanje, autor: Lou Zai, pogledajte originalni link.
