Návrh bezserverového API: osvědčené postupy

Návrh bezserverového API: Postupy

Účel a kontext: co znamená bezserverové API

Bezserverové (serverless) API je rozhraní postavené na spravovaných cloudových službách, v nichž aplikace běží v krátkodobých funkcích a platí se primárně za skutečné využití. Infrastruktura (škálování, instalace oprav, dostupnost) je abstraktní a automaticky ji spravuje poskytovatel. Cílem je rychlá iterace, vysoká elasticita a optimalizace nákladů, aniž by se obětovala spolehlivost, bezpečnost a pozorovatelnost.

Architektonické stavební prvky

  • API brána: ukončení HTTP(S), směrování na funkce/mikroslužby, omezování provozu, autentizace, metriky, WAF.
  • Funkce (FaaS): bezstavový výpočet (AWS Lambda, Azure Functions, Cloud Functions) spouštěný na požádání.
  • Datová vrstva: spravované databáze (NoSQL/SQL), fronty a streamy (SQS/SNS, EventBridge, Pub/Sub), objektové úložiště.
  • Identita a přístup: správa identity (Cognito/Entra/Identity Platform), OAuth/OIDC, případně mTLS.
  • Observabilita: logy, distribuované trasování, metriky, alarmy a strukturované události.

Návrhové principy bezserverového API

  • Bezstavovost: ve funkci neuchovávejte stav jednotlivých požadavků; ukládejte ho do datových služeb nebo krátkodobých cache s ohledem na TTL.
  • Idempotence: zajistěte opakovatelné zpracování požadavků (opakované pokusy). Požadavky identifikujte pomocí requestIdempotencyKey.
  • Řízení zpětného tlaku: zmírněte špičky pomocí front a asynchronních pracovních postupů.
  • Princip nejnižších oprávnění: nastavte oprávnění s jemnou granularitou na úrovni funkcí, tabulek, témat a bucketů.
  • Konfigurace místo kódu: trasy, omezování provozu, CORS a autentizaci nastavujte v API bráně; běhové parametry spravujte prostřednictvím prostředí a příznaků funkcí.

API brána: návrh rozhraní, limity a CORS

  • Model rozhraní: REST (konzistentní cesty ke zdrojům a metody), HTTP API (rychlejší/levnější varianty) nebo GraphQL pro agregaci.
  • Validace: používejte schémata (OpenAPI/JSON Schema) přímo v bráně; neplatné payloady odmítejte ještě před vyvoláním funkce.
  • Omezování četnosti požadavků: nastavte globální limity i limity pro jednotlivé klíče; při jejich překročení vracejte kód 429 s pravidly pro opakování požadavku a hlavičkou Retry-After.
  • Ukládání do cache: ukládejte odpovědi podle hlavičky cache-control a používejte cache pro jednotlivé trasy; pozor na personalizovaný obsah a tokeny.
  • CORS: povolte pouze nezbytné originy, metody a hlavičky; optimalizujte preflight požadavky krátkou funkcí nebo přímo konfigurací brány.

Studené starty, latence a výkon

  • Studené starty: minimalizujte závislosti, používejte menší běhová prostředí (např. Node.js/Go) a pro kritické trasy využijte předem alokovanou souběžnost.
  • Opětovné využití teplých instancí: vytvářejte klienty DB mimo obslužnou funkci (v globálním rozsahu), aby se připojení zachovalo i mezi jednotlivými vyvoláními.
  • Payloady: používejte kompresi GZIP/Brotli a limity velikosti (soubory nahrávejte přímo do objektového úložiště prostřednictvím předem podepsané URL).
  • Blízkost regionů: vybírejte region API a dat blízko uživatelům; u globálních API zvažte ukončení provozu na okraji sítě a aktivní–aktivní nasazení ve více regionech.

Autentizace a autorizace

  • Standardy: OAuth 2.1/OIDC s JWT nebo PASETO; krátké TTL, rotace klíčů (JWKS), validace audience/issuer.
  • Přístup s jemnou granularitou: mapujte entity na politiky založené na zdrojích v datové vrstvě; claims → ABAC.
  • mTLS/API klíče: používejte pro integrace mezi servery; klíče omezte rozsahem oprávnění a kvótami.
  • Oddělení: veřejné a interní endpointy umístěte na oddělené domény a použijte samostatná pravidla WAF.

Data a transakce v bezserverovém světě

  • NoSQL vs. SQL: předem navrhněte vzory přístupu; NoSQL použijte pro nízkou latenci a masivní škálování, SQL pro komplexní dotazy a ACID.
  • Transakce: pokud nejsou k dispozici distribuované transakce, použijte vzory outbox a saga s kompenzačními akcemi.
  • TTL a archivační politiky: automaticky expirujte záznamy s ohledem na právní požadavky (GDPR/uchovávání dat).
  • Cache: pro často používané cesty využívejte spravované služby pracující s daty v paměti (ElastiCache/Memorystore); cache invalidujte prostřednictvím událostí.

Asynchronní zpracování a pracovní postupy

  • Fronty a témata: oddělte přijetí požadavku od zpracování na pozadí; zajistěte doručení, fronty nedoručených zpráv a exponenciální prodlevy.
  • Orchestrace: používejte stavové automaty (Step Functions/Logic Apps/Workflows) s kompenzačními akcemi, časovými limity a pojistkami proti kaskádovému selhání.
  • Architektura řízená událostmi: emitujte doménové události; konzumenti vytvářejí projekce (vyhledávací index, analytika).

Bezpečnostní opatření

  • WAF a ochrana proti botům: používejte pravidla proti útokům typu injection, anomálnímu provozu a provozu z IP adres s nízkou reputací.
  • Správa tajných údajů: používejte KMS/HSM a trezory tajných údajů; klíče neukládejte do proměnných prostředí bez šifrování a rotace.
  • Odchozí provoz: používejte privátní konektivitu (VPC endpoints/Private Link) a seznam povolených odchozích spojení.
  • Audit: zaznamenávejte všechny změny konfigurace brány, funkcí a politik; používejte neměnné logy.

Observabilita a testovatelnost

  • Strukturované logy: používejte korelační ID napříč bránou, funkcí a DB; do logů nezapisujte žádné tajné údaje.
  • Trasování: používejte OpenTelemetry; rozsahy trasování veďte přes bránu, funkci, DB a frontu.
  • Metriky a SLO: sledujte latenci p99 pro jednotlivé endpointy, míru chyb, studené starty a saturaci souběžnosti; nastavte alarmy s přístupem více časových oken a více úrovní vyčerpávání rozpočtu chyb.
  • Testy: provádějte kontraktační testy rozhraní, integrační testy v sandboxovém účtu a chaos testy (selhání závislostí, zvýšená latence).

Řízení verzí a kompatibility

  • Verzování: používejte /v1, /v2 nebo vyjednávání o obsahu; zachovávejte zpětnou kompatibilitu payloadů.
  • Strategie nasazení: používejte canary a postupné nasazování, příznaky funkcí a automatický návrat k předchozí verzi na základě chybovosti/latence.
  • Kontrakty: používejte OpenAPI jako jediný zdroj pravdy; klientům poskytujte generované SDK.

Náklady a optimalizace

  • Jednotková ekonomika: zohledněte cenu za milion požadavků + GB-s výpočtu + odchozí provoz; modelujte latenci p99 ve vztahu k předem alokované souběžnosti.
  • Často používané cesty: přesouvejte náročné části do asynchronních pipeline; využívejte ukládání do cache a předběžné výpočty.
  • Agregace požadavků: GraphQL/výpočty na okraji sítě snižují počet vyvolání backendových funkcí.

Edge a globální distribuce

  • Funkce na okraji sítě: ověřování tokenů, směrování A/B testů a jednoduché obohacení dat v blízkosti uživatele.
  • Více regionů: provozujte API v režimu aktivní–aktivní s globálním DNS/přepnutím při selhání; konflikty řešte pomocí CRDT/last-write-wins podle domény.
  • CDN: ukládejte požadavky GET do cache; cache invalidujte prostřednictvím událostí a používejte ETag/If-None-Match.

Vzory API a anti-vzory

  • Vzory: požadavek–odpověď pro synchronní čtení, příkaz–asynchronní výsledek pro zápisy, webhook/outbox pro integrace, hromadné operace prostřednictvím úloh.
  • Anti-vzory: dlouhé synchronní běhy funkcí, udržování spojení po dobu několika minut (upřednostněte spravované služby WebSocket), příliš častá komunikace klientů namísto agregace, sdílené globální proměnné používané jako stav.

Schéma payloadů a správné kódy

  • Kontrakty: používejte explicitní typy, jednotky a enumy; verzujte schémata a označujte pole určená k budoucímu odstranění.
  • Kódy: 200/201/202 pro přijetí, 400 pro chybu validace, 401/403 pro autentizaci/autorizaci, 404 pro nenalezený zdroj, 409 pro konflikt, 429 pro překročení limitu, 5xx pro interní chybu; slaďte je s pravidly pro opakování požadavků na straně klienta.

Infrastruktura jako kód a prostředí

  • IaC: používejte deklarativní šablony (CDK/Terraform/Pulumi/SAM/Serverless Framework); verzujte je, provádějte kontrolu změn a detekci odchylek.
  • Prostředí: izolujte účty dev/stage/prod, pro API bránu používejte větev pro každé prostředí; pro PR vytvářejte náhledová prostředí.

Odolnost a spolehlivost

  • Časové limity: nastavujte je kratší než u závislostí; při čtení používejte souběžné spekulativní požadavky; pro externí API využívejte pojistku proti kaskádovému selhání.
  • Opakované pokusy: používejte exponenciální prodlevu s náhodnou odchylkou; zajistěte idempotenci; pro manuální zásah vyhraďte kanál pro nedoručené zprávy.
  • Politika: zajistěte řízené omezení funkcí při selhání (např. vrácením starší hodnoty z cache), záložní řešení a dočasné omezení nekritických funkcí během špiček.

Bezserverové GraphQL API

  • Resolvery: mapujte resolvery na funkce a používejte dataloadery k řešení problému N+1; autorizaci provádějte pro jednotlivá pole na základě claims.
  • Limity: omezte hloubku a složitost dotazu i časové limity jednotlivých resolverů; používejte uložené dotazy.
  • Odběry: používejte spravované kanály WebSocket/HTTP/2; posílejte pouze události s minimálním payloadem.

Audit a soulad s předpisy

  • PII: klasifikujte data, uplatňujte přístup ochrana soukromí již od návrhu, šifrujte data od začátku do konce (při přenosu i v úložišti) a pseudonymizujte je.
  • Dokumentace: udržujte neměnný audit změn konfigurace a přístupů; stanovte zásady uchovávání logů; přístup udělujte podle role a potřeby.

Příklad referenční topologie

  • API Gateway (veřejná) → funkce (autentizace, validace) → fronta (asynchronní příkaz) → orchestrátor (stavový pracovní postup) → DB (NoSQL) a index (vyhledávání).
  • Pro čtení: API Gateway → funkce → cache → DB; TTL a invalidace prostřednictvím událostí.
  • Integrace: outbox v DB → stream → pracovník webhooků → cílové API s opakovanými pokusy a podpisy požadavků.

Kontrolní seznam před nasazením do produkce

  • Schéma OpenAPI/GraphQL je publikováno, kontraktační testy procházejí.
  • Autentizace OIDC, validace aud/iss v bráně, role IAM s nejnižšími oprávněními.
  • Omezování provozu, WAF a CORS jsou nastaveny co nejužším způsobem.
  • Idempotence pro zápisy; pravidla pro opakované pokusy a prodlevy jsou definována.
  • Předem alokovaná souběžnost pro kritické cesty; konektory k DB se znovu používají.
  • Strukturované logy, trasování od začátku do konce, metriky p99, alarmy a provozní příručky.
  • Vydání canary s automatickým návratem k předchozí verzi; příznaky funkcí jsou připravené.
  • Plán obnovy po havárii: multi-AZ, snímky, test obnovy; proběhlo chaos cvičení.

Časté chyby a jak se jim vyhnout

  • Příliš jemné rozdělení funkcí bez sdílené vrstvy knihoven → vysoká latence a náklady. Řešení: sdílené vrstvy, vzor agregátoru.
  • Dlouhé synchronní běhy → překročení časových limitů a nákladná vyvolání funkcí. Řešení: rozdělit běh na kroky a použít orchestraci.
  • Chybějící idempotence → duplicitní objednávky. Řešení: klíče idempotence a podmíněné zápisy.
  • Nekontrolované CORS → bezpečnostní rizika. Řešení: přesně vymezit originy a metody.
  • Příliš volná politika IAM. Řešení: role s oprávněními omezenými na konkrétní zdroje a hranice oprávnění.

Závěr

Dobře navržené bezserverové API stojí na jasných kontraktech, bezstavových funkcích, důsledném zabezpečení a pozorovatelnosti, přičemž pro odolnost a škálování využívá asynchronní vzory. Díky API bráně, architekturám řízeným událostmi, IaC a automatizovaným testům lze dosáhnout rychlých iterací s nízkými provozními náklady a vysokou spolehlivostí. Klíčové je myslet na idempotenci, limity, latenci a správu verzí od prvního dne.