Dela via


Bra metoder för att öka prestanda med hjälp av meddelanden i Service Bus

Den här artikeln beskriver hur du använder Azure Service Bus för att optimera prestanda vid utbyte av asynkrona meddelanden. I den första delen av den här artikeln beskrivs olika mekanismer för att öka prestandan. Den andra delen innehåller vägledning om hur du använder Service Bus på ett sätt som kan erbjuda bästa prestanda i ett visst scenario.

I den här artikeln refererar termen "klient" till alla entiteter som har åtkomst till Service Bus. En klient kan ta rollen som avsändare eller mottagare. Termen "avsändare" används för en Service Bus-köklient eller en ämnesklient som skickar meddelanden till en Service Bus-kö eller ett ämne. Termen "mottagare" refererar till en Service Bus-köklient eller prenumerationsklient som tar emot meddelanden från en Service Bus-kö eller en prenumeration.

Resursplanering och överväganden

Precis som med all teknisk resurs är försiktig planering nyckeln till att säkerställa att Azure Service Bus ger den prestanda som programmet förväntar sig. Rätt konfiguration eller topologi för dina Service Bus-namnområden beror på en mängd faktorer som rör din programarkitektur och hur var och en av Service Bus-funktionerna används.

Prisnivå

Service Bus erbjuder olika prisnivåer. Vi rekommenderar att du väljer lämplig nivå för dina programkrav.

  • Standardnivå – Passar för utvecklar-/testmiljöer eller scenarier med lågt dataflöde där programmen inte är känsliga för begränsning.

  • Premiumnivå – Passar för produktionsmiljöer med olika dataflödeskrav där förutsägbar svarstid och dataflöde krävs. Dessutom kan Service Bus Premium-namnområden skalas automatiskt och kan aktiveras för att hantera toppar i dataflödet.

Kommentar

Om rätt nivå inte väljs finns det risk för att Service Bus-namnområdet överbelastas, vilket kan leda till begränsning.

Begränsning leder inte till dataförlust. Program som använder Service Bus SDK kan använda standardprincipen för återförsök för att säkerställa att data slutligen godkänns av Service Bus.

Beräkna dataflöde för Premium

Data som skickas till Service Bus serialiseras till binär och deserialiseras sedan när de tas emot av mottagaren. Medan program tänker på meddelanden som atomiska arbetsenheter mäter Service Bus dataflöde i termer av byte (eller megabyte).

När du beräknar dataflödeskravet bör du överväga de data som skickas till Service Bus (ingress) och data som tas emot från Service Bus (utgående).

Som förväntat är dataflödet högre för mindre meddelandenyttolaster som kan batchas tillsammans.

Benchmark-värden

Här är ett GitHub-exempel som du kan köra för att se det förväntade dataflödet som du får för ditt Service Bus-namnområde. I våra benchmark-tester observerade vi cirka 4 MB/sekund per meddelandeenhet (MU) av ingress och utgående.

Benchmarkingexemplet använder inga avancerade funktioner, så det dataflöde som dina program observerar är annorlunda, baserat på dina scenarier.

Beräkningsöverväganden

Service Bus kör flera bakgrundsprocesser som kan påverka beräkningsanvändningen. Dessa inkluderar, men är inte begränsade till, timers, scheman och måttutsläpp. Dessutom kräver användning av vissa Service Bus-funktioner beräkningsanvändning som kan minska det förväntade dataflödet. Några av dessa funktioner är -

  1. Sessioner.
  2. Fanning ut till flera prenumerationer på ett enda ämne.
  3. Kör många filter på en enda prenumeration.
  4. Schemalagda meddelanden.
  5. Uppskjutna meddelanden.
  6. Transaktioner.
  7. Deduplicering & se tillbaka på tidsfönstret.
  8. Vidarebefordra till (vidarebefordra från en entitet till en annan).

Om ditt program använder någon av ovanstående funktioner och du inte får det förväntade dataflödet kan du granska cpu-användningsstatistiken och överväga att skala upp Service Bus Premium-namnområdet. Du kan också använda Azure Monitor för att automatiskt skala Service Bus-namnområdet. Vi rekommenderar att du ökar antalet meddelandeenheter (MUS) när CPU-användningen överskrider 70 % för att säkerställa optimala prestanda.

Horisontell partitionering mellan namnområden

Även om det är enklare att skala upp beräkningsenheter (meddelandeenheter) som allokerats till namnområdet, kanske det inte ger någon linjär ökning av dataflödet. Det beror på interna Service Bus-enheter (lagring, nätverk osv.) som kan begränsa dataflödet.

Den renare lösningen i det här fallet är att fragmentera dina entiteter (köer och ämnen) i olika Service Bus Premium-namnområden. Du kan också överväga horisontell partitionering mellan olika namnområden i olika Azure-regioner.

Protokoll

Med Service Bus kan klienter skicka och ta emot meddelanden via något av tre protokoll:

  1. Advanced Message Queuing Protocol (AMQP)
  2. Service Bus Messaging Protocol (SBMP)
  3. Hypertext Transfer Protocol (HTTP)

AMQP är det mest effektiva eftersom det underhåller anslutningen till Service Bus. Den implementerar även batchbearbetning och prefetching. Om inget uttryckligen anges förutsätter allt innehåll i den här artikeln användningen av AMQP eller SBMP.

Viktigt!

SBMP-protokollet är endast tillgängligt för .NET Framework. AMQP är standardvärdet för .NET Standard.

Den 30 september 2026 drar vi tillbaka stödet för SBMP-protokollet för Azure Service Bus, så att du inte längre kan använda det här protokollet efter den 30 september 2026. Migrera till de senaste Azure Service Bus SDK-biblioteken med hjälp av AMQP-protokollet, som erbjuder kritiska säkerhetsuppdateringar och förbättrade funktioner, före det datumet.

Mer information finns i meddelandet om supportavgång.

Välja lämplig Service Bus .NET SDK

Paketet Azure.Messaging.ServiceBus är det senaste Azure Service Bus .NET SDK som är tillgängligt från och med november 2020. Det finns två äldre .NET SDK:er som fortsätter att få kritiska felkorrigeringar fram till den 30 september 2026, men vi rekommenderar starkt att du använder den senaste SDK:t i stället. Läs migreringsguiden för mer information om hur du flyttar från de äldre SDK:erna.

NuGet-paket Primära namnområden Minsta plattformar Protokoll
Azure.Messaging.ServiceBus (senaste) Azure.Messaging.ServiceBus
Azure.Messaging.ServiceBus.Administration
.NET Core 2.0
.NET Framework 4.6.1
Mono 5.4
Universell Windows Platform 10.0.16299
AMQP
HTTP
Microsoft.Azure.ServiceBus Microsoft.Azure.ServiceBus
Microsoft.Azure.ServiceBus.Management
.NET Core 2.0
.NET Framework 4.6.1
Mono 5.4
Universell Windows Platform 10.0.16299
AMQP
HTTP

Mer information om lägsta .NET Standard-plattformsstöd finns i .NET-implementeringsstöd.

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 supportavgång.

Återanvända fabriker och klienter

De Service Bus-klienter som interagerar med tjänsten, till exempel ServiceBusClient, ServiceBusSender, ServiceBusReceiver och ServiceBusProcessor, bör registreras för beroendeinmatning som singletons (eller instansieras en gång och delas). ServiceBusClient kan registreras för beroendeinmatning med ServiceBusClientBuilderExtensions.

Vi rekommenderar att du inte stänger eller tar bort dessa klienter när du har skickat eller tagit emot varje meddelande. Om du stänger eller tar bort de entitetsspecifika objekten (ServiceBusSender/Receiver/Processor) kan du ta bort länken till Service Bus-tjänsten. Om du tar bort ServiceBusClient kan anslutningen till Service Bus-tjänsten brytas.

Den här vägledningen gäller inte för ServiceBusSessionReceiver eftersom dess livslängd är densamma som själva sessionen. För program som arbetar med ServiceBusSessionReceiverrekommenderar vi att du använder en singleton-instans av ServiceBusClient för att acceptera varje session, som sträcker sig över en ny ServiceBusSessionReceiver bindning till den sessionen. När programmet har slutfört bearbetningen av sessionen bör det ta bort den associerade ServiceBusSessionReceiver.

Följande anmärkning gäller för alla SDK:er:

Kommentar

Att upprätta en anslutning är en dyr åtgärd som du kan undvika genom att återanvända samma fabriks- eller klientobjekt för flera åtgärder. Du kan på ett säkert sätt använda dessa klientobjekt för samtidiga asynkrona åtgärder och från flera trådar.

Samtidiga åtgärder

Åtgärder som att skicka, ta emot, ta bort och så vidare tar lite tid. Den här tiden inkluderar den tid som Service Bus-tjänsten tar att bearbeta åtgärden och svarstiden för begäran och svaret. Om du vill öka antalet åtgärder per tid måste åtgärderna köras samtidigt.

Klienten schemalägger samtidiga åtgärder genom att utföra asynkrona åtgärder. Nästa begäran startas innan den tidigare begäran har slutförts. Följande kodfragment är ett exempel på en asynkron sändningsåtgärd:

var messageOne = new ServiceBusMessage(body);
var messageTwo = new ServiceBusMessage(body);

var sendFirstMessageTask =
    sender.SendMessageAsync(messageOne).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #1");
    });
var sendSecondMessageTask =
    sender.SendMessageAsync(messageTwo).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #2");
    });

await Task.WhenAll(sendFirstMessageTask, sendSecondMessageTask);
Console.WriteLine("All messages sent");

Följande kod är ett exempel på en asynkron mottagningsåtgärd.

var client = new ServiceBusClient(connectionString);
var options = new ServiceBusProcessorOptions 
{

      AutoCompleteMessages = false,
      MaxConcurrentCalls = 20
};
await using ServiceBusProcessor processor = client.CreateProcessor(queueName,options);
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;

static Task ErrorHandler(ProcessErrorEventArgs args)
{
    Console.WriteLine(args.Exception);
    return Task.CompletedTask;
};

static async Task MessageHandler(ProcessMessageEventArgs args)
{
    Console.WriteLine("Handle message");
    await args.CompleteMessageAsync(args.Message);
}

await processor.StartProcessingAsync();

Mottagningsläge

När du skapar en kö eller prenumerationsklient kan du ange ett mottagningsläge: Peek-lock eller Ta emot och ta bort. Standardläget för mottagning är PeekLock. När du arbetar i standardläget skickar klienten en begäran om att ta emot ett meddelande från Service Bus. När klienten har tagit emot meddelandet skickar den en begäran om att slutföra meddelandet.

När du ställer in mottagningsläget på ReceiveAndDeletekombineras båda stegen i en enda begäran. De här stegen minskar det totala antalet åtgärder och kan förbättra det övergripande dataflödet för meddelanden. Den här prestandavinsten riskerar att förlora meddelanden.

Service Bus stöder inte transaktioner för mottagnings- och borttagningsåtgärder. Dessutom krävs peek-lock-semantik för alla scenarier där klienten vill skjuta upp eller ta bort ett meddelande.

Prefetching

Med förinläsning kan kön eller prenumerationsklienten läsa in extra meddelanden från tjänsten när den tar emot meddelanden. Klienten lagrar dessa meddelanden i en lokal cache. Cachens storlek bestäms av ServiceBusReceiver.PrefetchCount egenskaperna. Varje klient som aktiverar prefetching underhåller sin egen cache. En cache delas inte mellan klienter. Om klienten startar en mottagningsåtgärd och dess cacheminne är tomt skickar tjänsten en batch med meddelanden. Om klienten startar en mottagningsåtgärd och cachen innehåller ett meddelande tas meddelandet från cacheminnet.

När ett meddelande har förinställts låser tjänsten det förinställda meddelandet. Med låset kan det förinställda meddelandet inte tas emot av en annan mottagare. Om mottagaren inte kan slutföra meddelandet innan låset upphör att gälla blir meddelandet tillgängligt för andra mottagare. Den fördefinierade kopian av meddelandet finns kvar i cacheminnet. Mottagaren som använder den cachelagrade kopian som har upphört att gälla får ett undantag när den försöker slutföra meddelandet. Som standard upphör meddelandelåset att gälla efter 60 sekunder. Det här värdet kan utökas till 5 minuter. Om du vill förhindra förbrukning av meddelanden som har upphört att gälla anger du cachestorleken som är mindre än antalet meddelanden som en klient kan använda inom tidsgränsintervallet för låset.

När du använder standardlåsets förfallotid på 60 sekunder är ett bra värde för 20 gånger den maximala bearbetningshastigheten för PrefetchCount alla mottagare i fabriken. En fabrik skapar till exempel tre mottagare och varje mottagare kan bearbeta upp till 10 meddelanden per sekund. Antalet prefetch får inte överstiga 20 X 3 X 10 = 600. Som standard PrefetchCount är värdet 0, vilket innebär att inga extra meddelanden hämtas från tjänsten.

Förinläsning av meddelanden ökar det totala dataflödet för en kö eller prenumeration eftersom det minskar det totala antalet meddelandeåtgärder eller rundturer. Hämtningen av det första meddelandet tar dock längre tid (på grund av den ökade meddelandestorleken). Det går snabbare att ta emot förinställda meddelanden från cacheminnet eftersom dessa meddelanden redan har laddats ned av klienten.

TTL-egenskapen (time-to-live) för ett meddelande kontrolleras av servern när servern skickar meddelandet till klienten. Klienten kontrollerar inte meddelandets TTL-egenskap när meddelandet tas emot. I stället kan meddelandet tas emot även om meddelandets TTL har skickats medan meddelandet cachelagrades av klienten.

Prefetching påverkar inte antalet fakturerbara meddelandeåtgärder och är endast tillgängligt för Service Bus-klientprotokollet. HTTP-protokollet stöder inte prefetching. Förfunktioner är tillgängliga för både synkrona och asynkrona mottagningsåtgärder.

Prefetching och ReceiveMessagesAsync

Även om begreppen för att förinstallera flera meddelanden tillsammans har liknande semantik som bearbetning av meddelanden i en batch (ReceiveMessagesAsync), finns det några mindre skillnader som måste beaktas när du använder dessa metoder tillsammans.

Prefetch är en konfiguration (eller läge) på ServiceBusReceiver och ReceiveMessagesAsync är en åtgärd (som har semantik för begärandesvar).

När du använder dessa metoder tillsammans bör du överväga följande fall :

  • Prefetch ska vara större än eller lika med det antal meddelanden som du förväntar dig att ta emot från ReceiveMessagesAsync.
  • Prefetch kan vara upp till n/3 gånger så många meddelanden som bearbetas per sekund, där n är standardlåsets varaktighet.

Det finns vissa utmaningar med att ha ett girigt tillvägagångssätt, det vill: att hålla antalet prefetch högt, eftersom det innebär att meddelandet är låst till en viss mottagare. Vi rekommenderar att du provar prefetch-värden som ligger mellan de tröskelvärden som nämnts tidigare och identifierar vad som passar.

Flera köer eller ämnen

Om en enskild kö eller ett ämne inte kan hantera det förväntade antalet meddelanden använder du flera meddelandeentiteter. När du använder flera entiteter skapar du en dedikerad klient för varje entitet i stället för att använda samma klient för alla entiteter.

Fler köer eller ämnen innebär att du har fler entiteter att hantera vid distributionstillfället. Ur ett skalbarhetsperspektiv är det egentligen inte så stor skillnad som du skulle märka eftersom Service Bus redan sprider belastningen över flera loggar internt, så om du använder sex köer eller ämnen eller två köer eller ämnen kommer det inte att göra någon väsentlig skillnad.

Den tjänstnivå som du använder påverkar prestandaöversägbarheten. Om du väljer Standardnivå är dataflöde och svarstid bäst för en delad infrastruktur för flera klientorganisationer. Andra klienter i samma kluster kan påverka ditt dataflöde. Om du väljer Premium får du resurser som ger förutsägbara prestanda och dina flera köer eller ämnen bearbetas ur resurspoolen. Mer information finns i Prisnivåer.

Partitionerade namnområden

När du använder partitionerade premiumnivånamnområden ger flera partitioner med lägre meddelandeenheter (MU) bättre prestanda jämfört med en enda partition med högre processorer.

Scenarier

I följande avsnitt beskrivs vanliga meddelandescenarier och de önskade Service Bus-inställningarna. Dataflödesfrekvensen klassificeras som liten (mindre än 1 meddelande/sekund), måttlig (1 meddelande/sekund eller större men mindre än 100 meddelanden/sekund) och hög (100 meddelanden/sekund eller högre). Antalet klienter klassificeras som små (5 eller färre), måttliga (mer än 5 men mindre än eller lika med 20) och stora (mer än 20).

Kö med högt dataflöde

Mål: Maximera dataflödet för en enskild kö. Antalet avsändare och mottagare är litet.

  • Om du vill öka den totala sändningsfrekvensen i kön använder du flera meddelandefabriker för att skapa avsändare. Använd asynkrona åtgärder eller flera trådar för varje avsändare.
  • Om du vill öka den totala mottagningshastigheten från kön använder du flera meddelandefabriker för att skapa mottagare.
  • Ange antalet prefetch till 20 gånger den maximala bearbetningshastigheten för alla mottagare i en fabrik. Det här antalet minskar antalet Service Bus-klientprotokollöverföringar.

Flera köer med högt dataflöde

Mål: Maximera det totala dataflödet för flera köer. Dataflödet för en enskild kö är måttligt eller högt.

Om du vill få maximalt dataflöde mellan flera köer använder du de inställningar som beskrivs för att maximera dataflödet för en enskild kö. Använd också olika fabriker för att skapa klienter som skickar eller tar emot från olika köer.

Kö med låg svarstid

Mål: Minimera svarstiden för en kö eller ett ämne. Antalet avsändare och mottagare är litet. Dataflödet i kön är litet eller måttligt.

  • Om du använder en enskild klient anger du antalet prefetch till 20 gånger mottagarens bearbetningshastighet. Om flera meddelanden kommer till kön samtidigt överför Service Bus-klientprotokollet dem alla samtidigt. När klienten tar emot nästa meddelande finns det meddelandet redan i den lokala cachen. Cachen ska vara liten.
  • Om du använder flera klienter anger du antalet prefetch till 0. Genom att ange antalet kan den andra klienten ta emot det andra meddelandet medan den första klienten fortfarande bearbetar det första meddelandet.

Kö med ett stort antal avsändare

Mål: Maximera dataflödet för en kö eller ett ämne med ett stort antal avsändare. Varje avsändare skickar meddelanden med en måttlig hastighet. Antalet mottagare är litet.

Service Bus möjliggör upp till 1 000 samtidiga anslutningar till en meddelandeentitet. Den här gränsen tillämpas på namnområdesnivå och köer, ämnen eller prenumerationer begränsas av gränsen för samtidiga anslutningar per namnområde. För köer delas det här numret mellan avsändare och mottagare. Om alla 1 000 anslutningar krävs för avsändare ersätter du kön med ett ämne och en enda prenumeration. Ett ämne accepterar upp till 1 000 samtidiga anslutningar från avsändare. Prenumerationen accepterar ytterligare 1 000 samtidiga anslutningar från mottagare. Om fler än 1 000 samtidiga avsändare krävs ska avsändare skicka meddelanden till Service Bus-protokollet via HTTP.

Följ dessa steg för att maximera dataflödet:

  • Om varje avsändare är i en annan process använder du bara en enda fabrik per process.
  • Ange antalet prefetch till 20 gånger den maximala bearbetningshastigheten för alla mottagare i en fabrik. Det här antalet minskar antalet Service Bus-klientprotokollöverföringar.

Kö med ett stort antal mottagare

Mål: Maximera mottagningshastigheten för en kö eller prenumeration med ett stort antal mottagare. Varje mottagare tar emot meddelanden med en måttlig hastighet. Antalet avsändare är litet.

Service Bus möjliggör upp till 1 000 samtidiga anslutningar till en entitet. Om en kö kräver mer än 1 000 mottagare ersätter du kön med ett ämne och flera prenumerationer. Varje prenumeration har stöd för upp till 1 000 samtidiga anslutningar. Alternativt kan mottagare komma åt kön via HTTP-protokollet.

Följ dessa riktlinjer för att maximera dataflödet:

  • Om varje mottagare är i en annan process använder du bara en enda fabrik per process.
  • Ange antalet prefetch till ett litet värde (till exempel PrefetchCount = 10). Det här antalet hindrar mottagare från att vara inaktiva medan andra mottagare har ett stort antal cachelagrade meddelanden.

Ämne med några prenumerationer

Mål: Maximera dataflödet för ett ämne med några prenumerationer. Ett meddelande tas emot av många prenumerationer, vilket innebär att den kombinerade mottagningsfrekvensen för alla prenumerationer är större än sändningsfrekvensen. Antalet avsändare är litet. Antalet mottagare per prenumeration är litet.

Följ dessa riktlinjer för att maximera dataflödet:

  • Om du vill öka den totala sändningshastigheten i ämnet använder du flera meddelandefabriker för att skapa avsändare. Använd asynkrona åtgärder eller flera trådar för varje avsändare.
  • Om du vill öka den totala mottagningsfrekvensen från en prenumeration använder du flera meddelandefabriker för att skapa mottagare. Använd asynkrona åtgärder eller flera trådar för varje mottagare.
  • Ange antalet prefetch till 20 gånger den maximala bearbetningshastigheten för alla mottagare i en fabrik. Det här antalet minskar antalet Service Bus-klientprotokollöverföringar.

Ämne med ett stort antal prenumerationer

Mål: Maximera dataflödet för ett ämne med ett stort antal prenumerationer. Ett meddelande tas emot av många prenumerationer, vilket innebär att den kombinerade mottagningsfrekvensen för alla prenumerationer är större än sändningsfrekvensen. Antalet avsändare är litet. Antalet mottagare per prenumeration är litet.

Ämnen med ett stort antal prenumerationer exponerar vanligtvis ett lågt övergripande dataflöde om alla meddelanden dirigeras till alla prenumerationer. Det beror på att varje meddelande tas emot många gånger, och alla meddelanden i ett ämne och alla dess prenumerationer lagras i samma arkiv. Antagandet här är att antalet avsändare och antalet mottagare per prenumeration är litet. Service Bus stöder upp till 2 000 prenumerationer per ämne.

Prova följande steg för att maximera dataflödet:

  • Ange antalet prefetch till 20 gånger den förväntade hastighet med vilken meddelanden tas emot. Det här antalet minskar antalet Service Bus-klientprotokollöverföringar.