Používá bránu k agregaci několika jednotlivých požadavků do jednoho. Tento model se hodí, když klient musí k provedení operace volat více různých systémů back-end.
Kontext a problém
Je možné, že klient k provedení jednoho úkolu musí provést několik volání různých služeb back-end. Aplikace, která je kvůli provedení úkolu závislá na mnoha službách, musí na každý požadavek vynaložit prostředky. Když se do aplikace přidá nová funkce nebo služba, jsou potřeba další požadavky. Tím se nároky na prostředky a počet síťových volání ještě zvýší. Tato častá komunikace mezi klientem a back-endem může nepříznivě ovlivnit výkon a škálování aplikace. Kvůli architekturám mikroslužeb je tento problém častější, protože aplikace sestavené kolem mnoha menších služeb mají přirozeně větší počet volání mezi službami.
V následujícím diagramu klient odesílá požadavky do každé služby (1, 2, 3). Každá služba požadavek zpracuje a odešle odpověď zpět do aplikace (4, 5, 6). Přes mobilní síť s obvykle vysokou latencí je používání jednotlivých požadavků tímto způsobem neefektivní a může mít za následek přerušené připojení nebo neúplné požadavky. I když se dá každý požadavek provést paralelně, musí aplikace pro každý požadavek odeslat, čekat a zpracovat data, a to vždy v samostatných připojeních. Tím se zvyšuje riziko selhání.
Řešení
Použijte bránu ke snížení nadměrné komunikace mezi klientem a službami. Brána přijme požadavky klienta, odešle je různým systémům back-end a pak agreguje výsledky a zašle je zpět klientovi.
Tento model může snížit počet požadavků, které aplikace zasílá službám back-end, a zlepšit výkon aplikace v sítích s vysokou latencí.
V následujícím diagramu aplikace odesílá požadavek do brány (1). Požadavek obsahuje balíček dalších požadavků. Brána je rozloží a zpracuje každý požadavek jeho odesláním do příslušné služby (2). Každá služba vrátí odpověď bráně (3). Brána odpovědi z každé služby zkombinuje a odešle odpověď aplikaci (4). Aplikace vytvoří jeden požadavek a z brány obdrží jenom jednu odpověď.
Problémy a důležité informace
- Brány nesmí zavést párování služeb napříč službami back-end.
- Brána se musí nacházet blízko služeb back-end, aby se co nejvíce snížila latence.
- Služba brány může představovat kritický prvek způsobující selhání. Zajistěte, aby byla brána správně navržená a splňovala požadavky aplikace na dostupnost.
- Brána může představovat kritický bod. Zkontrolujte, jestli má brána odpovídající výkon pro zpracování zátěže a je možné ji škálovat, aby zvládala váš předpokládaný růst.
- Proveďte testování s bránou, abyste se ujistili, že nezpůsobíte kaskádová selhání služeb.
- Implementujte odolný návrh s využitím technik jako pažení, jistič, opakovánía časové limity.
- Pokud jedno nebo více volání služby trvá příliš dlouho, může být přijatelné vypršení časového limitu a vrácení částečné sady dat. Zvažte, jak vaše aplikace tento scénář zvládne.
- Používejte asynchronní vstup a výstup, aby zpoždění v back-endu nezpůsobovalo problémy s výkonem v aplikaci.
- Implementujte distribuované trasování pomocí ID korelace ke sledování každého jednotlivého volání.
- Monitorujte metriky požadavků a velikosti odpovědí.
- Zvažte vracení dat uložených v mezipaměti jako strategii pro převzetí služeb při selhání.
- Místo zabudování agregace do brány zvažte umístění agregační služby za bránou. Agregace požadavků bude mít pravděpodobně jiné nároky na prostředky než jiné služby v bráně a může mít vliv na funkce brány týkající se směrování a snižování zátěže.
Kdy se má tento model použít
Tento model použijte v těchto případech:
- Klient musí kvůli provedení operace komunikovat s více službami back-end.
- Klient může používat sítě s výraznou latencí, třeba mobilní sítě.
Tento model nebude pravděpodobně vhodný v následujících případech:
- Chcete snížit počet volání mezi klientem a jednou službou napříč více operacemi. V takovém scénáři může být lepší přidat do služby dávkovou operaci.
- Klient nebo aplikace se nachází blízko back-endových služeb a latence není významným faktorem.
Návrh úloh
Architekt by měl vyhodnotit způsob použití modelu agregace brány v návrhu úlohy k řešení cílů a principů popsaných v pilířích architektury Azure Well-Architected Framework. Příklad:
Pilíř | Jak tento model podporuje cíle pilíře |
---|---|
Rozhodnutí o návrhu spolehlivosti pomáhají vaší úloze stát se odolnou proti selhání a zajistit, aby se po selhání obnovila do plně funkčního stavu. | Tato topologie umožňuje mimo jiné posunout zpracování přechodných chyb z distribuované implementace mezi klienty na centralizovanou implementaci. - RE:07 Přechodné chyby |
Rozhodnutí o návrhu zabezpečení pomáhají zajistit důvěrnost, integritu a dostupnost dat a systémů vaší úlohy. | Tato topologie často snižuje počet dotykových bodů, které má klient se systémem, což snižuje veřejnou plochu a ověřovací body. Agregované back-endy můžou zůstat plně izolované v síti od klientů. - SE:04 Segmentace - SE:08 Posílení zabezpečení |
Efektivita provozu pomáhá poskytovat kvalitu úloh prostřednictvím standardizovaných procesů a týmové soudržnosti. | Tento model umožňuje, aby se back-endová logika vyvíjela nezávisle na klientech, takže můžete měnit řetězené implementace služeb nebo dokonce zdroje dat, aniž byste museli měnit klientské touchpointy. - OE:04 Nástroje a procesy |
Efektivita výkonu pomáhá vaší úloze efektivně splňovat požadavky prostřednictvím optimalizací škálování, dat a kódu. | Tento návrh může mít menší latenci než návrh, ve kterém klient vytváří více připojení. Ukládání do mezipaměti v implementacích agregace minimalizuje volání back-endových systémů. - PE:03 Výběr služeb - Výkon dat PE:08 |
Stejně jako u jakéhokoli rozhodnutí o návrhu zvažte jakékoli kompromisy proti cílům ostatních pilířů, které by mohly být s tímto vzorem zavedeny.
Příklad
Následující příklad ukazuje, jak vytvořit jednoduchou službu NGINX agregace pomocí brány s využitím Lua.
worker_processes 4;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location = /batch {
content_by_lua '
ngx.req.read_body()
-- read json body content
local cjson = require "cjson"
local batch = cjson.decode(ngx.req.get_body_data())["batch"]
-- create capture_multi table
local requests = {}
for i, item in ipairs(batch) do
table.insert(requests, {item.relative_url, { method = ngx.HTTP_GET}})
end
-- execute batch requests in parallel
local results = {}
local resps = { ngx.location.capture_multi(requests) }
for i, res in ipairs(resps) do
table.insert(results, {status = res.status, body = cjson.decode(res.body), header = res.header})
end
ngx.say(cjson.encode({results = results}))
';
}
location = /service1 {
default_type application/json;
echo '{"attr1":"val1"}';
}
location = /service2 {
default_type application/json;
echo '{"attr2":"val2"}';
}
}
}