Přenosy zpráv, zámky a vyrovnání

Centrální funkcí zprostředkovatele zpráv, jako je Service Bus, je přijímat zprávy do fronty nebo tématu a uchovávat je k dispozici pro pozdější načtení. Send je termín, který se běžně používá pro přenos zprávy do zprostředkovatele zpráv. Příjem je termín, který se běžně používá k přenosu zprávy do klienta načítání.

Když klient odešle zprávu, obvykle chce vědět, jestli je zpráva správně přenesena a přijata zprostředkovatelem nebo jestli došlo k nějaké chybě. Toto kladné nebo záporné potvrzení vyřeší pochopení stavu přenosu zprávy jak klientem, tak zprostředkovatelem. Proto se označuje jako vypořádání.

Podobně když zprostředkovatel přenese zprávu klientovi, zprostředkovatel a klient chtějí zjistit, zda je zpráva úspěšně zpracována, a proto může být odebrána, nebo zda doručení nebo zpracování zprávy selhalo, a proto může být zpráva doručena znovu.

Operace odesílání s vyrovnáním

Při použití kteréhokoli z podporovaných klientů rozhraní API služby Service Bus jsou operace odesílání do služby Service Bus vždy explicitně vyřešené, což znamená, že operace rozhraní API čeká na přijetí výsledku doručení služby Service Bus a pak dokončí operaci odeslání.

Pokud služba Service Bus zprávu odmítne, obsahuje odmítnutí indikátor chyby a text s ID sledování. Zamítnutí také obsahuje informace o tom, jestli je možné operaci opakovat s jakýmkoli očekáváním úspěchu. V klientovi jsou tyto informace převedeny na výjimku a vyvolány volající operace odeslání. Pokud je zpráva přijata, operace se bezobslužně dokončí.

Protokol AMQP (Advanced Messaging Queuing Protocol) je jediným protokolem podporovaným pro klienty .NET Standard, Java, JavaScript, Python a Go. Pro klienty rozhraní .NET Framework můžete použít protokol SBMP (Service Bus Messaging Protocol) nebo AMQP. Při použití protokolu AMQP jsou přenosy zpráv a vypořádání kanály a asynchronní. Doporučujeme použít varianty rozhraní API asynchronního programovacího modelu.

30. září 2026 vyřadíme knihovny sady SDK služby Azure Service Bus pro WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus a com.microsoft.azure.servicebus, které nevyhovují pokynům sady Azure SDK. Také ukončíme podporu protokolu SBMP, takže tento protokol už nebudete moct používat po 30. září 2026. Před tímto datem migrujte na nejnovější knihovny sady Azure SDK, které nabízejí důležité aktualizace zabezpečení a vylepšené funkce.

I když starší knihovny je možné používat i po 30. září 2026, nebudou už od Microsoftu dostávat oficiální podporu a aktualizace. Další informace najdete v oznámení o vyřazení podpory.

Odesílatel může na drát umístit několik zpráv v rychlém sledu, aniž by musel čekat na potvrzení každé zprávy, stejně jako v opačném případě s protokolem SBMP nebo s HTTP 1.1. Tyto asynchronní operace odesílání jsou dokončeny, protože příslušné zprávy jsou přijímány a uloženy v dělených entitách nebo při odesílání do různých entit se překrývají. K dokončení může dojít také z původní objednávky odeslání.

Strategie pro zpracování výsledků operací odesílání může mít okamžitý a významný dopad na výkon vaší aplikace. Příklady v této části jsou napsané v jazyce C# a vztahují se na budoucí verze Jazyka Java, monos, přísliby JavaScriptu a ekvivalentní koncepty v jiných jazycích.

Pokud aplikace vytváří shluky zpráv, které jsou zde znázorněny ve smyčce prostého textu, a před odesláním další zprávy, synchronních nebo asynchronních obrazců rozhraní API, bylo očekáván dokončení každé operace odeslání, synchronní nebo asynchronní obrazce rozhraní API, přičemž 10 zpráv se dokončí až po 10 sekvenčních úplných odezvách pro vypořádání.

S předpokládanou latencí odezvy protokolu TCP (Transmission Control Protocol) o velikosti 70 milisekund od místní lokality do služby Service Bus a poskytnutím pouhých 10 ms pro příjem a uložení každé zprávy trvá následující smyčka alespoň 8 sekund, nepočítá se čas přenosu datové části nebo potenciální účinky zahlcení trasy:

for (int i = 0; i < 10; i++)
{
    // creating the message omitted for brevity
    await sender.SendMessageAsync(message);
}

Pokud aplikace spustí 10 asynchronních operací odesílání okamžitě a očekává jejich dokončení samostatně, doba odezvy těchto 10 operací odesílání se překrývají. 10 zpráv se přenáší okamžitě po sobě, potenciálně i sdílení rámců TCP a celková doba přenosu do značné míry závisí na době související se sítí, kterou trvá, než se zprávy přenesou do zprostředkovatele.

Se stejnými předpoklady jako u předchozí smyčky může celková překrývající se doba provádění pro následující smyčku zůstat pod jednou sekundou:

var tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
    tasks.Add(sender.SendMessageAsync(message));
}
await Task.WhenAll(tasks);

Je důležité si uvědomit, že všechny asynchronní programovací modely používají nějakou formu skryté pracovní fronty založené na paměti, která obsahuje čekající operace. Když se rozhraní API pro odesílání vrátí, úloha odeslání se zařadí do fronty v této pracovní frontě, ale gesto protokolu se spustí jenom po spuštění úlohy. Pro kód, který má tendenci nasdílat shluky zpráv a kde spolehlivost je problém, je třeba věnovat pozornost tomu, že ne příliš mnoho zpráv se umístí "do letu" najednou, protože všechny odeslané zprávy zabírají paměť, dokud nejsou vloženy do drátu.

Semaphores, jak je znázorněno v následujícím fragmentu kódu v jazyce C#, jsou synchronizační objekty, které v případě potřeby umožňují omezování na úrovni aplikace. Toto použití semaforu umožňuje maximálně 10 zpráv v letu najednou. Před odesláním se převezme jeden z 10 dostupných zámků semaforu a po dokončení odesílání se uvolní. 11. průchod smyčkou čeká na dokončení alespoň jedné z předchozích operací odeslání a pak zpřístupní jeho zámek:

var semaphore = new SemaphoreSlim(10);

var tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
    await semaphore.WaitAsync();

    tasks.Add(sender.SendMessageAsync(message).ContinueWith((t)=>semaphore.Release()));
}
await Task.WhenAll(tasks);

Aplikace by nikdy neměly inicializovat asynchronní operaci odesílání "fire and forget" způsobem, aniž by načítá výsledek operace. Tím se může načíst vnitřní a neviditelná fronta úloh do vyčerpání paměti a zabránit aplikaci v detekci chyb odeslání:

for (int i = 0; i < 10; i++)
{
    sender.SendMessageAsync(message); // DON’T DO THIS
}

S klientem AMQP nízké úrovně přijímá Service Bus také "přednastavené" přenosy. Přednastavený přenos je operace aktivace a zapomnění, pro kterou se výsledek v obou případech neohlašuje zpět klientovi a zpráva se při odeslání považuje za vyřešenou. Nedostatek zpětné vazby pro klienta také znamená, že pro diagnostiku nejsou dostupná žádná data s možností reakce, což znamená, že tento režim nemá nárok na pomoc prostřednictvím podpora Azure.

Vyrovnání operací příjmu

Pro operace příjmu klienti rozhraní API služby Service Bus umožňují dva různé explicitní režimy: příjem a odstranění a náhled uzamčení.

ReceiveAndDelete

Režim příjmu a odstranění informuje zprostředkovatele, aby při odeslání zvážil všechny zprávy, které odesílá přijímajícímu klientovi. To znamená, že zpráva je považována za spotřebovanou, jakmile ji zprostředkovatel umístí do drátu. Pokud se přenos zprávy nezdaří, zpráva se ztratí.

Nevýhodou tohoto režimu je, že příjemce nemusí provádět další akce se zprávou a také není pomalý čekáním na výsledek vypořádání. Pokud data obsažená v jednotlivých zprávách mají nízkou hodnotu nebo jsou smysluplná jen pro velmi krátkou dobu, je tento režim rozumnou volbou.

PeekLock

Režim Peek-Lock říká zprostředkovateli, že přijímající klient chce urovnat přijaté zprávy explicitně. Zpráva je zpřístupněna pro příjemce ke zpracování, zatímco je uchována pod výhradním zámkem ve službě, aby ji ostatní konkurenční příjemci neviděli. Doba trvání zámku je původně definována na úrovni fronty nebo předplatného a klient, který zámek vlastní, prostřednictvím operace RenewMessageLockAsync . Podrobnosti o obnovení zámků najdete v části Prodloužení platnosti zámků v tomto článku.

Když je zpráva uzamčená, můžou ostatní klienti přijímající ze stejné fronty nebo odběru převzít zámky a načíst další dostupné zprávy, které nejsou pod aktivním zámkem. Pokud je zámek zprávy explicitně uvolněn nebo když zámek vyprší, zpráva se umístí na začátek pořadí načítání nebo blízko něj pro opětovné vydání.

Když příjemce zprávu opakovaně uvolní nebo nechá zámek uplynou po definovaný počet (Maximální počet doručení), zpráva se automaticky odebere z fronty nebo odběru a umístí se do přidružené fronty nedoručených zpráv.

Přijímající klient zahájí vypořádání přijaté zprávy s pozitivním potvrzením při volání kompletního rozhraní API pro zprávu. Označuje zprostředkovatele, že zpráva byla úspěšně zpracována a zpráva je odebrána z fronty nebo odběru. Zprostředkovatel odpoví na záměr vypořádání příjemce odpovědí, která označuje, zda lze vypořádání provést.

Když přijímající klient zprávu nezpracuje, ale chce zprávu znovu nasadit, může explicitně požádat o vydání a odemknutí zprávy okamžitě voláním rozhraní API Pro opuštění zprávy nebo nemůže nic udělat a nechat zámek uplynout.

Pokud přijímající klient nezpracuje zprávu a ví, že opětovné nasazení zprávy a opakování operace nepomůže, může zprávu odmítnout, což ji přesune do fronty nedoručených zpráv voláním rozhraní DeadLetter API ve zprávě, což také umožňuje nastavit vlastní vlastnost včetně kódu důvodu, který lze načíst se zprávou z fronty nedoručených zpráv.

Poznámka:

Dílčí fronta nebo odběr tématu existuje pouze v případě, že je pro frontu nebo odběr tématu povolená funkce nedoručených zpráv.

Zvláštní případ vypořádání je odložení, které je popsáno v samostatném článku.

Operace Completenebo , DeadLettermohou RenewLock selhat kvůli problémům se sítí, pokud vypršela platnost uchovávaného zámku, nebo existují další podmínky na straně služby, které brání vypořádání. V jednom z těchto případů služba odešle negativní potvrzení, které se zobrazí jako výjimka v klientech rozhraní API. Pokud je důvodem přerušené síťové připojení, zámek se zahodí, protože Service Bus nepodporuje obnovení existujících propojení AMQP na jiném připojení.

Pokud Complete dojde k selhání, ke kterému obvykle dochází na samém konci zpracování zpráv a v některých případech po minutách zpracování, může přijímající aplikace rozhodnout, jestli má zachovat stav práce a ignorovat stejnou zprávu, když je doručena podruhé, nebo jestli se má výsledek práce vypsat a opakovat, když je zpráva znovu spuštěna.

Typickým mechanismem pro identifikaci duplicitních dodávek zpráv je kontrola ID zprávy, která může a měla by být nastavena odesílatelem na jedinečnou hodnotu, případně v souladu s identifikátorem z původního procesu. Plánovač úloh by pravděpodobně nastavil ID zprávy na identifikátor úlohy, kterou se pokouší přiřadit k pracovnímu procesu s daným pracovníkem, a pracovní proces by ignoroval druhý výskyt přiřazení úlohy, pokud je tato úloha již dokončena.

Důležité

Je důležité si uvědomit, že zámek, který PeekLock nebo SessionLock získává ve zprávě, je nestálý a může dojít ke ztrátě v následujících podmínkách.

  • Aktualizace služby
  • Aktualizace operačního systému
  • Změna vlastností entity (fronta, téma, předplatné) při podržení zámku

Když dojde ke ztrátě zámku, Azure Service Bus vygeneruje zprávu MessageLockLostException nebo SessionLockLostException, která se zobrazí v klientské aplikaci. V takovém případě by se měla automaticky aktivovat výchozí logika opakování klienta a operace by se měla zopakovat.

Prodloužení platnosti zámků

Výchozí hodnota doby trvání zámku je 1 minuta. Na úrovni fronty nebo předplatného můžete zadat jinou hodnotu doby trvání zámku. Klient, který zámek vlastní, může zámek zprávy obnovit pomocí metod objektu příjemce. Místo toho můžete použít funkci automatického prodlužování uzamčení, kde můžete určit dobu trvání, po kterou chcete zámek obnovit.

Je nejlepší nastavit dobu uzamčení na něco vyššího, než je normální doba zpracování, takže zámek nemusíte obnovovat. Maximální hodnota je 5 minut, takže pokud chcete zámek prodloužit, musíte ho prodloužit. Delší doba uzamčení, než je potřeba, má také určité důsledky. Když třeba váš klient přestane fungovat, zpráva se znovu zpřístupní až po uplynutí doby trvání uzamčení.

Další kroky