Mönstret Gateway-samling
Använd en gateway för att slå samman flera enskilda förfrågningar till en enda begäran. Det här mönstret är användbart när en klient måste göra flera anrop till olika serverdelssystem att utföra en åtgärd.
Kontext och problem
För att kunna utföra en aktivitet kanske en klient behöver göra flera anrop till olika serverdelstjänster. Ett program som förlitar sig på många tjänster för att utföra en uppgift måste förbruka resurser på varje begäran. När en ny funktion eller tjänst läggs till i programmet, behövs ytterligare begäranden, vilket ytterligare ökar resurskraven och nätverksanropen. Den här trafikintensiviteten mellan en klient och en serverdel kan påverka programmets prestanda och skalning negativt. Mikrotjänstarkitekturer har gjort att det här problemet har blivit vanligare, eftersom program som är uppbyggda kring många mindre tjänster helt naturligt har en större mängd övergripande tjänstanrop.
I följande diagram skickar klienten begäranden till varje tjänst (1,2,3). Varje tjänst bearbetar begäran och skickar svaret tillbaka till programmet (4,5,6). Via ett mobilnätverk, som vanligtvis har lång svarstid, är det ineffektivt att använda enskilda begäranden på det här sättet, och det kan resultera i en bruten anslutning eller ofullständiga begäranden. Medan varje begäran kan göras parallellt, måste programmet skicka, vänta och bearbeta data för varje begäran på separata anslutningar, vilket ökar risken för fel.

Lösning
Använd en gateway för att minska trafikintensiteten mellan klienten och tjänsterna. Gatewayen tar emot begäranden från klienter, skickar begäranden till olika serverdelssystem, aggregerar resultaten och skickar tillbaka dem till den begärande klienten.
Det här mönstret kan minska antalet begäranden som programmet gör till serverdelstjänster och förbättra programmets prestanda via nätverk med lång svarstid.
I följande diagram skickar programmet en begäran till gatewayen (1). Begäran innehåller ett paket med andra begäranden. Gatewayen delar upp dem och bearbetar varje begäran genom att skicka den till den aktuella tjänsten (2). Varje tjänst returnerar ett svar till gatewayen (3). Gatewayen kombinerar svaren från varje tjänst och skickar svaret till programmet (4). Programmet gör en begäran och får bara ett enda svar från gatewayen.

Problem och överväganden
- Gatewayen bör inte introducera tjänstekoppling över serverdelstjänsterna.
- Gatewayen måste finnas nära serverdelstjänsterna för att minska svarstiden så mycket som möjligt.
- Gatewaytjänsten kan införa en felkritisk systemdel. Se till att gatewayen är korrekt utformad för att uppfylla kraven på programtillgänglighet.
- Gatewayen kan införa en flaskhals. Se till att gatewayen har tillfredsställande prestanda för att hantera belastningen och kan skalas för att uppfylla den förväntade tillväxten.
- Utför belastningstest mot gatewayen för att se till att du inte orsakar sammanhängande fel för tjänsterna.
- Implementera en flexibel design med hjälp av tekniker, till exempel bulkheads (vattentäta skott), kretsbrytning, försök igen och tidsgränser.
- Om ett eller flera tjänsteanrop tar för lång tid, kan det vara möjligt att aktivera tidsgränsen och returnera en partiell datauppsättning. Fundera över hur programmet hanterar det här scenariot.
- Använd asynkront I/O för att se till att en fördröjning på serverdelen inte orsakar prestandaproblem i programmet.
- Implementera distribuerad spårning med korrelations-ID:n för att spåra varje enskilt anrop.
- Övervaka begärandemått och svarsstorlekar.
- Överväg att returnera cachelagrade data som en redundansstrategi för hantering av fel.
- Överväg att placera en aggregeringstjänst bakom gatewayen i stället för att bygga in aggregering i gatewayen. Begärandeaggregering har sannolikt andra resurskrav än andra tjänster i gatewayen och kan påverka gatewayens routnings- och avlastningsfunktioner.
När du ska använda det här mönstret
Använd det här mönstret i sådana här scenarier:
- En klient behöver kommunicera med flera serverdelstjänster för att utföra en åtgärd.
- Klienten kan använda nätverk med betydande svarstid, till exempel mobila nätverk.
Det här mönstret kanske inte lämpar sig om:
- Du bör minska antalet anrop mellan en klient och en enskild tjänst mellan flera åtgärder. I det här scenariot kan det vara bättre att lägga till en batchåtgärd i tjänsten.
- Klienten och programmet finns nära serverdelstjänsterna och svarstiden är inte en viktig faktor.
Exempel
Följande exempel illustrerar hur du skapar en enkel NGINX-tjänst för gatewayaggregering med hjälp av 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"}';
}
}
}