Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den centrala funktionen för en meddelandekö, till exempel Service Bus, är att acceptera meddelanden i en kö eller ett ämne och hålla dem tillgängliga för senare hämtning. Termen skicka används för att beskriva processen för att överföra ett meddelande till meddelandeförmedlaren, medan ta emot refererar till processen för att hämta ett meddelande från meddelandeförmedlaren.
När en klient skickar ett meddelande vill den vanligtvis veta om koordinatorn överförde och accepterade meddelandet korrekt eller om något slags fel uppstod. Den här positiva eller negativa bekräftelsen avgör förståelsen för både klienten och mäklaren om meddelandets överföringstillstånd. Därför kallas det för en uppgörelse.
På samma sätt, när mäklaren överför ett meddelande till en klient, vill både mäklaren och klienten säkerställa en förståelse för om meddelandet har bearbetats framgångsrikt och kan tas bort, eller om leveransen eller bearbetningen misslyckades, vilket innebär att meddelandet eventuellt måste levereras igen.
Slutföra sändningsoperationer
När du använder någon av de Service Bus API-klienter som stöds regleras alltid sändningsåtgärderna till Service Bus explicit. Den här metoden innebär att API-åtgärden väntar på att ett godkännanderesultat från Service Bus ska tas emot innan den slutför sändningsåtgärden.
Om Service Bus avvisar meddelandet innehåller avvisandet en felindikator och text med ett spårnings-ID i det. Avvisandet innehåller också information om huruvida åtgärden kan göras om med någon förväntan på framgång. Klienten omvandlar den här informationen till ett undantag och genererar den till anroparen för sändningsåtgärden. Om meddelandet godkänns slutförs åtgärden tyst.
Advanced Messaging Queuing Protocol (AMQP) är det enda protokoll som stöds för .NET Standard-, Java-, JavaScript-, Python- och Go-klienter. För .NET Framework-klienter kan du använda Service Bus Messaging Protocol (SBMP) eller AMQP. När du använder AMQP-protokollet är meddelandeöverföringar och kvittningar pipelinede och asynkrona. Vi rekommenderar att du använder api-varianterna för asynkrona programmeringsmodeller.
Den 30 september 2026 drar vi tillbaka Azure Service Bus SDK-biblioteken WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus och com.microsoft.azure.servicebus, som inte följer Riktlinjerna för Azure SDK. Vi kommer också att avsluta stödet för SBMP-protokollet, så du kommer inte längre att kunna använda det här protokollet efter den 30 september 2026. Migrera till de senaste Azure SDK-biblioteken, som erbjuder kritiska säkerhetsuppdateringar och förbättrade funktioner, före det datumet.
Även om de äldre biblioteken fortfarande kan användas efter den 30 september 2026 får de inte längre officiell support och uppdateringar från Microsoft. Mer information finns i meddelandet om avveckling av support.
En avsändare kan placera flera meddelanden på tråden i snabb följd utan att vänta på att varje meddelande ska bekräftas, vilket annars skulle vara fallet med SBMP-protokollet eller med HTTP 1.1. Dessa asynkrona sändningsåtgärder slutförs när respektive meddelanden accepteras och lagras, på partitionerade entiteter eller när sändningsåtgärden till olika entiteter överlappar varandra. Slutförandena kan också inträffa utanför den ursprungliga sändordningen.
Strategin för att hantera resultatet av sändningsåtgärder kan ha omedelbar och betydande prestandapåverkan för ditt program. Exemplen i det här avsnittet är skrivna i C# och gäller för Java-terminer, Java-monoer, JavaScript-löften och motsvarande begrepp på andra språk.
Om applikationen genererar mängder meddelanden, som illustreras här med en enkel loop, och väntar på att varje sändningsåtgärd ska slutföras innan nästa meddelande skickas, oavsett om det är synkrona eller asynkrona API-former, slutförs bara 10 meddelanden efter 10 sekventiella fullständiga rundturer för avslut.
Om vi antar svarstid på 70 millisekunder för TCP (Transmission Control Protocol) från en lokal plats till Service Bus och ger bara 10 ms för Service Bus att acceptera och lagra varje meddelande, tar följande loop upp minst 8 sekunder, utan att räkna nyttolastöverföringstid eller potentiella trafikstockningar:
for (int i = 0; i < 10; i++)
{
// creating the message omitted for brevity
await sender.SendMessageAsync(message);
}
Om programmet startar de 10 asynkrona sändningsoperationerna direkt efter varandra och väntar på respektive slutförande separat, överlappar rundtrippstiden för dessa 10 sändningsoperationer. De 10 meddelandena överförs i omedelbar följd och kan till och med dela TCP-ramar. Den totala överföringstiden beror till stor del på den nätverksrelaterade tid det tar att överföra meddelandena till mäklaren.
Med samma antaganden som för föregående loop kan den totala överlappande körningstiden för följande loop ligga långt under en sekund:
var tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
tasks.Add(sender.SendMessageAsync(message));
}
await Task.WhenAll(tasks);
Observera att alla asynkrona programmeringsmodeller använder någon form av minnesbaserad, dold arbetskö som innehåller väntande åtgärder. När sändnings-API:et returnerar lägger sig uppgiften i arbetskön, men protokollhandlingen påbörjas först när det är uppgiftens tur att köras. För kod som tenderar att skicka meddelanden och där tillförlitlighet är ett problem bör du se till att inte för många meddelanden skickas "i luften" samtidigt, eftersom alla skickade meddelanden tar upp minnet tills de sätts på tråden.
Semaforer, som visas i följande kodfragment i C#, är synkroniseringsobjekt som aktiverar sådan begränsning på programnivå vid behov. Denna användning av en semafor gör det möjligt för högst 10 meddelanden att vara i flygning på en gång. En av de 10 tillgängliga semaforlåsen tas innan sändningen och den släpps när sändningen slutförs. Den elfte genomkörningen genom slingan väntar tills minst en av de tidigare sändningsåtgärderna har slutförts och gör sedan låset tillgängligt.
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);
Program bör aldrig initiera en asynkron sändningsåtgärd på ett "fire and forget"-sätt utan att hämta resultatet av åtgärden. "Genom att göra detta kan den interna och osynliga uppgiftskön laddas upp till en punkt där minnesutrymmet överbelastas, och förhindra att programmet upptäcker sändningsfel:"
for (int i = 0; i < 10; i++)
{
sender.SendMessageAsync(message); // DON’T DO THIS
}
Med en låg nivå AMQP-klient accepterar Service Bus även "förutbestämda" överföringar. En förinställd överföring är en "fire-and-forget"-åtgärd för vilken resultatet i vilket fall som helst inte rapporteras tillbaka till klienten och meddelandet anses vara avgjort när det skickas. Bristen på feedback till klienten innebär också att det inte finns några användbara data tillgängliga för diagnostik, vilket innebär att det här läget inte kvalificerar sig för hjälp via Azure Support.
Avsluta mottagningsoperationer
För mottagningsåtgärder stöder Service Bus API-klienterna två explicita lägen: Receive-and-Delete och Peek-Lock.
ReceiveAndDelete
Läget Ta emot och ta bort instruerar meddelandemäklaren att betrakta alla meddelanden som skickas till mottagarklienten som avgjorda vid sändning. Meddelandet förbrukas så snart mäklaren placerar det på nätverket. Om meddelandeöverföringen misslyckas går meddelandet förlorat.
Mottagaren behöver inte vidta några ytterligare åtgärder för meddelandet och saktas inte ned genom att vänta på resultatet av uppgörelsen. Om data i de enskilda meddelandena har ett lågt värde eller bara är meningsfulla under en mycket kort tid är det här läget ett rimligt val.
PeekLock
Peek-Lock-läget talar om för mäklaren att den mottagande klienten uttryckligen vill hantera mottagna meddelanden. Meddelandet är tillgängligt för mottagaren att bearbeta, medan tjänsten har ett exklusivt lås så att andra konkurrerande mottagare inte kan se det. Kön eller prenumerationen definierar ursprungligen låsets varaktighet. Klienten som äger låset kan utöka det med hjälp av åtgärden RenewMessageLockAsync . Mer information om hur du förnyar lås finns i avsnittet Förnya lås i den här artikeln.
När ett meddelande är låst kan andra klienter som tar emot från samma kö eller prenumeration ta på sig lås och hämta nästa tillgängliga meddelanden som inte är under aktivt lås. När låset på ett meddelande uttryckligen släpps eller när låset upphör att gälla går meddelandet tillbaka till framsidan av hämtningsordningen för omleverans.
När mottagarna upprepade gånger släpper meddelandet eller låter låset gå ut under ett definierat antal gånger (maximalt leveransantal), tas meddelandet automatiskt bort från kön eller prenumerationen och placeras i den associerade döda-brev-kön.
Den mottagande klienten initierar kvittningen av ett mottaget meddelande med en positiv bekräftelse när den anropar det fullständiga API:et för meddelandet. Det anger för mäklaren att meddelandet har framgångsrikt bearbetats och tas bort från kön eller prenumerationen. Mäklaren svarar på mottagarens avsikt om uppgörelse med ett svar som anger om uppgörelsen kunde genomföras.
När den mottagande klienten inte kan bearbeta ett meddelande, men vill att meddelandet ska levereras igen, kan den uttryckligen be om att meddelandet släpps och låsas upp omedelbart genom att anropa Abandon API för meddelandet. Eller så kan den göra ingenting och låta låset förfalla.
Om en mottagande klient inte kan bearbeta ett meddelande och vet att det inte hjälper att leverera meddelandet igen och försöker utföra åtgärden igen kan det avvisa meddelandet. Genom att anropa DeadLetter-API :et för meddelandet flyttas meddelandet till kön med obeställbara meddelanden. Det här API:et gör det också möjligt att ange en anpassad egenskap, inklusive en orsakskod som kan hämtas med meddelandet från kön med obeställbara meddelanden.
Anteckning
Det finns bara en dödbrevsunderkö för en kö eller en ämnesprenumeration när du aktiverar funktionen för dödbrev för kön eller prenumerationen.
Ett särskilt fall av förlikning är uppskjutande. Mer information finns i artikeln Meddelandeförsening .
Complete, DeadLetter, eller RenewLock-operationerna kan misslyckas på grund av nätverksproblem, om den låsta låsetiden har gått ut eller om det finns andra villkor på tjänstsidan som förhindrar utförandet. I ett av de senare fallen skickar tjänsten en negativ bekräftelse som visas som ett undantag i API-klienterna. Om orsaken är en trasig nätverksanslutning tas låset bort eftersom Service Bus inte stöder återställning av befintliga AMQP-länkar på en annan anslutning.
Om Complete misslyckas, vilket vanligtvis inträffar i slutet av meddelandehanteringen och i vissa fall efter minuter av bearbetningsarbete, kan det mottagande programmet bestämma om det ska bevara arbetets tillstånd och ignorera samma meddelande när det levereras en andra gång, eller om det ska slänga arbetsresultatet och försöka på nytt när meddelandet levereras igen.
Den typiska mekanismen för att identifiera duplicerade meddelandeleveranser är genom att kontrollera message-id. Avsändaren kan och bör ange message-id ett unikt värde, eventuellt justerat med en identifierare från den ursprungliga processen. En jobbschemaläggare anger message-id troligen till identifieraren för det jobb som den försöker tilldela till en arbetare. Arbetaren ignorerar den andra förekomsten av jobbtilldelningen om jobbet redan är klart.
Att designa för idempotent meddelandehantering blir avgörande. Praktiska tekniker och exempel på hur du uppnår idempotens i distribuerade system finns i den här guiden: Vad betyder Idempotent?
Viktigt!
Det är viktigt att observera att låset som PeekLock eller SessionLock hämtar i meddelandet är flyktigt och kan gå förlorat under följande villkor
- Tjänstuppdatering
- OS-uppdatering
- Ändra egenskaper för entiteten (kö, ämne, prenumeration) medan låset hålls.
- Om Service Bus-klientprogrammet av någon anledning förlorar sin anslutning till Service Bus
- När du använder sessioner och
SessionIdleTimeoutär kortare än varaktigheten för meddelandelåset, och ingen åtgärd utförs på meddelandet inomSessionIdleTimeoutperioden, upphör sessionen att gälla och meddelandelåset går förlorat
När låset går förlorat genererar Azure Service Bus en MessageLockLostException eller SessionLockLostException, som visas i klientprogrammet. I så fall bör klientens standardlogik för omförsök automatiskt sätta igång och försöka utföra åtgärden på nytt. Dessutom ökas inte leveransantalet för meddelandet.
Förnya lås
Standardvärdet för låsvaraktigheten är 1 minut. Du kan ange ett annat värde för låsvaraktigheten på kö - eller prenumerationsnivå . Klienten som äger låset kan förnya meddelandelåset med hjälp av metoder för mottagarobjektet. Du kan också använda funktionen för automatisk låsförnyelse där du anger hur lång tid du vill fortsätta att förnya låset.
Ange låsvaraktigheten till ett värde som är högre än den normala bearbetningstiden, så att du inte behöver förnya låset. Det maximala värdet är 5 minuter, så du måste förnya låset om du vill ha det längre. Att ha en längre låsvaraktighet än vad som behövs har också vissa konsekvenser. När klienten till exempel slutar fungera blir meddelandet endast tillgängligt igen när låsets varaktighet har passerat.
Nästa steg
- Ett särskilt fall av förlikning är uppskjutet. Se meddelandeuppskjutande för detaljer.
- Mer information om obeställbara bokstäver finns i Köer med obeställbara bokstäver.
- Mer information om Service Bus-meddelanden i allmänhet finns i Service Bus-köer, ämnen och prenumerationer.