Dela via


Partitionerade köer och ämnen

Azure Service Bus använder flera meddelandeköer för att bearbeta meddelanden och flera meddelandearkiv för att lagra meddelanden. En konventionell kö eller ett ämne hanteras av en enda meddelandeförmedlare och ett meddelandelager. Med Service Bus-partitioner kan köer och ämnen, eller meddelandeentiteter, partitioneras mellan flera meddelandeköer och meddelandearkiv. Partitionering innebär att det totala dataflödet för en partitionerad entitet inte längre begränsas av prestanda för en enda meddelandekö eller meddelandearkiv. Dessutom gör ett tillfälligt avbrott i en meddelandelagring inte en partitionerad kö eller ett ämne otillgängligt. Partitionerade köer och ämnen kan innehålla alla avancerade Service Bus-funktioner, till exempel stöd för transaktioner och sessioner.

Anteckning

Det finns vissa skillnader mellan SKU:n Basic/Standard och Premium när det gäller partitionering.

  • Partitionering är tillgänglig vid entitetens skapande för alla köer och ämnen i Basic eller Standard SKU:er. Ett namnområde kan ha både partitionerade och icke-partitionerade entiteter.
  • Partitionering är tillgänglig vid skapande av namnrymden för Premium-meddelande-SKU:n, och alla köer och ämnen i den namnrymden partitioneras. Alla tidigare migrerade partitionerade entiteter i Premium-namnområden fortsätter att fungera som förväntat.
  • När du aktiverar partitionering i SKU:erna Basic eller Standard skapar du alltid 16 partitioner.
  • När du aktiverar partitionering i Premium SKU anger du antalet partitioner när namnområdet skapas.

Du kan inte ändra partitioneringsalternativet för ett befintligt namnområde, en kö eller ett ämne. Du kan bara ange alternativet när du skapar entiteten.

Hur det fungerar

Varje partitionerad kö eller ämne består av flera partitioner. Varje partition lagras i ett annat meddelandearkiv och hanteras av en annan meddelandekö. När du skickar ett meddelande till en partitionerad kö eller ett ämne tilldelar Service Bus meddelandet till en av partitionerna. Service Bus väljer partitionen slumpmässigt eller använder en partitionsnyckel som avsändaren anger.

När en klient vill ta emot ett meddelande från en partitionerad kö, eller från en prenumeration på ett partitionerat ämne, kontrollerar Service Bus alla partitioner för meddelanden. Det returnerar det första meddelandet som det får från något av meddelandearkiven till mottagaren. Service Bus cachelagrar de andra meddelandena och returnerar dem när de tar emot fler mottagningsbegäranden. En mottagande klient känner inte till partitioneringen. Det klientinriktade beteendet för en partitionerad kö eller ett ämne (till exempel läsa, slutföra, skjuta upp, deadletter, prefetching) är identiskt med beteendet för en vanlig entitet.

Peek-operationen på en icke-partitionerad entitet returnerar alltid det äldsta meddelandet, men detta gäller inte för en partitionerad entitet. I stället returneras det äldsta meddelandet i en av de partitioner vars meddelandemäklare svarade först. Det finns ingen garanti för att det returnerade meddelandet är det äldsta i alla partitioner.

Det kostar inget extra när du skickar ett meddelande till eller tar emot ett meddelande från en partitionerad kö eller ett ämne.

Anteckning

Granskningsåtgärden returnerar det äldsta meddelandet från partitionen baserat på dess sekvensnummer. För partitionerade entiteter är sekvensnumret relativt partitionen. Mer information finns i Meddelandesekvensering och tidsstämplar.

Användning av partitionsnycklar

När du lägger till ett meddelande i en partitionerad kö eller ett ämne söker Service Bus efter förekomsten av en partitionsnyckel. Om den hittar en väljer den partitionen baserat på den nyckeln. Om den inte hittar någon partitionsnyckel väljer den partitionen baserat på en intern algoritm.

Använda en partitionsnyckel

Vissa scenarier, till exempel sessioner eller transaktioner, kräver att meddelanden lagras i en specifik partition. Alla dessa scenarier kräver användning av en partitionsnyckel. Service Bus tilldelar alla meddelanden som använder samma partitionsnyckel till samma partition. Om partitionen är tillfälligt otillgänglig returnerar Service Bus ett fel.

Beroende på scenariot används olika meddelandeegenskaper som en partitionsnyckel:

SessionId: Om ett meddelande har angett sessions-ID-egenskapen använder Service Bus den som partitionsnyckel. På så sätt hanterar samma meddelandekö alla meddelanden som tillhör samma session. Med hjälp av sessioner garanterar Service Bus meddelandeordning samt konsekvensen av sessionstillstånd.

PartitionKey: Om ett meddelande har egenskapen partitionsnyckel, men inte sessions-ID-egenskapen, använder Service Bus egenskapsvärdet för partitionsnyckeln som partitionsnyckel. Om meddelandet har både sessions-ID:t och partitionsnyckelns egenskaper inställda måste båda egenskaperna vara identiska. Om egenskapen partitionsnyckel är inställd på ett annat värde än sessions-ID-egenskapen returnerar Service Bus ett ogiltigt åtgärdsfel. Använd egenskapen partitionsnyckel om en avsändare skickar icke-sessionsmedvetna transaktionsmeddelanden. Partitionsnyckeln ser till att samma meddelandekö hanterar alla meddelanden som skickas i en transaktion.

MessageId: Om du skapar kön eller ämnet med dubblettidentifieringsfunktionen och inte anger sessions-ID eller partitionsnyckelegenskaper fungerar egenskapsvärdet för meddelande-ID som partitionsnyckel. (Microsoft-klientbiblioteken tilldelar automatiskt ett meddelande-ID om det sändande programmet inte gör det.) I det här fallet hanterar samma meddelandekö alla kopior av samma meddelande. Med det här ID:t kan Service Bus identifiera och eliminera dubblettmeddelanden. Om dubblettidentifieringsfunktionen inte är aktiverad betraktar Service Bus inte meddelande-ID-egenskapen som en partitionsnyckel.

Använder inte en partitionsnyckel

Om du inte anger en partitionsnyckel distribuerar Service Bus meddelanden i ett turordningssätt till alla partitioner i den partitionerade kön eller det partitionerade topic. Om den valda partitionen inte är tillgänglig tilldelar Service Bus meddelandet till en annan partition. På så sätt lyckas sändningsåtgärden trots att ett meddelandearkiv tillfälligt inte är tillgängligt. Du uppnår dock inte den garanterade ordning som en partitionsnyckel tillhandahåller.

En mer ingående diskussion om kompromissen mellan tillgänglighet (ingen partitionsnyckel) och konsekvens (med hjälp av en partitionsnyckel) finns i Tillgänglighet och konsekvens i Event Hubs. Förutom att partitions-ID inte exponeras för användare gäller den här informationen lika för partitionerade Service Bus-entiteter.

Om du vill ge Service Bus tillräckligt med tid för att skicka meddelandet till en annan partition måste tidsgränsvärdet som anges av klienten som skickar meddelandet vara större än 15 sekunder. Standardvärdet på 60 sekunder rekommenderas.

En partitionsnyckel "fäster" ett meddelande till en specifik partition. Om meddelandearkivet som innehåller den här partitionen inte är tillgängligt returnerar Service Bus ett fel. I avsaknad av en partitionsnyckel kan Service Bus välja en annan partition och åtgärden lyckas. Ange därför inte en partitionsnyckel om den inte krävs.

Avancerade ämnen

Använda transaktioner med partitionerade entiteter

Meddelanden som du skickar som en del av en transaktion måste ange en partitionsnyckel. Nyckeln kan vara en av följande egenskaper: sessions-ID, partitionsnyckel eller meddelande-ID. Alla meddelanden som du skickar som en del av samma transaktion måste ange samma partitionsnyckel. Om du försöker skicka ett meddelande utan en partitionsnyckel i en transaktion returnerar Service Bus ett ogiltigt åtgärdsfel. Om du försöker skicka flera meddelanden inom samma transaktion som har olika partitionsnycklar returnerar Service Bus ett ogiltigt åtgärdsfel. Till exempel:

CommittableTransaction committableTransaction = new CommittableTransaction();
using (TransactionScope ts = new TransactionScope(committableTransaction))
{
    ServiceBusMessage msg = new ServiceBusMessage("This is a message");
    msg.PartitionKey = "myPartitionKey";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

Om du anger någon av de egenskaper som fungerar som en partitionsnyckel fäster Service Bus meddelandet på en specifik partition. Det här beteendet inträffar oavsett om du använder en transaktion eller inte. Ange inte en partitionsnyckel om det inte behövs.

Använd transaktioner i sessioner med partitionerade entiteter

Om du vill skicka ett transaktionsmeddelande till ett sessionsmedveten ämne eller kö anger du sessions-ID-egenskapen för meddelandet. Om du anger egenskapen partitionsnyckel måste den vara identisk med sessions-ID-egenskapen. Om de skiljer sig returnerar Service Bus ett ogiltigt åtgärdsfel.

Till skillnad från vanliga (icke-partitionerade) köer eller ämnen kan du inte använda en enda transaktion för att skicka flera meddelanden till olika sessioner. Om du försöker utföra den här åtgärden returnerar Service Bus ett ogiltigt åtgärdsfel. Till exempel:

CommittableTransaction committableTransaction = new CommittableTransaction();
using (TransactionScope ts = new TransactionScope(committableTransaction))
{
    ServiceBusMessage msg = new ServiceBusMessage("This is a message");
    msg.SessionId = "mySession";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

Automatisk vidarebefordran av meddelanden med partitionerade entiteter

Service Bus stöder automatisk vidarebefordran av meddelanden från, till eller mellan partitionerade entiteter. Du kan aktivera den här funktionen när du skapar eller uppdaterar köer och prenumerationer. Mer information finns i Aktivera vidarebefordran av meddelanden. Om meddelandet anger en partitionsnyckel (sessions-ID, partitionsnyckel eller meddelande-ID) används partitionsnyckeln för målentiteten.

Överväganden och riktlinjer

  • Funktioner med hög konsekvens: Om en entitet använder funktioner som sessioner, dubblettidentifiering eller explicit kontroll över partitioneringsnyckeln dirigeras alltid meddelandeåtgärderna till en specifik partition. Om någon av partitionerna upplever hög trafik eller om det underliggande arkivet är ohälsosamt, kommer dessa operationer att misslyckas och tillgängligheten blir sämre. På det hela taget är konsekvensen fortfarande mycket högre än för icke-partitionerade entiteter. Endast en delmängd av trafiken upplever problem, i motsats till all trafik. Mer information finns i den här diskussionen om tillgänglighet och konsekvens.
  • Hantering: Åtgärder som Skapa, Uppdatera och Ta bort måste utföras på alla partitioner i entiteten. Om en partition inte är felfri kan det leda till fel för dessa åtgärder. För åtgärden Hämta måste information som antal meddelanden aggregeras från alla partitioner. Om en partition inte är felfri rapporteras statusen för entitetstillgänglighet som begränsad.
  • Scenarier med låg volymmeddelande: För sådana scenarier, särskilt när du använder HTTP-protokollet, kan du behöva utföra flera mottagningsåtgärder för att få alla meddelanden. För att ta emot begäranden utför klientdelen en mottagning på alla partitioner och cachelagrar alla svar som den tar emot. En efterföljande mottagningsbegäran på samma anslutning drar nytta av denna cachelagring och latensen är lägre. Men om du har flera anslutningar eller använder HTTP upprättas en ny anslutning för varje begäran. Därför finns det ingen garanti för att den hamnar på samma nod. Om alla befintliga meddelanden är låsta och cachelagrade i en annan klientdel returnerar mottagningsåtgärden null. Meddelanden upphör så småningom att gälla och du kan ta emot dem igen. HTTP keep-alive rekommenderas. När du använder partitionering i scenarier med låg volym kan det ta längre tid än förväntat att ta emot åtgärder. Använd därför inte partitionering i dessa scenarier. Ta bort befintliga partitionerade entiteter och återskapa dem med partitionering inaktiverat för att förbättra prestanda.
  • Bläddra/granska meddelanden: Granskningsåtgärden returnerar inte alltid det antal meddelanden som efterfrågas. Två vanliga orsaker förklarar det här beteendet. En orsak är att den aggregerade storleken på samlingen med meddelanden överskrider den maximala storleken. En annan orsak är att en partition i partitionerade köer eller ämnen kanske inte har tillräckligt med meddelanden för att returnera det begärda antalet meddelanden. Om ett program i allmänhet vill granska eller bläddra i ett visst antal meddelanden bör det anropa granskningsåtgärden upprepade gånger tills det hämtar det antalet meddelanden, eller så finns det inga fler meddelanden att granska. Mer information, inklusive kodexempel, finns i Meddelandebläddring.

Begränsningar för partitionerade entiteter

För närvarande medför Service Bus följande begränsningar för partitionerade köer och ämnen:

  • Partitionerade köer och ämnen stöder inte att skicka meddelanden som tillhör olika sessioner i en enda transaktion.
  • Service Bus tillåter för närvarande upp till 100 partitionerade köer eller ämnen per namnområde för SKU:n Basic och Standard. Varje partitionerad kö eller ämne räknas mot kvoten på 10 000 entiteter per namnområde.

Nästa steg

Du kan aktivera partitionering med hjälp av Azure Portal, PowerShell, CLI, Resource Manager-mall, .NET, Java, Python och JavaScript. Mer information finns i Aktivera partitionering (Basic/Standard).

Mer information om huvudbegreppen i meddelandespecifikationen för Advanced Message Queuing Protocol (AMQP) 1.0 finns i protokollguiden för AMQP 1.0.