Model konkurujících si příjemců
Umožňuje několika souběžným příjemcům zpracovávat zprávy přijaté ve stejném kanálu pro zasílání zpráv. Systém tak může zpracovávat více zpráv souběžně, což umožňuje optimalizovat propustnost, zlepšit škálovatelnost a dostupnost a vyrovnávat zatížení.
Kontext a problém
Očekává se, že aplikace spuštěná v cloudu bude zpracovávat velké množství požadavků. Běžným postupem místo synchronního zpracování každého požadavku je, že aplikace předá požadavky prostřednictvím systému zasílání zpráv jiné službě (službě příjemce), která je zpracuje asynchronně. Tato strategie pomáhá zajistit, aby obchodní logika v aplikaci nebyla během zpracování požadavků blokovaná.
Počet požadavků se může v průběhu času z mnoha důvodů výrazně lišit. Náhlé zvýšení aktivity uživatelů nebo počtu agregovaných požadavků přicházejících z více tenantů může způsobit nepředvídatelné zatížení. V obdobích špičky může být potřeba, aby systém zpracoval stovky požadavků za sekundu, zatímco v jinou dobu může být počet požadavků velmi malý. Navíc povaha akcí zpracovávajících tyto požadavky může být velmi proměnlivá. Při používání jediné instance služby příjemce může docházet k zahlcení této instance požadavky nebo může docházet k přetížení systému zasílání zpráv velkým počtem zpráv přicházejících z aplikace. Aby mohl systém zpracovávat proměnlivé zatížení, může používat více instancí služby příjemce. Tito příjemci ale musí být koordinovaní, aby se zajistilo, že každá zpráva se doručí jenom jednomu příjemci. Zatížení se také musí mezi příjemci vyrovnávat, aby se zabránilo tomu, že se některá instance stane kritickým bodem.
Řešení
K implementaci komunikačního kanálu mezi aplikací a instancemi služby příjemce se používá fronta zpráv. Aplikace odesílá požadavky ve formě zpráv do fronty a instance služby příjemce přijímají zprávy z fronty a zpracovávají je. Tento přístup umožňuje, aby zprávy z libovolné instance aplikace zpracovával stejný fond instancí služby příjemce. Obrázek znázorňuje distribuci úloh do instancí služby pomocí fronty zpráv.

Toto řešení má tyto výhody:
Nabízí systém vyrovnávání zatížení, který umožňuje zpracovávat velké odchylky v množství požadavků odesílaných instancemi aplikace. Fronta funguje jako vyrovnávací prostředek mezi instancemi aplikace a instancemi služby příjemce. Může usnadnit minimalizaci dopadu na dostupnost a odezvu instancí aplikace i služby, jak je popsáno v modelu vyrovnávání zatížení na základě fronty. Zpracování zprávy, která vyžaduje některé dlouhotrvající akce, nezabraňuje souběžnému zpracovávání dalších zpráv jinými instancemi služby příjemce.
Zvyšuje spolehlivost. Pokud odesílatel místo použití tohoto modelu komunikuje přímo s příjemcem, ale nemonitoruje tohoto příjemce, je vysoká pravděpodobnost, že při selhání u příjemce může dojít ke ztrátě zpráv nebo k chybě při jejich zpracování. V tomto modelu se zprávy neodesílají konkrétní instanci služby. Instance služby, která selhala, nezablokuje odesílatele a zprávy může zpracovat kterákoli funkční instance služby.
Nevyžaduje složitou koordinaci mezi příjemci ani mezi odesílatelem a instancemi příjemce. Fronta zpráv zajišťuje, že každá zpráva se doručí aspoň jednou.
Je škálovatelné. Systém může při změně množství zpráv dynamicky zvýšit nebo snížit počet instancí služby příjemce.
Pokud fronta zpráv poskytuje transakční operace čtení, může se zvýšit odolnost. Pokud instance služby příjemce načte a zpracuje zprávu v rámci transakční operace a tato instance služby příjemce selže, může tento model zajistit vrácení dané zprávy do fronty, aby ji mohla načíst a zpracovat jiná instance služby příjemce.
Problémy a důležité informace
Když se budete rozhodovat, jak tento model implementovat, měli byste vzít v úvahu následující skutečnosti:
Pořadí zpráv: Pořadí, ve kterém instance služby příjemce přijímají zprávy, není zaručené a neodráží nutně pořadí, ve kterém se zprávy vytvořily. Navrhněte systém tak, aby se zajistilo, že zpracování zpráv bude idempotentní, protože tak můžete omezit závislost na pořadí, ve kterém se zprávy zpracovávají. Další informace najdete v blogu Jonathana Olivera v příspěvku o modelech idempotence.
Fronty služby Microsoft Azure Service Bus můžou k implementaci zaručeného pořadí zpráv využívat relace zpráv (metoda první dovnitř, první ven). Další informace najdete v článku o modelech zasílání zpráv s využitím relací.
Navrhování služeb z hlediska odolnosti: Pokud je systém navržený tak, aby zjišťoval a restartoval instance služby, které selhaly, může být nutné, aby se zpracování prováděné instancemi služby implementovalo jako idempotentní operace, které minimalizují účinky toho, že se jedna zpráva načte a zpracuje více než jednou.
Zjišťování nezpracovatelných zpráv: Poškozená zpráva nebo úloha vyžadující přístup k prostředkům, které nejsou k dispozici, může způsobit selhání instance služby. Systém by měl bránit návratu takových zpráv do fronty a místo toho zaznamenávat a ukládat podrobnosti o těchto zprávách někam jinam, aby se v případě potřeby daly analyzovat.
Zpracování výsledků: Instance služby zpracovávající zprávu je zcela oddělená od aplikační logiky, která generuje danou zprávu, a nemusí s ní přímo komunikovat. Pokud instance služby generuje výsledky, které je potřeba předávat zpět do aplikační logiky, je nutné, aby byly tyto informace uložené v umístění, které je přístupné pro obě služby. Aby se zabránilo načítání neúplných dat aplikační logikou, je nutné, aby systém indikoval, že zpracování je dokončené.
Pokud používáte Azure, může pracovní proces předávat výsledky zpět do aplikační logiky pomocí vyhrazené fronty odpovědí na zprávy. Je nutné, aby aplikační logika mohla zjišťovat korelaci těchto výsledků s původní zprávou. Tento scénář je podrobně popsaný v úvodu k asynchronnímu zasílání zpráv.
Škálování systému zasílání zpráv: V řešení většího rozsahu se může jedna fronta zpráv zahltit velkým počtem zpráv a stát se kritickým bodem v systému. V této situaci zvažte rozdělení systému zasílání zpráv tak, aby se zprávy od určitých odesílatelů odesílaly do konkrétní fronty, nebo použití vyrovnávání zatížení k distribuci zpráv do více front.
Zajištění spolehlivosti systému zasílání zpráv: Vyžaduje se spolehlivý systém zasílání zpráv, který zaručuje, že když aplikace zprávu zařadí do fronty, nedojde ke ztrátě zprávy. To je nezbytné k tomu, aby se zajistilo, že všechny zprávy se doručí aspoň jednou.
Kdy se má tento model použít
Tento model použijte v těchto případech:
- Zatížení pro aplikaci je rozdělené na úlohy, které lze spustit asynchronně.
- Úlohy jsou nezávislé a můžou běžet paralelně.
- Množství úloh je velmi proměnlivé a vyžaduje škálovatelné řešení.
- Řešení musí poskytovat vysokou dostupnost a musí být odolné pro případ, že se zpracování úlohy nezdaří.
Tento model nebude pravděpodobně vhodný v následujících případech:
- Zatížení aplikace není možné snadno rozdělit na jednotlivé úlohy nebo mezi úlohami se vyskytuje vysoký stupeň závislosti.
- Úlohy je nutné provádět synchronně a logika aplikace musí před pokračováním čekat na dokončení úlohy.
- Úlohy je nutné provádět v určitém pořadí.
Některé systémy zasílání zpráv podporují relace, které umožňují odesílateli seskupovat zprávy a zajistit, aby je všechny zpracoval stejný příjemce. Tento mechanismus lze použít u zpráv s určenou prioritou (pokud se tato funkce podporuje) k implementaci takového typu řazení zpráv, který doručuje zprávy podle pořadí od odesílatele jedinému příjemci.
Příklad
Azure poskytuje Service Bus fronty a triggery front azure function, které jsou v kombinaci přímou implementací tohoto vzoru návrhu cloudu. Azure Functions integrace s Azure Service Bus prostřednictvím triggerů a vazeb. Integrace s Service Bus umožňuje vytvářet funkce, které využívají zprávy fronty odeslané vydavateli. Aplikace pro publikování budou odesílat zprávy do fronty a spotřebiteli implementované jako Azure Functions mohou načítat zprávy z této fronty a zpracovávat je.
Kvůli odolnosti fronta Service Bus umožňuje spotřebiteli použít režim při načítání zprávy z fronty. Tento režim zprávu ve skutečnosti neodebere, ale jednoduše ji skryje před ostatními PeekLock spotřebiteli. Modul runtime Azure Functions přijme zprávu v režimu PeekLock, pokud se funkce úspěšně dokončí, zavolá ve zprávě Complete nebo může zavolat Abandon, pokud funkce selže, a zpráva se znovu zobrazí, což umožní jinému spotřebiteli ji načíst. Pokud funkce běží po dobu delší než časový limit PeekLock, zámek se automaticky obnoví, pokud je funkce spuštěná.
Azure Functions/in můžete škálovat na více nebo více na základě hloubky fronty, a to vše jako konkurující si spotřebiteli fronty. Pokud je vytvořeno více instancí funkcí, všechny tyto funkce soupeří nezávisle na vytažením a zpracováním zpráv.
Podrobné informace o používání front služby Azure Service Bus najdete v tématu Fronty, témata a odběry služby Service Bus.
Informace o triggeru aktivovaném frontou Azure Functions v tématu Trigger azure Service Bus pro Azure Functions.
Následující kód ukazuje, jak můžete vytvořit novou zprávu a odeslat ji do fronty Service Bus fronty pomocí QueueClient instance.
private string serviceBusConnectionString = ...;
...
public async Task SendMessagesAsync(CancellationToken ct)
{
try
{
var msgNumber = 0;
var queueClient = new QueueClient(serviceBusConnectionString, "myqueue");
while (!ct.IsCancellationRequested)
{
// Create a new message to send to the queue
string messageBody = $"Message {msgNumber}";
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
// Write the body of the message to the console
this._logger.LogInformation($"Sending message: {messageBody}");
// Send the message to the queue
await queueClient.SendAsync(message);
this._logger.LogInformation("Message successfully sent.");
msgNumber++;
}
}
catch (Exception exception)
{
this._logger.LogException(exception.Message);
}
}
Následující příklad kódu ukazuje konzumenta napsaného jako funkce Azure v jazyce C#, který čte metadata zpráv a protokoluje Service Bus fronty. Všimněte ServiceBusTrigger si, jak se atribut používá k jeho vytvoření vazby k Service Bus frontě.
[FunctionName("ProcessQueueMessage")]
public static void Run(
[ServiceBusTrigger("myqueue", Connection = "ServiceBusConnectionString")]
string myQueueItem,
Int32 deliveryCount,
DateTime enqueuedTimeUtc,
string messageId,
ILogger log)
{
log.LogInformation($"C# ServiceBus queue trigger function consumed message: {myQueueItem}");
log.LogInformation($"EnqueuedTimeUtc={enqueuedTimeUtc}");
log.LogInformation($"DeliveryCount={deliveryCount}");
log.LogInformation($"MessageId={messageId}");
}
Související informace
Při implementaci tohoto modelu můžou být relevantní následující modely a pokyny:
Úvod k asynchronnímu zasílání zpráv: Fronty zpráv jsou asynchronní komunikační mechanismus. Pokud služba příjemce vyžaduje odeslání odpovědi do aplikace, může být nutná implementace nějakého způsobu zasílání odpovědí. Úvod k asynchronnímu zasílání zpráv poskytuje informace o tom, jak se dá zasílání požadavků a odpovědí implementovat pomocí front zpráv.
Pokyny pro automatické škálování. Instance služby příjemce by mělo být možné spouštět a zastavovat, protože délka fronty, do které aplikace odesílají zprávy, se mění. Automatické škálování může usnadnit udržování propustnosti zpracování v obdobích špičky.
Model výpočtu konsolidace prostředků: Mělo by být možné provést konsolidaci více instancí služby příjemce do jediného procesu, aby se snížily náklady a režie na správu. Model konsolidace výpočtových prostředků popisuje výhody a nevýhody tohoto přístupu.
Model vyrovnávání zatížení na základě fronty. Zavedení fronty zpráv může systému dodat odolnost tím, že instance služby budou moct zpracovávat výrazně proměnlivá množství požadavků z instancí aplikace. Fronta zpráv funguje jako prostředek, který vyrovnává zatížení. Model vyrovnávání zatížení na základě fronty popisuje tento scénář podrobněji.