Bevezetés Kongba
1. Bemutatkozás
A Kong egy nyílt forráskódú API-átjáró és mikroszolgáltatás-kezelő réteg.
Az Nginx és a lua-nginx-modul (konkrétan az OpenResty) alapján a Kong bedugaszolható architektúrája rugalmassá és erőteljessé teszi.
2. Fogalmak
Mielőtt belevágnánk a kódmintákba, vessünk egy pillantást Kong legfontosabb fogalmaira:
- API objektum - minden olyan HTTP-végpont tulajdonságait beburkolja, amelyek végrehajtanak egy adott feladatot vagy szolgáltatást nyújtanak. A konfigurációk tartalmazzák a HTTP-módszereket, a végpont URI-kat, az upstream URL-t, amely az API-kiszolgálóinkra mutat és felhasználásra kerül a kérések proxy-jára, a maximális visszavonásokra, a sebességkorlátokra, az időkorlátokra stb.
- Fogyasztói objektum - az API végpontjaink használatával bárki tulajdonságait áttekinti. Nyomon követésre, hozzáférés-ellenőrzésre és egyebekre fogják használni
- Felső objektum - leírja, hogy a bejövő kérések hogyan lesznek proxyzálva vagy kiegyensúlyozva a terheléssel, amelyet virtuális gazdagépnév képvisel
- Célobjektum - azt jelenti, hogy a szolgáltatásokat megvalósítják és kiszolgálják, hostnévvel (vagy IP-címmel) és porttal azonosítva. Vegye figyelembe, hogy minden upstream célpontja csak hozzáadható vagy letiltható. A célváltozások előzményeit az upstream tartja fenn
- Plugin Object - bedugható funkciók az alkalmazás funkcióinak gazdagítására a kérés és a válasz életciklusa alatt. Például API hitelesítés és sebességkorlátozó funkciók hozzáadhatók a releváns bővítmények engedélyezésével. Kong nagyon erős beépülő modulokat kínál a beépülő galériában
- Admin API - RESTful API-végpontok, amelyeket a Kong-konfigurációk, végpontok, fogyasztók, beépülő modulok stb. Kezelésére használnak
Az alábbi kép azt mutatja be, hogy a Kong miben különbözik a régi architektúrától, ami segíthet megérteni, miért vezette be ezeket a fogalmakat:
(forrás: //getkong.org/)
3. Beállítás
A hivatalos dokumentáció részletes útmutatásokat tartalmaz a különböző környezetekhez.
4. API kezelés
Miután helyileg beállította a Kong-ot, harapjuk meg Kong erőteljes szolgáltatásait azáltal, hogy megadjuk az egyszerű részvény lekérdezési végpontunkat:
@RestController @RequestMapping ("/ stock") public class QueryController {@GetMapping ("/ {code}") public String getStockPrice (@PathVariable String code) {return "BTC" .equalsIgnoreCase (code)? "10000": "0"; }}
4.1. API hozzáadása
Ezután adjuk hozzá a lekérdezési API-t a Kong-hoz.
Az admin API-k a következőn keresztül érhetők el // localhost: 8001, így minden API-kezelési műveletünket ezzel az alap URI-val fogjuk elvégezni:
APIObject stockAPI = új APIObject ("stock-api", "stock.api", "// localhost: 8080", "/"); HttpEntity apiEntity = új HttpEntity (stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity ("// localhost: 8001 / apis", apiEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ());
Itt hozzáadtunk egy API-t a következő konfigurációval:
{"name": "stock-api", "hosts": "stock.api", "upstream_url": "// localhost: 8080", "uris": "/"}
- "név" az API azonosítója, amelyet annak viselkedésének manipulálásakor használnak
- "otthont ad" a bejövő kérések átirányításához az adott fájlhoz lesz használva „Upstream_url” a "Házigazda" fejléc
- A relatív elérési utak hozzá lesznek adva a konfigurált „urikhoz”
Abban az esetben, ha le akarjuk vonni az API-t, vagy a konfiguráció hibás, egyszerűen eltávolíthatjuk:
restTemplate.delete ("// localhost: 8001 / apis / stock-api");
Az API-k hozzáadása után ezek keresztül lesznek felhasználhatók // localhost: 8000:
String apiListResp = restTemplate.getForObject ("// localhost: 8001 / apis /", String.class); assertTrue (apiListResp.contains ("stock-api")); HttpHeaders fejlécek = new HttpHeaders (); headers.set ("Host", "stock.api"); RequestEntity requestEntity = new RequestEntity (fejlécek, HttpMethod.GET, új URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate.exchange (requestEntity, String.class); assertEquals ("10000", stockPriceResp.getBody ());
A fenti kódmintában megpróbáljuk lekérdezni a részvényárfolyamot az API-n keresztül, amelyet most adtunk Konghoz.
Kéréssel // localhost: 8000 / stock / btc, ugyanazt a szolgáltatást kapjuk, mint a közvetlen lekérdezés // localhost: 8080 / stock / btc.
4.2. API-fogyasztó hozzáadása
Beszéljünk most a biztonságról - pontosabban az API-nkat elérő felhasználók hitelesítéséről.
Vegyünk fel egy fogyasztót a részvény lekérdezési API-ba, hogy később engedélyezhessük a hitelesítési funkciót.
Fogyasztó hozzáadása egy API-hoz ugyanolyan egyszerű, mint egy API hozzáadása. A fogyasztó neve (vagy azonosítója) az egyetlen kötelező mező a fogyasztó összes tulajdonságánál:
ConsumerObject fogyasztó = new ConsumerObject ("eugenp"); HttpEntity addConsumerEntity = új HttpEntity (fogyasztó); ResponseEntity addConsumerResp = restTemplate.postForEntity ("// localhost: 8001 / consumer /", addConsumerEntity, String.class); assertEquals (HttpStatus.CREATED, addConsumerResp.getStatusCode ());
Itt új fogyasztóként hozzáadtuk az „eugenp” -t:
{"felhasználónév": "eugenp"}
4.3. A hitelesítés engedélyezése
Itt jön a Kong legerősebb tulajdonsága, a beépülő modulok.
Most egy autent bővítményt fogunk alkalmazni a proxykészlet lekérdezés API-ra:
PluginObject authPlugin = új PluginObject ("kulcs-hitelesítés"); ResponseEntity enableAuthResp = restTemplate.postForEntity ("// localhost: 8001 / apis / stock-api / plugins", új HttpEntity (authPlugin), String.class); assertEquals (HttpStatus.CREATED, enableAuthResp.getStatusCode ());
Ha megpróbáljuk lekérdezni a részvény árát a proxy URI-n keresztül, a kérelmet elutasítjuk:
HttpHeaders fejlécek = new HttpHeaders (); headers.set ("Host", "stock.api"); RequestEntity requestEntity = new RequestEntity (fejlécek, HttpMethod.GET, új URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate .exchange (requestEntity, String.class); assertEquals (HttpStatus.UNAUTHORIZED, stockPriceResp.getStatusCode ());
Emlékezz arra Eugen az egyik API-fogyasztónk, ezért engedélyeznünk kell számára az API használatát egy hitelesítési kulcs hozzáadásával:
String consumerKey = "eugenp.pass"; KeyAuthObject keyAuth = új KeyAuthObject (consumerKey); ResponseEntity keyAuthResp = restTemplate.postForEntity ("// localhost: 8001 / consumer / eugenp / key-auth", új HttpEntity (keyAuth), String.class); assertTrue (HttpStatus.CREATED == keyAuthResp.getStatusCode ());
Azután Eugen használhatja ezt az API-t, mint korábban:
HttpHeaders fejlécek = new HttpHeaders (); headers.set ("Host", "stock.api"); fejlécek.set ("apikey", consumerKey); RequestEntity requestEntity = new RequestEntity (fejlécek, HttpMethod.GET, új URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate .exchange (requestEntity, String.class); assertEquals ("10000", stockPriceResp.getBody ());
5. Speciális funkciók
Az alapvető API proxy és menedzsment mellett a Kong támogatja az API terheléselosztását, fürtözését, állapotfelmérését és felügyeletét stb.
Ebben a szakaszban megvizsgáljuk, hogyan lehet betölteni az egyenlegkérelmeket a Kongszal, és hogyan lehet biztonságossá tenni az adminisztrátori API-kat.
5.1. Terhelés elosztás
Kong két stratégiát kínál a terheléselosztási kérelmekhez a háttérszolgáltatások számára: dinamikus gyűrűkiegyenlítőt és egy egyszerű DNS-alapú módszert. Az egyszerűség kedvéért, a gyűrűkiegyensúlyozót fogjuk használni.
Mint korábban említettük, az upstream-eket használják a terhelés-kiegyenlítéshez, és mindegyik upstream-nek több célja lehet.
Kong egyaránt támogatja a súlyozott körméretes és hash-alapú kiegyensúlyozó algoritmusokat. Alapértelmezés szerint a súlyozott körméretes sémát használják - ahol az egyes célpontokhoz a súlyuk szerint érkeznek a kérések.
Először készítsük elő az upstream-t:
UpstreamObject upstream = new UpstreamObject ("stock.api.service"); ResponseEntity addUpstreamResp = restTemplate.postForEntity ("// localhost: 8001 / upstreams", új HttpEntity (upstream), String.class); assertEquals (HttpStatus.CREATED, addUpstreamResp.getStatusCode ());
Ezután adjon hozzá két célt az upstream-hez, egy tesztverziót a súly = 10, és egy kiadási verzió a súly = 40:
TargetObject testTarget = új TargetObject ("localhost: 8080", 10); ResponseEntity addTargetResp = restTemplate.postForEntity ("//localhost:8001/upstreams/stock.api.service/targets", új HttpEntity (testTarget), String.class); assertEquals (HttpStatus.CREATED, ddTargetResp.getStatusCode ()); TargetObject releaseTarget = új TargetObject ("localhost: 9090", 40); addTargetResp = restTemplate.postForEntity ("//localhost:8001/upstreams/stock.api.service/targets", új HttpEntity (releaseTarget), String.class); assertEquals (HttpStatus.CREATED, addTargetResp.getStatusCode ());
A fenti konfigurációval feltételezhetjük, hogy a kérelmek 1/5-e a teszt verzióra, 4/5 pedig a kiadási verzióra kerül:
APIObject stockAPI = új APIObject ("balance-stock-api", "balance.stock.api", "//stock.api.service", "/"); HttpEntity apiEntity = új HttpEntity (stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity ("// localhost: 8001 / apis", apiEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ()); HttpHeaders fejlécek = new HttpHeaders (); headers.set ("Host", "balance.stock.api"); for (int i = 0; i <1000; i ++) {RequestEntity requestEntity = új RequestEntity (fejlécek, HttpMethod.GET, új URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate.exchange (requestEntity, String.class); assertEquals ("10000", stockPriceResp.getBody ()); } int releaseCount = restTemplate.getForObject ("// localhost: 9090 / stock / reqcount", Integer.class); int testCount = restTemplate.getForObject ("// localhost: 8080 / stock / reqcount", Integer.class); assertTrue (Math.round (releaseCount * 1,0 / testCount) == 4);
Ne feledje, hogy a súlyozott körbetétes séma megközelíti a szolgáltatások háttérterjesztésére vonatkozó igényeket a súlyarányhoz viszonyítva, így csak az arány közelítése ellenőrizhető, ami a fenti kód utolsó sorában tükröződik.
5.2. Az Admin API védelme
Alapértelmezés szerint Kong csak a helyi felületről fogad adminisztrációs kéréseket, ami a legtöbb esetben elég jó korlátozás. De ha más hálózati interfészeken keresztül akarjuk kezelni, akkor a admin_listen érték ben kong.conf, és konfigurálja a tűzfalszabályokat.
Vagy megtehetjük, hogy a Kong magának az Admin API-nak a proxyjaként szolgál. Tegyük fel, hogy az API-kat az „/ admin-api” elérési utdal szeretnénk kezelni, hozzáadhatunk egy ilyen API-t:
APIObject stockAPI = új APIObject ("admin-api", "admin.api", "// localhost: 8001", "/ admin-api"); HttpEntity apiEntity = új HttpEntity (stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity ("// localhost: 8001 / apis", apiEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ());
Most már használhatjuk a proxy adminisztrátori API-t az API-k kezelésére:
HttpHeaders fejlécek = new HttpHeaders (); headers.set ("Host", "admin.api"); APIObject baeldungAPI = új APIObject ("baeldung-api", "baeldung.com", "//ww.baeldung.com", "/"); RequestEntity requestEntity = új RequestEntity (baeldungAPI, fejlécek, HttpMethod.POST, új URI ("// localhost: 8000 / admin-api / apis")); ResponseEntity addAPIResp = restTemplate .exchange (requestEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ());
Biztosan azt akarjuk, hogy a proxy API biztonságban legyen. Ez könnyen elérhető a hitelesítési plugin engedélyezésével a proxy adminisztrátori API-nál.
6. Összefoglalás
Ebben a cikkben bemutattuk a Kong-ot - egy platformot a mikroszolgáltatás API-átjárójához, és annak központi funkcionalitására összpontosítottunk - az API-k kezelésére és a kérelmek irányítására az upstream szerverek felé, valamint néhány fejlettebb szolgáltatásra, például a terheléselosztásra.
Mégis van még számos szilárd funkció, amelyet felfedezhetünk, és ha szükséges, kialakíthatjuk saját pluginjainkat - itt folytathatja a hivatalos dokumentáció felfedezését.
Mint mindig, a teljes megvalósítás megtalálható a Githubon.