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.