Susipažinkite su Python API šliuzo kūrimu integruojant paslaugų tinklą. Sužinokite apie mikropaslaugas, maršrutizavimą, autentifikavimą ir stebėjimą globaliame kontekste.
Python API šliuzas: paslaugų tinklo (Service Mesh) diegimas šiuolaikinėms architektūroms
Šiuolaikiniame greitai besikeičiančiame skaitmeniniame pasaulyje mikropaslaugų architektūros tapo norma kuriant mastelį keičiančias, atsparias ir lengvai prižiūrimas programas. Šių architektūrų pagrindas yra efektyvios ir saugios komunikacijos tarp paslaugų poreikis. Būtent čia pasitarnauja API šliuzai ir paslaugų tinklai (Service Meshes). Šiame straipsnyje nagrinėjama, kaip sukurti Python pagrindu veikiantį API šliuzą ir integruoti jį su paslaugų tinklu, suteikiant tvirtą sprendimą mikropaslaugų komunikacijos valdymui globaliame kontekste.
API šliuzų ir paslaugų tinklų supratimas
Kas yra API šliuzas?
API šliuzas veikia kaip vienas įėjimo taškas visoms kliento užklausoms, siunčiamoms į mikropaslaugų „backend'ą“. Jis atlieka tokias užduotis kaip:
- Maršrutizavimas: Užklausų nukreipimas į atitinkamą mikropaslaugą.
- Autentifikavimas ir autorizavimas: Kliento tapatybės patikrinimas ir užtikrinimas, kad jis turi reikiamus leidimus.
- Užklausų skaičiaus ribojimas (Rate Limiting): Piktnaudžiavimo prevencija ir sąžiningo paslaugų naudojimo užtikrinimas.
- Užklausų transformavimas: Užklausų modifikavimas prieš siunčiant jas į „backend'ą“.
- Atsakymų agregavimas: Atsakymų iš kelių mikropaslaugų sujungimas į vieną atsakymą.
- Spartinimas (Caching): Uždelsimo mažinimas ir našumo gerinimas.
Įsivaizduokite jį kaip pažangų jūsų programos administratorių, kuris tvarko visą gaunamą srautą ir užtikrina, kad jis saugiai ir efektyviai pasiektų tinkamą vietą. Pavyzdžiui, mobilioji programėlė Australijoje gali siųsti užklausą į API šliuzą, kuris ją nukreipia į kainodaros paslaugą Singapūre ir atsargų valdymo paslaugą Vokietijoje, o prieš grąžindamas rezultatus vartotojui, juos apjungia.
Kas yra paslaugų tinklas (Service Mesh)?
Paslaugų tinklas yra infrastruktūros lygmuo, kuris tvarko komunikaciją tarp paslaugų mikropaslaugų architektūroje. Jis suteikia tokias funkcijas kaip:
- Paslaugų aptikimas (Service Discovery): Automatinis prieinamų paslaugos egzempliorių radimas.
- Srauto valdymas: Srauto tarp paslaugų kontrolė, įskaitant apkrovos balansavimą, maršrutizavimą ir grandinės pertraukimą (circuit breaking).
- Stebimumas: Įžvalgų apie paslaugų našumą ir būklę teikimas.
- Saugumas: Komunikacijos tarp paslaugų šifravimas ir saugumo politikų taikymas.
Paslaugų tinklą paprastai sudaro valdymo plokštuma (pvz., „Istio“) ir duomenų plokštuma (pvz., „Envoy“). Duomenų plokštuma perima visą komunikaciją tarp paslaugų ir taiko valdymo plokštumos apibrėžtas politikas. Įsivaizduokite nematomų kurjerių tinklą, kuris tvarko visą vidinę komunikaciją, užtikrindamas, kad pranešimai būtų pristatyti saugiai, patikimai ir efektyviai. Paslaugų tinklas pagal nutylėjimą įgalina nulinio pasitikėjimo tinklą (zero-trust networking) – kiekviena paslauga autentifikuoja kiekvieną kitą paslaugą, nepriklausomai nuo jų buvimo vietos. Tai ypač svarbu tarptautinėse korporacijose, kurių paslaugos išsidėsčiusios skirtinguose geografiniuose regionuose.
Kodėl verta derinti API šliuzą ir paslaugų tinklą?
Nors tiek API šliuzai, tiek paslaugų tinklai sprendžia mikropaslaugų komunikacijos problemas, jie veikia skirtinguose lygmenyse ir sprendžia skirtingas užduotis. API šliuzas skirtas išorinio srauto valdymui, o paslaugų tinklas – vidinio srauto valdymui. Šių dviejų technologijų derinys suteikia visapusišką sprendimą mikropaslaugų komunikacijos saugumui, valdymui ir stebėjimui tiek klasterio viduje, tiek išorėje.
Pavyzdžiui, apsvarstykime el. prekybos platformą. API šliuzas tvarko užklausas iš interneto ir mobiliųjų programėlių, autentifikuoja vartotojus, taiko užklausų limitus ir nukreipia užklausas į atitinkamas „backend“ paslaugas. Paslaugų tinklas valdo komunikaciją tarp „backend“ paslaugų, užtikrindamas saugų ir patikimą ryšį tarp produktų katalogo, užsakymų valdymo ir mokėjimų apdorojimo paslaugų. API šliuzas gali naudoti išorines autentifikavimo paslaugas, tokias kaip „Okta“ ar „Auth0“, o paslaugų tinklas užtikrina saugią komunikaciją tarp vidinių paslaugų naudodamas abipusį TLS (mTLS).
Python API šliuzo kūrimas
Python, turintis gausią bibliotekų ir karkasų ekosistemą, yra puikus pasirinkimas kuriant API šliuzus. Naudosime kelių karkasų derinį, kad sukurtume mastelį keičiantį ir lengvai prižiūrimą šliuzą.
Karkasų pasirinkimas
- FastAPI: Šiuolaikiškas, didelio našumo žiniatinklio karkasas API kūrimui. FastAPI suteikia automatinį duomenų patvirtinimą, serializavimą ir dokumentacijos generavimą.
- Uvicorn: ASGI serveris, skirtas vykdyti asinchronines Python programas.
- Requests: Biblioteka, skirta siųsti HTTP užklausas į „backend“ paslaugas. Sudėtingesniems scenarijams apsvarstykite galimybę naudoti `httpx`, kuris palaiko asinchroniškumą.
- PyJWT: Biblioteka, skirta darbui su JSON Web Tokens (JWT) autentifikavimui.
Projekto struktūra
api_gateway/ ├── main.py # Pagrindinis programos failas ├── config.py # Konfigūracijos nustatymai ├── routes.py # API maršrutizavimo apibrėžimai ├── auth.py # Autentifikavimo logika ├── utils.py # Pagalbinės funkcijos └── requirements.txt # Projekto priklausomybės
Kodo pavyzdys: main.py
from fastapi import FastAPI, Depends, HTTPException, Request
from fastapi.responses import JSONResponse
import uvicorn
import requests
import jwt
from config import settings
from auth import verify_jwt
from routes import router
app = FastAPI()
app.include_router(router)
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
response = await call_next(request)
return response
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
Kodo pavyzdys: routes.py
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import JSONResponse
import requests
import jwt
from config import settings
from auth import verify_jwt
router = APIRouter()
@router.get("/products/{product_id}")
async def get_product(product_id: int, request: Request, is_authenticated: bool = Depends(verify_jwt)):
# Persiųsti užklausą į produktų paslaugą
product_service_url = f"{settings.product_service_url}/products/{product_id}"
try:
response = requests.get(product_service_url)
response.raise_for_status() # Išmesti HTTPError esant blogiems atsakymams (4xx arba 5xx)
return response.json()
except requests.exceptions.RequestException as e:
raise HTTPException(status_code=500, detail=f"Klaida komunikuojant su produktų paslauga: {e}")
@router.post("/orders")
async def create_order(request: Request, is_authenticated: bool = Depends(verify_jwt)):
# Persiųsti užklausą į užsakymų paslaugą
order_service_url = f"{settings.order_service_url}/orders"
body = await request.json()
try:
response = requests.post(order_service_url, json=body)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
raise HTTPException(status_code=500, detail=f"Klaida komunikuojant su užsakymų paslauga: {e}")
Kodo pavyzdys: auth.py
from fastapi import HTTPException, Depends, Header
import jwt
from config import settings
from typing import Optional
async def verify_jwt(authorization: Optional[str] = Header(None)) -> bool:
if not authorization:
raise HTTPException(status_code=401, detail="Būtina pateikti 'Authorization' antraštę")
try:
token = authorization.split(" ")[1]
jwt.decode(token, settings.jwt_secret, algorithms=[settings.jwt_algorithm])
return True
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Rakto galiojimo laikas baigėsi")
except jwt.InvalidTokenError:
raise HTTPException(status_code=401, detail="Neteisingas raktas")
Kodo pavyzdys: config.py
import os
from typing import Optional
from pydantic import BaseSettings
class Settings(BaseSettings):
product_service_url: str = os.getenv("PRODUCT_SERVICE_URL", "http://localhost:8001")
order_service_url: str = os.getenv("ORDER_SERVICE_URL", "http://localhost:8002")
jwt_secret: str = os.getenv("JWT_SECRET", "secret")
jwt_algorithm: str = os.getenv("JWT_ALGORITHM", "HS256")
settings = Settings()
Konfigūracija
Saugokite konfigūracijos nustatymus, tokius kaip „backend“ paslaugų URL ir autentifikavimo raktus, atskirame konfigūracijos faile (pvz., `config.py`). Naudokite aplinkos kintamuosius skirtingoms aplinkoms konfigūruoti (kūrimo, testavimo, produkcijos).
Autentifikavimas
Įdiekite autentifikavimą naudojant JWT. API šliuzas patikrina JWT prieš persiųsdamas užklausą į „backend“ paslaugą. Šis metodas skatina saugumą ir decentralizaciją. Didesnėms organizacijoms apsvarstykite galimybę integruoti su tapatybės tiekėju, pvz., „Keycloak“ ar „Azure AD“. Tai gali centralizuoti autentifikavimo ir autorizavimo politikas.
Maršrutizavimas
Apibrėžkite maršrutus atskirame faile (pvz., `routes.py`). Naudokite FastAPI maršrutizatoriaus funkciją, kad susietumėte gaunamas užklausas su atitinkamomis „backend“ paslaugomis. Įgyvendinkite maršrutizavimą pagal užklausos kelią, HTTP metodą ir antraštes.
Pavyzdys: API šliuzo dokerizavimas
Sukurkite `Dockerfile`, kad supakuotumėte API šliuzą į konteinerį.
FROM python:3.9-slim-buster WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Integracija su paslaugų tinklu
Python API šliuzo integravimas su paslaugų tinklu, tokiu kaip „Istio“, pagerina saugumą, stebimumą ir srauto valdymą. Daugiausia dėmesio skirsime tam, kaip sukonfigūruoti „Istio“, kad jis valdytų srautą, einantį per API šliuzą.
„Istio“ diegimas
Prieš tęsdami, įsitikinkite, kad jūsų Kubernetes klasteryje yra įdiegtas „Istio“. Diegimo instrukcijas rasite oficialioje „Istio“ dokumentacijoje. Daugelis debesijos paslaugų teikėjų, tokių kaip AWS, „Google Cloud“ ir „Azure“, siūlo valdomas „Istio“ paslaugas, kurios supaprastina diegimą ir valdymą.
„Sidecar“ įdiegimas
„Istio“ naudoja „sidecar“ tarpinį serverį („Envoy“), kad perimtų visą srautą į paslaugą ir iš jos. Norėdami įjungti „Istio“ API šliuzui, turite įdiegti „sidecar“ tarpinį serverį į API šliuzo „pod'ą“. Paprastai tai daroma pridedant anotaciją prie „pod'o“ diegimo aprašo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
labels:
app: api-gateway
spec:
replicas: 1
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
annotations:
sidecar.istio.io/inject: "true" # Įjungti Istio sidecar įdiegimą
spec:
containers:
- name: api-gateway
image: your-api-gateway-image:latest
ports:
- containerPort: 8000
Virtualiosios paslaugos ir šliuzai
„Istio“ naudoja virtualiąsias paslaugas (Virtual Services) ir šliuzus (Gateways) srauto maršrutizavimui valdyti. Šliuzas apibrėžia įėjimo tašką srautui į tinklą, o virtualioji paslauga apibrėžia, kaip srautas nukreipiamas į paslaugas tinkle.
„Istio“ šliuzo kūrimas
Apibrėžkite „Istio“ šliuzą, kad API šliuzas būtų pasiekiamas išoriniam srautui.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: api-gateway-gateway
spec:
selector:
istio: ingressgateway # Naudoti numatytąjį Istio ingress šliuzą
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*" # Pakeiskite savo domenu
Virtualiosios paslaugos kūrimas
Apibrėžkite virtualiąją paslaugą, kad nukreiptumėte srautą iš šliuzo į API šliuzo paslaugą.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-gateway-virtualservice
spec:
hosts:
- "*" # Pakeiskite savo domenu
gateways:
- api-gateway-gateway
http:
- route:
- destination:
host: api-gateway # Paslaugos pavadinimas Kubernetes aplinkoje
port:
number: 8000 # Prievadas, kurio klausosi API šliuzas
Srauto valdymas su „Istio“
„Istio“ suteikia galingas srauto valdymo galimybes, tokias kaip:
- Apkrovos balansavimas: Srauto paskirstymas tarp kelių paslaugos egzempliorių. „Istio“ palaiko įvairius apkrovos balansavimo algoritmus, įskaitant „round robin“, „least connections“ ir „consistent hashing“.
- Srauto padalijimas („Canary“ diegimai): Palaipsnis naujų paslaugos versijų diegimas, siunčiant nedidelę srauto dalį į naują versiją. Tai leidžia išbandyti naujas funkcijas produkcijoje nepaveikiant visų vartotojų.
- Grandinės pertraukimas (Circuit Breaking): Kaskadinių gedimų prevencija automatiškai sustabdant srautą į neveikiančias paslaugas.
- Gedimų įterpimas (Fault Injection): Uždelsimų ar klaidų įterpimas į srautą, siekiant išbandyti jūsų programos atsparumą.
Pavyzdys: „Canary“ diegimas su „Istio“
Norėdami atlikti „canary“ diegimą, galite sukonfigūruoti „Istio“ siųsti nedidelę srauto dalį (pvz., 10 %) į naują API šliuzo versiją.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: api-gateway-virtualservice
spec:
hosts:
- "*" # Pakeiskite savo domenu
gateways:
- api-gateway-gateway
http:
- route:
- destination:
host: api-gateway # 1 versija
port:
number: 8000
weight: 90
- destination:
host: api-gateway-v2 # 2 versija (Canary)
port:
number: 8000
weight: 10
Stebimumas
Stebėjimas ir registravimas yra labai svarbūs norint suprasti jūsų API šliuzo ir „backend“ paslaugų našumą bei būklę. Įdiekite visapusišką stebimumą naudodami tokius įrankius kaip:
- Prometheus: Stebėjimo sistema, skirta metrikoms rinkti ir saugoti. „Istio“ integruojasi su „Prometheus“, kad pateiktų metrikas apie paslaugų srautą, delsą ir klaidas.
- Grafana: Duomenų vizualizavimo įrankis, skirtas prietaisų skydeliams kurti jūsų programai stebėti.
- Jaeger: Paskirstytojo sekimo sistema, skirta užklausoms sekti, kai jos keliauja per jūsų mikropaslaugas. „Istio“ gali automatiškai generuoti visos komunikacijos tarp paslaugų sekimo duomenis.
- Fluentd/Elasticsearch/Kibana (EFK Stack): Registravimo rinkinys, skirtas žurnalams rinkti, saugoti ir analizuoti.
„Istio“ telemetrija
„Istio“ automatiškai renka telemetrijos duomenis apie paslaugų srautą, įskaitant metrikas, žurnalus ir sekimo duomenis. Šiuos duomenis galite naudoti savo API šliuzo ir „backend“ paslaugų našumui bei būklei stebėti. Sukonfigūruokite „Istio“, kad telemetrijos duomenys būtų eksportuojami į „Prometheus“, „Grafana“ ir „Jaeger“.
Specifinės API šliuzo metrikos
Be „Istio“ telemetrijos duomenų, taip pat turėtumėte rinkti specifines API šliuzo metrikas, tokias kaip:
- Užklausų dažnis: Užklausų skaičius per sekundę.
- Atsakymo laikas: Vidutinis laikas, per kurį apdorojama užklausa.
- Klaidų dažnis: Procentinė dalis užklausų, kurios baigiasi klaida.
- Autentifikavimo sėkmės/nesėkmės dažnis: Sėkmingų ir nesėkmingų autentifikavimo bandymų skaičius.
- Spartinimo talpyklos pataikymo dažnis (Cache Hit Rate): Procentinė dalis užklausų, kurios aptarnaujamos iš spartinimo talpyklos.
Saugumo aspektai
Saugumas yra svarbiausias dalykas kuriant API šliuzą. Apsvarstykite šias saugumo priemones:
- Autentifikavimas ir autorizavimas: Įdiekite patikimus autentifikavimo ir autorizavimo mechanizmus, kad apsaugotumėte savo „backend“ paslaugas. Naudokite JWT, OAuth 2.0 ar kitus pramonės standartų protokolus.
- Įvesties patvirtinimas: Patvirtinkite visas gaunamas užklausas, kad išvengtumėte įterpimo atakų.
- Užklausų skaičiaus ribojimas: Įdiekite užklausų limitavimą, kad išvengtumėte piktnaudžiavimo ir paslaugos trikdymo atakų.
- TLS šifravimas: Šifruokite visą komunikaciją tarp API šliuzo ir „backend“ paslaugų naudodami TLS. „Istio“ suteikia automatinį TLS šifravimą naudojant abipusį TLS (mTLS).
- Žiniatinklio programų ugniasienė (WAF): Naudokite WAF, kad apsisaugotumėte nuo įprastų žiniatinklio programų atakų, tokių kaip SQL injekcija ir „cross-site scripting“ (XSS).
- Reguliarūs saugumo auditai: Atlikite reguliarius saugumo auditus, kad nustatytumėte ir pašalintumėte pažeidžiamumus.
Abipusis TLS (mTLS) su „Istio“
„Istio“ gali automatiškai įdiegti mTLS visai komunikacijai tarp paslaugų, užtikrindamas, kad visa komunikacija būtų užšifruota ir autentifikuota. Tai suteikia stiprų apsaugos sluoksnį nuo pasiklausymo ir klastojimo.
Išplėstinės temos
GraphQL šliuzas
Vietoj REST API apsvarstykite galimybę naudoti GraphQL efektyvesniam duomenų gavimui. Įdiekite GraphQL šliuzą naudodami bibliotekas, tokias kaip Graphene ir Ariadne. GraphQL leidžia klientams prašyti tik tų duomenų, kurių jiems reikia, sumažinant perteklinį duomenų gavimą ir gerinant našumą.
gRPC šliuzas
Didelio našumo komunikacijai tarp paslaugų apsvarstykite galimybę naudoti gRPC. Įdiekite gRPC šliuzą, kad gRPC paslaugos būtų pasiekiamos išoriniams klientams. Naudokite įrankius, tokius kaip grpc-gateway, kad generuotumėte RESTful API iš gRPC apibrėžimų.
Beserveris API šliuzas
Įdiekite savo API šliuzą kaip beserverę funkciją naudodami platformas, tokias kaip AWS Lambda, Google Cloud Functions ar Azure Functions. Beserveriai API šliuzai siūlo mastelio keitimą, ekonomiškumą ir sumažintas eksploatacijos išlaidas. Pavyzdžiui, API šliuzas gali būti integruotas su AWS Lambda funkcijomis, parašytomis Python kalba, kad apdorotų užklausas. Šis beserveris metodas gali žymiai sumažinti infrastruktūros išlaidas.
Išvada
Python API šliuzo kūrimas integruojant paslaugų tinklą suteikia tvirtą ir mastelį keičiantį sprendimą mikropaslaugų komunikacijai valdyti. Derindami API šliuzų ir paslaugų tinklų privalumus, galite pasiekti geresnį saugumą, stebimumą ir srauto valdymą. Ši architektūra puikiai tinka šiuolaikinėms, debesijos technologijomis pagrįstoms programoms, kurioms reikalingas didelis prieinamumas, mastelio keitimas ir saugumas. Nepamirškite atsižvelgti į savo specifinius reikalavimus ir pasirinkti įrankius bei technologijas, kurios geriausiai atitinka jūsų poreikius. Pavyzdžiui, mažesnė įmonė gali rinktis „Kong“ kaip API šliuzą ir „Linkerd“ kaip paslaugų tinklą dėl jų santykinai paprasto naudojimo, o didesnė įmonė gali pasirinkti „Istio“ ir pagal užsakymą sukurtą Python API šliuzą, kad galėtų smulkmeniškai kontroliuoti kiekvieną savo architektūros aspektą. Tinkamų įrankių pasirinkimas ir kruopštus minėtų saugumo aspektų įgyvendinimas yra būtini sėkmei. Be to, nuolatinis stebėjimas ir prisitaikymas yra labai svarbūs norint išlaikyti tvirtą ir saugų API šliuzą nuolat kintančioje technologijų aplinkoje.