Een inleiding tot Kong

1. Inleiding

Kong is een open-source API-gateway en microservicebeheerlaag.

Gebaseerd op Nginx en de lua-nginx-module (specifiek OpenResty), maakt Kong's pluggable architectuur het flexibel en krachtig.

2. Sleutelbegrippen

Laten we, voordat we in codevoorbeelden duiken, eens kijken naar de belangrijkste concepten in Kong:

  • API-object - wraps eigenschappen van elk HTTP (s) -eindpunt dat een specifieke taak uitvoert of een bepaalde service levert. Configuraties omvatten HTTP-methoden, eindpunt-URI's, upstream-URL die naar onze API-servers verwijst en zal worden gebruikt voor proxyverzoeken, maximale pensioneringen, snelheidslimieten, time-outs, enz.
  • Consumentenobject - wraps eigenschappen van iedereen die onze API-eindpunten gebruikt. Het wordt gebruikt voor tracking, toegangscontrole en meer
  • Stroomopwaarts object - beschrijft hoe inkomende verzoeken via proxy of load-balanced zullen worden uitgevoerd, vertegenwoordigd door een virtuele hostnaam
  • Doelobject - vertegenwoordigt de services worden geïmplementeerd en bediend, geïdentificeerd door een hostnaam (of een IP-adres) en een poort. Merk op dat doelen van elke stroomopwaarts alleen kunnen worden toegevoegd of uitgeschakeld. Een geschiedenis van doelwijzigingen wordt bijgehouden door de stroomopwaarts
  • Plugin-object - pluggable functies om functionaliteiten van onze applicatie te verrijken tijdens de aanvraag- en responslevenscyclus. API-authenticatie en snelheidsbeperkende functies kunnen bijvoorbeeld worden toegevoegd door relevante plug-ins in te schakelen. Kong biedt zeer krachtige plug-ins in zijn galerij met plug-ins
  • Admin API - RESTful API-eindpunten die worden gebruikt om Kong-configuraties, eindpunten, consumenten, plug-ins, enzovoort te beheren

De onderstaande afbeelding laat zien hoe Kong verschilt van een oude architectuur, wat ons zou kunnen helpen begrijpen waarom het deze concepten introduceerde:

(bron: //getkong.org/)

3. Installatie

De officiële documentatie biedt gedetailleerde instructies voor verschillende omgevingen.

4. API-beheer

Laten we na het lokaal opzetten van Kong een hapje nemen van de krachtige functies van Kong door ons eenvoudige eindpunt voor voorraadquery's te proxy:

@RestController @RequestMapping ("/ stock") openbare klasse QueryController {@GetMapping ("/ {code}") openbare tekenreeks getStockPrice (@PathVariable Tekenreekscode) {retour "BTC" .equalsIgnoreCase (code)? "10000": "0"; }}

4.1. Een API toevoegen

Laten we vervolgens onze query-API toevoegen aan Kong.

De admin API's zijn toegankelijk via // localhost: 8001, dus al onze API-beheerbewerkingen worden uitgevoerd met deze basis-URI:

APIObject stockAPI = nieuw APIObject ("stock-api", "stock.api", "// localhost: 8080", "/"); HttpEntity apiEntity = nieuwe HttpEntity (stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity ("// localhost: 8001 / apis", apiEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ());

Hier hebben we een API toegevoegd met de volgende configuratie:

{"name": "stock-api", "hosts": "stock.api", "upstream_url": "// localhost: 8080", "uris": "/"}
  • "naam" is een identificatie voor de API, die wordt gebruikt bij het manipuleren van zijn gedrag
  • "Hosts" wordt gebruikt om inkomende verzoeken naar gegeven te routeren "Upstream_url" door de "Gastheer" koptekst
  • Relatieve paden worden vergeleken met de geconfigureerde ‘uris’

Als we een API willen afschaffen of als de configuratie niet klopt, kunnen we deze eenvoudig verwijderen:

restTemplate.delete ("// localhost: 8001 / apis / stock-api");

Nadat API's zijn toegevoegd, zijn ze beschikbaar voor consumptie via // localhost: 8000:

String apiListResp = restTemplate.getForObject ("// localhost: 8001 / apis /", String.class); assertTrue (apiListResp.contains ("stock-api")); HttpHeaders headers = nieuwe HttpHeaders (); headers.set ("Host", "stock.api"); RequestEntity requestEntity = nieuwe RequestEntity (headers, HttpMethod.GET, nieuwe URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate.exchange (requestEntity, String.class); assertEquals ("10000", stockPriceResp.getBody ());

In het bovenstaande codevoorbeeld proberen we de aandelenkoers op te vragen via de API die we zojuist aan Kong hebben toegevoegd.

Door te vragen // localhost: 8000 / stock / btc, krijgen we dezelfde service als rechtstreeks vanuit // localhost: 8080 / stock / btc.

4.2. Een API-consument toevoegen

Laten we het nu hebben over beveiliging - meer specifiek authenticatie voor de gebruikers die toegang hebben tot onze API.

Laten we een consument toevoegen aan onze voorraadquery-API, zodat we de authenticatiefunctie later kunnen inschakelen.

Het toevoegen van een consument voor een API is net zo eenvoudig als het toevoegen van een API. De naam (of id) van de consument is het enige verplichte veld van alle eigenschappen van de consument:

ConsumerObject consumer = new ConsumerObject ("eugenp"); HttpEntity addConsumerEntity = nieuwe HttpEntity (consument); ResponseEntity addConsumerResp = restTemplate.postForEntity ("// localhost: 8001 / consumenten /", addConsumerEntity, String.class); assertEquals (HttpStatus.CREATED, addConsumerResp.getStatusCode ());

Hier hebben we "eugenp" als nieuwe consument toegevoegd:

{"gebruikersnaam": "eugenp"}

4.3. Verificatie inschakelen

Hier komt de krachtigste functie van Kong, plug-ins.

Nu gaan we een auth-plug-in toepassen op onze proxy-API voor voorraadquery's:

PluginObject authPlugin = nieuw PluginObject ("key-auth"); ResponseEntity enableAuthResp = restTemplate.postForEntity ("// localhost: 8001 / apis / stock-api / plugins", nieuwe HttpEntity (authPlugin), String.class); assertEquals (HttpStatus.CREATED, enableAuthResp.getStatusCode ());

Als we de prijs van een aandeel proberen op te vragen via de proxy-URI, wordt het verzoek afgewezen:

HttpHeaders headers = nieuwe HttpHeaders (); headers.set ("Host", "stock.api"); RequestEntity requestEntity = nieuwe RequestEntity (headers, HttpMethod.GET, nieuwe URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate .exchange (requestEntity, String.class); assertEquals (HttpStatus.UNAUTHORIZED, stockPriceResp.getStatusCode ());

Onthoud dat Eugen is een van onze API-gebruikers, dus we moeten hem toestaan ​​deze API te gebruiken door een authenticatiesleutel toe te voegen:

String consumerKey = "eugenp.pass"; KeyAuthObject keyAuth = nieuwe KeyAuthObject (consumerKey); ResponseEntity keyAuthResp = restTemplate.postForEntity ("// localhost: 8001 / consumenten / eugenp / key-auth", nieuwe HttpEntity (keyAuth), String.class); assertTrue (HttpStatus.CREATED == keyAuthResp.getStatusCode ());

Dan Eugen kan deze API gebruiken zoals voorheen:

HttpHeaders headers = nieuwe HttpHeaders (); headers.set ("Host", "stock.api"); headers.set ("apikey", consumerKey); RequestEntity requestEntity = nieuwe RequestEntity (headers, HttpMethod.GET, nieuwe URI ("// localhost: 8000 / stock / btc")); ResponseEntity stockPriceResp = restTemplate .exchange (requestEntity, String.class); assertEquals ("10000", stockPriceResp.getBody ());

5. Geavanceerde functies

Afgezien van de standaard API-proxy en -beheer, ondersteunt Kong ook API-taakverdeling, clustering, gezondheidscontrole en monitoring, enz.

In dit gedeelte gaan we bekijken hoe u balansverzoeken kunt laden met Kong en hoe u beheer-API's kunt beveiligen.

5.1. Load Balancing

Kong biedt twee strategieën voor load balancing-aanvragen voor back-endservices: een dynamische ringbalancer en een eenvoudige DNS-gebaseerde methode. Om het simpel te houden, we zullen de ring-balancer gebruiken.

Zoals we eerder vermeldden, worden upstreams gebruikt voor load-balancing, en elke upstream kan meerdere doelen hebben.

Kong ondersteunt zowel gewogen round-robin als hash-gebaseerde balansalgoritmen. Standaard wordt het gewogen round-robin-schema gebruikt - waar verzoeken worden afgeleverd bij elk doel op basis van hun gewicht.

Laten we eerst de stroomopwaarts voorbereiden:

UpstreamObject upstream = nieuw UpstreamObject ("stock.api.service"); ResponseEntity addUpstreamResp = restTemplate.postForEntity ("// localhost: 8001 / upstreams", nieuwe HttpEntity (upstream), String.class); assertEquals (HttpStatus.CREATED, addUpstreamResp.getStatusCode ());

Voeg vervolgens twee doelen toe voor de upstream, een testversie met gewicht = 10, en een releaseversie met gewicht = 40:

TargetObject testTarget = nieuw TargetObject ("localhost: 8080", 10); ResponseEntity addTargetResp = restTemplate.postForEntity ("//localhost:8001/upstreams/stock.api.service/targets", nieuwe HttpEntity (testTarget), String.class); assertEquals (HttpStatus.CREATED, ddTargetResp.getStatusCode ()); TargetObject releaseTarget = nieuw TargetObject ("localhost: 9090", 40); addTargetResp = restTemplate.postForEntity ("//localhost:8001/upstreams/stock.api.service/targets", nieuwe HttpEntity (releaseTarget), String.class); assertEquals (HttpStatus.CREATED, addTargetResp.getStatusCode ());

Met de bovenstaande configuratie kunnen we aannemen dat 1/5 van de verzoeken naar de testversie gaat en 4/5 naar de releaseversie:

APIObject stockAPI = nieuw APIObject ("balanced-stock-api", "balanced.stock.api", "//stock.api.service", "/"); HttpEntity apiEntity = nieuwe HttpEntity (stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity ("// localhost: 8001 / apis", apiEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ()); HttpHeaders headers = nieuwe HttpHeaders (); headers.set ("Host", "balanced.stock.api"); for (int i = 0; i <1000; i ++) {RequestEntity requestEntity = new RequestEntity (headers, HttpMethod.GET, new 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);

Merk op dat het gewogen round-robin-schema verzoeken om back-endservices ongeveer in evenwicht brengt met de gewichtsverhouding, zodat alleen een benadering van de verhouding kan worden geverifieerd, weergegeven in de laatste regel van bovenstaande code.

5.2. Beveiliging van de Admin API

Standaard accepteert Kong alleen admin-verzoeken van de lokale interface, wat in de meeste gevallen een voldoende goede beperking is. Maar als we het via andere netwerkinterfaces willen beheren, kunnen we de admin_listen waarde in kong.confen configureer firewallregels.

Of we kunnen Kong laten dienen als proxy voor de Admin API zelf. Stel dat we API's willen beheren met het pad "/ admin-api", dan kunnen we een API als volgt toevoegen:

APIObject stockAPI = nieuw APIObject ("admin-api", "admin.api", "// localhost: 8001", "/ admin-api"); HttpEntity apiEntity = nieuwe HttpEntity (stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity ("// localhost: 8001 / apis", apiEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ());

Nu kunnen we de proxy-beheer-API gebruiken om API's te beheren:

HttpHeaders headers = nieuwe HttpHeaders (); headers.set ("Host", "admin.api"); APIObject baeldungAPI = nieuw APIObject ("baeldung-api", "baeldung.com", "//ww.baeldung.com", "/"); RequestEntity requestEntity = nieuwe RequestEntity (baeldungAPI, headers, HttpMethod.POST, nieuwe URI ("// localhost: 8000 / admin-api / apis")); ResponseEntity addAPIResp = restTemplate .exchange (requestEntity, String.class); assertEquals (HttpStatus.CREATED, addAPIResp.getStatusCode ());

We willen natuurlijk dat de proxy-API wordt beveiligd. Dit kan eenvoudig worden bereikt door authenticatie-plug-in in te schakelen voor de proxy admin API.

6. Samenvatting

In dit artikel hebben we Kong geïntroduceerd - een platform voor microservice API-gateway en gericht op de kernfunctionaliteit ervan - het beheren van API's en routeringsverzoeken naar upstream-servers, evenals op enkele meer geavanceerde functies zoals taakverdeling.

Toch zijn er nog veel meer solide functies die we kunnen verkennen, en we kunnen onze eigen plug-ins ontwikkelen als dat nodig is - u kunt hier doorgaan met het verkennen van de officiële documentatie.

Zoals altijd is de volledige implementatie te vinden op Github.


$config[zx-auto] not found$config[zx-overlay] not found