Model prioritní fronty

Azure Service Bus

Určuje prioritu požadavků odeslaných službám, aby se požadavky s vyšší prioritou přijímaly a zpracovávaly rychleji než požadavky s nižší prioritou. Tento model je užitečný v aplikacích, které jednotlivým klientům nabízí různé záruky úrovní služeb.

Kontext a problém

Aplikace mohou jiným službám delegovat konkrétní úlohy – například provedení zpracování na pozadí nebo integrování s jinými aplikacemi nebo službami. Fronta zpráv v cloudu se obecně používá k delegování úkolů ke zpracování na pozadí. V mnoha případech není pořadí, ve kterém služba přijímá požadavky, důležité. V některých případech je ale důležité určitým žádostem zvýšit prioritu. Tyto požadavky by se měly zpracovávat dříve než žádosti s nižší prioritou, které aplikace dříve odeslala.

Řešení

Fronta obvykle představuje strukturu FIFO (first-in) a příjemci obvykle přijímají zprávy ve stejném pořadí, v jakém se publikují do fronty. Některé fronty zpráv ale podporují prioritní vyřizování. Aplikace, která publikuje zprávu, může přiřadit prioritu. Zprávy ve frontě se automaticky přeuspořádají tak, aby zprávy s vyšší prioritou byly přijaty před těmi, které mají nižší prioritu. Tento diagram znázorňuje proces:

Diagram znázorňující mechanismus řazení front, který podporuje stanovení priorit zpráv

Poznámka:

Většina implementací front zpráv podporuje více příjemců. (Viz Model Konkurenční spotřebitelé.) Počet procesů příjemce je možné vertikálně navýšit nebo snížit na základě poptávky.

U systémů, které fronty s prioritním vyřizováním zpráv nepodporují, je alternativním řešením spravovat samostatnou frontu pro každou prioritu. Aplikace je zodpovědná za odesílání zpráv do příslušné fronty. Každá fronta může mít samostatný fond příjemců. Fronty s vyšší prioritou můžou mít větší fond příjemců, kteří běží na rychlejším hardwaru než fronty s nižší prioritou. Tento diagram znázorňuje použití samostatných front zpráv pro každou prioritu:

Diagram znázorňující použití samostatných front zpráv pro každou prioritu

Variantou této strategie je implementace jednoho fondu příjemců, kteří nejprve kontrolují zprávy ve frontách s vysokou prioritou, a teprve potom, co začnou načítat zprávy z front s nižší prioritou. Existuje několik sémantických rozdílů mezi řešením, které používá jeden fond procesů příjemců (buď s jednou frontou, která podporuje zprávy s různými prioritami nebo s více frontami, které zpracovávají zprávy s jednou prioritou) a řešením, které používá více front se samostatným fondem pro každou frontu.

V přístupu s jedním fondem se zprávy s vyšší prioritou vždy přijímají a zpracovávají před zprávami s nižší prioritou. Zprávy s nízkou prioritou můžou být teoreticky neustále nahrazovány a nemusí být nikdy zpracovány. V přístupu s více fondy se zprávy s nižší prioritou vždy zpracovávají, ale ne tak rychle jako zprávy s vyšší prioritou (v závislosti na relativní velikosti fondů a prostředcích, které jsou pro ně k dispozici).

Použití mechanismu řazení front podle priority může poskytnout následující výhody:

  • Umožňuje aplikacím splňovat obchodní požadavky, které vyžadují stanovení priorit dostupnosti nebo výkonu, například nabízení různých úrovní služeb různým skupinám zákazníků.

  • Může pomoct minimalizovat provozní náklady. Pokud používáte přístup s jednou frontou, můžete v případě potřeby škálovat počet příjemců. Zprávy s vysokou prioritou se stále zpracovávají jako první (i když možná pomaleji) a zprávy s nižší prioritou můžou být delší dobu zpožděné. Pokud implementujete přístup s více frontami zpráv se samostatnými fondy příjemců pro každou frontu, můžete omezit fond příjemců pro fronty s nižší prioritou. Dokonce můžete pozastavit zpracování pro některé fronty s velmi nízkou prioritou zastavením všech příjemců, kteří naslouchají zprávám v těchto frontách.

  • Přístup s více frontami zpráv může díky rozdělení zpráv podle požadavků na zpracování pomoct maximalizovat výkon a škálovatelnost aplikace. Můžete například určit prioritu kritických úkolů tak, aby je zpracovávali příjemci, kteří běží okamžitě, a méně důležité úlohy na pozadí můžou zpracovat příjemci, kteří mají naplánované spouštění v časech, které jsou méně zaneprázdněné.

Důležité informace

Při rozhodování o implementaci tohoto modelu zvažte následující body:

  • Priority definujte v kontextu řešení. Například zprávu s vysokou prioritou je možné definovat jako zprávu, která by se měla zpracovat do 10 sekund. Identifikujte požadavky pro zpracování položek s vysokou prioritou a prostředky, které je potřeba přidělit, aby splňovaly vaše kritéria.

  • Rozhodněte se, jestli musí být všechny položky s vysokou prioritou zpracovány před všemi položkami s nižší prioritou. Pokud zprávy zpracovává jeden fond příjemců, musíte poskytnout mechanismus, který může předejít a pozastavit úlohu, která zpracovává zprávu s nízkou prioritou, pokud zpráva s vyšší prioritou vstoupí do fronty.

  • Při použití jednoho fondu procesů příjemců, které místo vyhrazeného fondu příjemců pro každou frontu používají jeden fond front, musí příjemce použít algoritmus, který zajistí, že vždy obsluhuje zprávy z front s vyšší prioritou před zprávami z front s nižší prioritou.

  • Sledujte rychlost zpracování ve frontách s vysokou a nízkou prioritou, abyste zajistili, že se zprávy v těchto frontách zpracovávají očekávaným tempem.

  • Pokud potřebujete zaručit, že se budou zpracovávat zprávy s nízkou prioritou, implementujte přístup fronty zpráv s více fondy příjemců. Alternativně můžete ve frontě, která podporuje stanovení priorit zpráv, dynamicky zvýšit prioritu zprávy ve frontě podle věku. Tento přístup ale závisí na frontě zpráv, která tuto funkci poskytuje.

  • Strategie použití samostatných front založených na prioritě zpráv se doporučuje pro systémy, které mají několik dobře definovaných priorit.

  • Systém může logicky určit priority zpráv. Například místo explicitních zpráv s vysokou a nízkou prioritou můžete zprávy označit jako "platící zákazník" nebo "neplacený zákazník". Váš systém pak může přidělit více prostředků ke zpracování zpráv od platících zákazníků.

  • Ke kontrole fronty zprávy může dojít k finančním nákladům a nákladům na zpracování. Některé komerční systémy zasílání zpráv například účtují malý poplatek pokaždé, když se zpráva publikuje nebo načte, a pokaždé, když se na zprávy dotazuje fronta. Tyto náklady se zvyšují při kontrole více front.

  • Velikost fondu příjemců můžete dynamicky upravit na základě délky fronty, kterou fond obsluhuje. Další informace najdete v doprovodných materiálech k automatickému škálování.

Kdy se má tento model použít

Tento model je vhodný pro následující scénáře:

  • Systém musí zpracovat více úloh, které mají různé priority.

  • Různí uživatelé nebo tenanti by se měli obsluhovat s různými prioritami.

Návrh úloh

Architekt by měl vyhodnotit způsob použití vzoru Prioritní fronta v návrhu úloh 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. Oddělení položek na základě obchodní priority umožňuje soustředit se na nejdůležitější práci na spolehlivost.

- RE:02 Kritické toky
- RE:07 Úlohy na pozadí
Efektivita výkonu pomáhá vaší úloze efektivně splňovat požadavky prostřednictvím optimalizací škálování, dat a kódu. Oddělení položek na základě obchodní priority umožňuje soustředit se na výkon na většinu práce citlivé na čas.

- PE:09 Kritické toky

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

Azure neposkytuje mechanismus řazení front, který nativně podporuje automatické stanovení priorit zpráv prostřednictvím řazení. Poskytuje ale témata služby Azure Service Bus, předplatná služby Service Bus, která podporují mechanismus řazení front, který poskytuje filtrování zpráv, a řadu flexibilních funkcí, díky kterým je Azure ideální pro většinu implementací front priorit.

Řešení Azure může implementovat téma služby Service Bus, do kterého může aplikace publikovat zprávy, stejně jako by je posílala do fronty. Zprávy mohou obsahovat metadata ve formě vlastních vlastností definovaných aplikací. Odběry služby Service Bus můžete k tématu přidružit a odběry můžou filtrovat zprávy na základě jejich vlastností. Když aplikace odešle zprávu do tématu, zpráva se směruje do příslušného předplatného, kde si ji příjemce může přečíst. Procesy příjemců mohou načítat zprávy z odběru pomocí stejné sémantiky, kterou by používaly s frontou zpráv. (Předplatné je logická fronta.) Tento diagram ukazuje, jak implementovat prioritní frontu pomocí témat a odběrů služby Service Bus:

Diagram znázorňující, jak implementovat prioritní frontu pomocí témat a odběrů služby Service Bus

V předchozím diagramu aplikace vytvoří několik zpráv a přiřadí vlastní vlastnost volanou Priority v každé zprávě. Priority má hodnotu High nebo Low. Aplikace tyto zprávy odešle do tématu. Téma obsahuje dvě přidružená předplatná, která filtrují zprávy na Priority základě vlastnosti. Jedno odběr přijímá zprávy s vlastností nastavenou Priority na High. Ostatní přijímají zprávy s vlastností nastavenou Priority na Low. Fond příjemců čte zprávy z každého odběru. Předplatné s vysokou prioritou má větší fond a tito příjemci můžou běžet na výkonnějších počítačích, které mají více dostupných prostředků než počítače pro fond s nízkou prioritou.

V tomto příkladu není nic zvláštního ohledně označení zpráv s vysokou a nízkou prioritou. Jsou to jednoduše popisky, které jsou v každé zprávě zadané jako vlastnosti. Slouží k směrování zpráv do konkrétního předplatného. Pokud jsou potřeba další priority, je relativně snadné vytvořit více předplatných a fondů procesů příjemců, aby se tyto priority zvládly.

Řešení PriorityQueue na GitHubu je založené na tomto přístupu. Toto řešení obsahuje projekty funkcí Azure Functions s názvem PriorityQueueConsumerHigh a PriorityQueueConsumerLow. Tyto projekty Azure Functions se integrují se službou Service Bus prostřednictvím triggerů a vazeb. Připojí se k různým odběrům definovaným v ServiceBusTrigger příchozích zprávách a reagují na ně.

public static class PriorityQueueConsumerHighFn
{
    [FunctionName("HighPriorityQueueConsumerFunction")]
    public static void Run(
      [ServiceBusTrigger("messages", "highPriority", Connection = "ServiceBusConnection")]string highPriorityMessage,
      ILogger log)
    {
        log.LogInformation($"C# ServiceBus topic trigger function processed message: {highPriorityMessage}");
    }
}

Jako správce můžete nakonfigurovat, kolik instancí může funkce ve službě Aplikace Azure škálovat na více instancí. Můžete to provést tak , že nakonfigurujete možnost Vynutit limit horizontálního navýšení kapacity na webu Azure Portal a nastavíte maximální limit horizontálního navýšení kapacity pro každou funkci. Obvykle potřebujete mít více instancí PriorityQueueConsumerHigh funkce než funkce PriorityQueueConsumerLow . Tato konfigurace zajišťuje, že zprávy s vysokou prioritou se čtou z fronty rychleji než zprávy s nízkou prioritou.

Jiný projekt obsahuje funkci Azure aktivovanou časem, která je nakonfigurovaná tak, PriorityQueueSenderaby běžela každých 30 sekund. Tato funkce se integruje se službou Service Bus prostřednictvím výstupní vazby a odesílá dávky zpráv s nízkou a vysokou prioritou do objektu IAsyncCollector . Když funkce publikuje zprávy do tématu, které je přidružené k odběrům používaným PriorityQueueConsumerHigh funkcemi a PriorityQueueConsumerLow funkcemi, určuje prioritu Priority pomocí vlastní vlastnosti, jak je znázorněno zde:

public static class PriorityQueueSenderFn
{
    [FunctionName("PriorityQueueSenderFunction")]
    public static async Task Run(
        [TimerTrigger("0,30 * * * * *")] TimerInfo myTimer,
        [ServiceBus("messages", Connection = "ServiceBusConnection")] IAsyncCollector<ServiceBusMessage> collector)
    {
        for (int i = 0; i < 10; i++)
        {
            var messageId = Guid.NewGuid().ToString();
            var lpMessage = new ServiceBusMessage() { MessageId = messageId };
            lpMessage.ApplicationProperties["Priority"] = Priority.Low;
            lpMessage.Body = BinaryData.FromString($"Low priority message with Id: {messageId}");
            await collector.AddAsync(lpMessage);

            messageId = Guid.NewGuid().ToString();
            var hpMessage = new ServiceBusMessage() { MessageId = messageId };
            hpMessage.ApplicationProperties["Priority"] = Priority.High;
            hpMessage.Body = BinaryData.FromString($"High priority message with Id: {messageId}");
            await collector.AddAsync(hpMessage);
        }
    }
}

Další kroky

Při implementaci tohoto modelu vám můžou být užitečné následující zdroje informací:

  • Ukázka, která ukazuje tento vzor, na GitHubu

  • Úvod do asynchronního zasílání zpráv. Služba příjemce, která zpracovává žádost, může potřebovat odeslat odpověď do instance aplikace, která žádost odeslala. Tento článek obsahuje informace o strategiích, které můžete použít k implementaci zasílání zpráv požadavků a odpovědí.

  • Pokyny k automatickému škálování Velikost fondu procesů příjemců, které zpracovávají frontu, můžete někdy škálovat na základě délky fronty. Tato strategie vám může pomoct zlepšit výkon, zejména pro fondy, které zpracovávají zprávy s vysokou prioritou.

Při implementaci tohoto modelu vám můžou být užitečné následující vzory:

  • Model konkurenčních spotřebitelů: Pokud chcete zvýšit propustnost front, můžete implementovat více příjemců, kteří paralelně naslouchají stejné frontě a zpracovávají úlohy. Tito příjemci soutěží o zprávy, ale pouze jeden by měl být schopen zpracovat každou zprávu. Tento článek obsahuje další informace o výhodách a nevýhodách implementace tohoto přístupu.

  • Model omezení využití sítě. Omezení využití sítě můžete implementovat použitím front. Prioritní zasílání zpráv můžete použít k zajištění toho, aby žádosti z kritických aplikací nebo aplikací, které běží vysoce hodnotovými zákazníky, byly upřednostněné oproti žádostem od méně důležitých aplikací.