AMQP 1.0 in azure Service Bus- en Event Hubs-protocolhandleiding

Het Advanced Message Queueing Protocol 1.0 is een gestandaardiseerde frame- en overdrachtsprotocol voor asynchroon, veilig en betrouwbaar overbrengen van berichten tussen twee partijen. Het is het primaire protocol van Azure Service Bus Messaging en Azure Event Hubs.

AMQP 1.0 is het resultaat van brede samenwerking in de branche die middlewareleveranciers, zoals Microsoft en Red Hat, samenbrengt met veel middlewaregebruikers zoals JP Morgan Chase die de financiële dienstverlening vertegenwoordigen. Het technische standaardisatieforum voor het AMQP-protocol en extensiespecificaties is OASIS en heeft formele goedkeuring als internationale standaard als ISO/IEC 19494:2014 bereikt.

Doelstellingen

In dit artikel vindt u een overzicht van de belangrijkste concepten van de AMQP 1.0-berichtspecificatie, samen met de uitbreidingsspecificaties die zijn ontwikkeld door het Technische Comité van OASIS AMQP en wordt uitgelegd hoe Azure Service Bus deze specificaties implementeert en bouwt.

Het doel is voor elke ontwikkelaar die gebruikmaakt van een bestaande AMQP 1.0-clientstack op elk platform om te kunnen communiceren met Azure Service Bus via AMQP 1.0.

Algemene AMQP 1.0-stacks, zoals Apache Qpid Proton of AMQP.NET Lite, implementeren alle kern-AMQP 1.0-protocolelementen, zoals sessies of koppelingen. Deze fundamentele elementen worden soms verpakt met een API op een hoger niveau; Apache Proton biedt zelfs twee, de imperatieve Messenger-API en de reactieve Reactor-API.

In de volgende discussie gaan we ervan uit dat het beheer van AMQP-verbindingen, sessies en koppelingen en de verwerking van frameoverdrachten en stroombeheer worden verwerkt door de respectieve stack (zoals Apache Proton-C) en dat er niet veel nodig is als er specifieke aandacht van toepassingsontwikkelaars is. We gaan er abstract van uit dat er enkele API-primitieven bestaan, zoals de mogelijkheid om verbinding te maken en om een vorm van afzender- en ontvangerabstrahionobjecten te maken, die vervolgens een vorm van send() en receive() bewerkingen hebben.

Bij het bespreken van geavanceerde mogelijkheden van Azure Service Bus, zoals het bladeren door berichten of het beheer van sessies, worden deze functies uitgelegd in AMQP-termen, maar ook als een gelaagde pseudo-implementatie boven op deze veronderstelde API-abstractie.

Wat is AMQP?

AMQP is een frame- en overdrachtsprotocol. Framen betekent dat het structuur biedt voor binaire gegevensstromen die in beide richtingen van een netwerkverbinding stromen. De structuur biedt delineatie voor afzonderlijke gegevensblokken, frames genoemd, die tussen de verbonden partijen moeten worden uitgewisseld. De overdrachtsmogelijkheden zorgen ervoor dat beide communicerende partijen een gedeeld begrip kunnen vaststellen over wanneer frames worden overgedragen en wanneer overdrachten als volledig worden beschouwd.

In tegenstelling tot eerdere verlopen conceptversies die zijn geproduceerd door de AMQP-werkgroep die nog in gebruik zijn door een paar berichtbrokers, schrijft het uiteindelijke en gestandaardiseerde AMQP 1.0-protocol de aanwezigheid van een berichtenbroker of een bepaalde topologie voor entiteiten binnen een berichtenbroker niet voor.

Het protocol kan worden gebruikt voor symmetrische peer-to-peer-communicatie, voor interactie met berichtbrokers die wachtrijen ondersteunen en entiteiten publiceren/abonneren, zoals Azure Service Bus doet. Het kan ook worden gebruikt voor interactie met berichteninfrastructuur waarbij de interactiepatronen verschillen van normale wachtrijen, zoals het geval is met Azure Event Hubs. Een Event Hub fungeert als een wachtrij wanneer er gebeurtenissen naartoe worden verzonden, maar fungeert meer als een seriële opslagservice wanneer gebeurtenissen worden gelezen; het lijkt enigszins op een tapestation. De client kiest een offset in de beschikbare gegevensstroom en wordt vervolgens alle gebeurtenissen van die offset naar de meest recente beschikbare geleverd.

Het AMQP 1.0-protocol is ontworpen om uitbreidbaar te zijn, zodat verdere specificaties de mogelijkheden ervan kunnen verbeteren. De drie uitbreidingsspecificaties die in dit document worden besproken, illustreren dit. Voor communicatie via bestaande HTTPS/WebSockets-infrastructuur kan het lastig zijn om de systeemeigen AMQP TCP-poorten te configureren. Een bindingsspecificatie definieert hoe AMQP wordt gelaagd via WebSockets. Voor interactie met de berichteninfrastructuur op aanvraag-/antwoordmode voor beheerdoeleinden of om geavanceerde functionaliteit te bieden, definieert de AMQP-beheerspecificatie de vereiste basisinteractieprimitieven. Voor federatieve autorisatiemodelintegratie definieert de AMQP-claimgebaseerde beveiligingsspecificatie hoe u autorisatietokens koppelt en verlengt die zijn gekoppeld aan koppelingen.

Eenvoudige AMQP-scenario's

In deze sectie wordt het basisgebruik van AMQP 1.0 met Azure Service Bus uitgelegd, waaronder het maken van verbindingen, sessies en koppelingen, en het overdragen van berichten naar en van Service Bus-entiteiten, zoals wachtrijen, onderwerpen en abonnementen.

De meest gezaghebbende bron voor meer informatie over hoe AMQP werkt, is de AMQP 1.0-specificatie, maar de specificatie is geschreven om de implementatie nauwkeurig te begeleiden en niet om het protocol te leren. Deze sectie is gericht op het introduceren van zoveel terminologie als nodig is voor het beschrijven van de wijze waarop Service Bus AMQP 1.0 gebruikt. Voor een uitgebreidere inleiding tot AMQP, evenals een bredere bespreking van AMQP 1.0, kunt u deze videocursus bekijken.

Verbindingen en sessies

AMQP roept de containers voor communicatieprogramma's aan; die knooppunten bevatten, die de communicerende entiteiten binnen deze containers zijn. Een wachtrij kan een dergelijk knooppunt zijn. AMQP maakt multiplexing mogelijk, zodat één verbinding kan worden gebruikt voor veel communicatiepaden tussen knooppunten; Een toepassingsclient kan bijvoorbeeld gelijktijdig ontvangen van de ene wachtrij en verzenden naar een andere wachtrij via dezelfde netwerkverbinding.

Diagram showing Sessions and Connections between containers.

De netwerkverbinding wordt dus verankerd in de container. Het wordt gestart door de container in de clientrol die een uitgaande TCP-socketverbinding maakt met een container in de ontvangerrol, die luistert naar en accepteert binnenkomende TCP-verbindingen. De verbindingshanddruk omvat het onderhandelen over de protocolversie, het declareren of onderhandelen over het gebruik van Tls/SSL (Transport Level Security) en een verificatie-/autorisatie-handshake in het verbindingsbereik dat is gebaseerd op SASL.

Voor Azure Service Bus of Azure Event Hubs is het gebruik van TLS altijd vereist. Het ondersteunt verbindingen via TCP-poort 5671, waarbij de TCP-verbinding eerst wordt overschreven met TLS voordat u de AMQP-protocolhandhake invoert en ook verbindingen via TCP-poort 5672 ondersteunt, waarbij de server onmiddellijk een verplichte upgrade van verbinding met TLS biedt met behulp van het door AMQP voorgeschreven model. De AMQP WebSockets-binding maakt een tunnel via TCP-poort 443 die vervolgens gelijk is aan AMQP 5671-verbindingen.

Na het instellen van de verbinding en TLS biedt Service Bus twee SASL-mechanismeopties:

  • SASL PLAIN wordt vaak gebruikt voor het doorgeven van gebruikersnaam- en wachtwoordreferenties aan een server. Service Bus heeft geen accounts, maar heeft de naam Gedeelde toegangsbeveiligingsregels, die rechten verlenen en zijn gekoppeld aan een sleutel. De naam van een regel wordt gebruikt als gebruikersnaam en de sleutel (als base64 gecodeerde tekst) wordt gebruikt als het wachtwoord. De rechten die zijn gekoppeld aan de gekozen regel bepalen de bewerkingen die zijn toegestaan voor de verbinding.
  • SASL ANONYMOUS wordt gebruikt voor het omzeilen van SASL-autorisatie wanneer de client het CBS-model (claims based-security) wil gebruiken dat later wordt beschreven. Met deze optie kan een clientverbinding anoniem tot stand worden gebracht gedurende een korte periode waarin de klant alleen kan communiceren met het CBS-eindpunt en de CBS-handshake moet worden voltooid.

Nadat de transportverbinding tot stand is gebracht, declareren de containers elk de maximale framegrootte die ze willen verwerken. Na een time-out voor inactiviteit wordt de verbinding eenzijdig verbroken als er geen activiteit op de verbinding is.

Ze declareren ook hoeveel gelijktijdige kanalen worden ondersteund. Een kanaal is een unidirectioneel, uitgaand, virtueel overdrachtspad boven aan de verbinding. Een sessie neemt een kanaal van elk van de onderling verbonden containers om een bidirectioneel communicatiepad te vormen.

Sessies hebben een stroombeheermodel op basis van vensters; wanneer een sessie wordt gemaakt, declareert elke partij hoeveel frames het wil accepteren in het ontvangstvenster. Wanneer de partijen frames uitwisselen, vullen overgedragen frames dat venster en overdrachten stoppen wanneer het venster vol is en totdat het venster opnieuw wordt ingesteld of uitgebreid met behulp van de stroom performatief (performatief is de AMQP-term voor bewegingen op protocolniveau uitgewisseld tussen de twee partijen).

Dit model op basis van vensters is ongeveer vergelijkbaar met het TCP-concept van stroombeheer op basis van vensters, maar op sessieniveau in de socket. Het protocolconcept van het toestaan van meerdere gelijktijdige sessies bestaat, zodat verkeer met hoge prioriteit kan worden overgeslagen door normaal verkeer, zoals op een snelweg expressbaan.

Azure Service Bus gebruikt momenteel precies één sessie voor elke verbinding. De maximale framegrootte van Service Bus is 262.144 bytes (256-K bytes) voor Service Bus Standard. Het is 1048576 (100 MB) voor Service Bus Premium en Event Hubs. Service Bus legt geen beperkingsvensters op sessieniveau op, maar stelt het venster regelmatig opnieuw in als onderdeel van stroombeheer op koppelingsniveau (zie de volgende sectie).

Verbindingen, kanalen en sessies zijn kortstondig. Als de onderliggende verbinding samenvalt, moeten verbindingen, TLS-tunnel, SASL-autorisatiecontext en sessies opnieuw worden hersteld.

Vereisten voor uitgaande poort amQP

Voor clients die AMQP-verbindingen via TCP gebruiken, moeten poorten 5671 en 5672 worden geopend in de lokale firewall. Naast deze poorten kan het nodig zijn om extra poorten te openen als de functie EnableLinkRedirect is ingeschakeld. EnableLinkRedirect is een nieuwe berichtenfunctie waarmee u één hop kunt overslaan tijdens het ontvangen van berichten, waardoor de doorvoer wordt verhoogd. De client communiceert rechtstreeks met de back-endservice via poortbereik 104XX, zoals wordt weergegeven in de volgende afbeelding.

List of destination ports

Een .NET-client mislukt met een SocketException ('Er is geprobeerd toegang te krijgen tot een socket op een manier die niet is toegestaan door de toegangsmachtigingen') als deze poorten worden geblokkeerd door de firewall. De functie kan worden uitgeschakeld door in te stellen EnableAmqpLinkRedirect=false in de verbindingsreeks, waardoor de clients via poort 5671 moeten communiceren met de externe service.

AMQP draagt berichten over via koppelingen. Een koppeling is een communicatiepad dat is gemaakt via een sessie waarmee berichten in één richting kunnen worden overgedragen; de overdrachtsstatusonderhandeling is via de koppeling en bidirectioneel tussen de verbonden partijen.

Screenshot showing a Session carrying a link connection between two containers.

Koppelingen kunnen op elk gewenst moment worden gemaakt door een container en via een bestaande sessie, waardoor AMQP verschilt van vele andere protocollen, waaronder HTTP en MQTT, waarbij de inleiding van overdrachten en overdrachtspad een exclusieve bevoegdheid is van de partij die de socketverbinding maakt.

De koppelings-initiërende container vraagt de tegenovergestelde container om een koppeling te accepteren en kiest een rol van afzender of ontvanger. Daarom kan een container het maken van unidirectionele of bidirectionele communicatiepaden initiëren, waarbij de laatste is gemodelleerd als paren van koppelingen.

Koppelingen worden benoemd en gekoppeld aan knooppunten. Zoals vermeld in het begin, zijn knooppunten de communicerende entiteiten in een container.

In Service Bus is een knooppunt direct gelijk aan een wachtrij, een onderwerp, een abonnement of een deadlettersubqueue van een wachtrij of abonnement. De knooppuntnaam die in AMQP wordt gebruikt, is daarom de relatieve naam van de entiteit in de Service Bus-naamruimte. Als een wachtrij de naam myqueueheeft, is dat ook de naam van het AMQP-knooppunt. Een onderwerpabonnement volgt de HTTP-API-conventie door te worden gesorteerd in een resourceverzameling 'abonnementen', en dus heeft een abonnementssubsub in een onderwerp mytopic de naam van het AMQP-knooppunt mytopic/subscriptions/sub.

De verbindingsclient is ook vereist voor het gebruik van een lokale knooppuntnaam voor het maken van koppelingen; Service Bus is niet prescriptief over deze knooppuntnamen en interpreteert deze niet. AMQP 1.0-clientstacks maken doorgaans gebruik van een schema om ervoor te zorgen dat deze kortstondige knooppuntnamen uniek zijn in het bereik van de client.

Transfers

Zodra er een koppeling tot stand is gebracht, kunnen berichten via die koppeling worden overgedragen. In AMQP wordt een overdracht uitgevoerd met een expliciet protocolbeweging (de overdrachtsgebaar ) waarmee een bericht van de afzender naar de ontvanger wordt verplaatst via een koppeling. Een overdracht is voltooid wanneer deze 'geregeld' is, wat betekent dat beide partijen een gedeeld begrip hebben vastgesteld van het resultaat van die overdracht.

A diagram showing a message's transfer between the Sender and Receiver and disposition that results from it.

In het eenvoudigste geval kan de afzender ervoor kiezen om berichten 'vooraf geregeld' te verzenden, wat betekent dat de client niet geïnteresseerd is in het resultaat en de ontvanger geen feedback geeft over het resultaat van de bewerking. Deze modus wordt ondersteund door Service Bus op het niveau van het AMQP-protocol, maar wordt niet weergegeven in een van de client-API's.

Het normale geval is dat berichten worden verzonden die niet zijn ingesteld en dat de ontvanger vervolgens acceptatie of afwijzing aangeeft met behulp van de uitvoering van de verwijdering . Afwijzing treedt op wanneer de ontvanger het bericht om welke reden dan ook niet kan accepteren en het afwijzingsbericht informatie bevat over de reden, wat een foutstructuur is die is gedefinieerd door AMQP. Als berichten worden geweigerd vanwege interne fouten in Service Bus, retourneert de service extra informatie in die structuur die kan worden gebruikt voor het verstrekken van diagnostische hints aan het ondersteuningspersoneel als u ondersteuningsaanvragen indient. U vindt later meer informatie over fouten.

Een speciale vorm van afwijzing is de vrijgegeven toestand, die aangeeft dat de ontvanger geen technisch bezwaar heeft tegen de overdracht, maar ook geen belang heeft bij het vereffenen van de overdracht. Dat geval bestaat bijvoorbeeld wanneer een bericht wordt bezorgd bij een Service Bus-client en de client ervoor kiest het bericht 'af te laten' omdat het bericht niet kan worden uitgevoerd als gevolg van het verwerken van het bericht; de bezorging van berichten zelf heeft geen schuld. Een variatie van die status is de gewijzigde status, waardoor wijzigingen in het bericht worden toegestaan terwijl het wordt vrijgegeven. Die status wordt momenteel niet gebruikt door Service Bus.

De AMQP 1.0-specificatie definieert een verdere verwijderingsstatus met de naam ontvangen, die specifiek helpt bij het afhandelen van koppelingsherstel. Met koppelingsherstel kunt u de status van een koppeling en eventuele leveringen die in behandeling zijn, opnieuw kopiëren boven op een nieuwe verbinding en sessie, wanneer de vorige verbinding en sessie verloren zijn gegaan.

Service Bus biedt geen ondersteuning voor koppelingsherstel; als de client de verbinding met Service Bus verliest met een niet-verbonden berichtoverdracht in behandeling, gaat deze berichtoverdracht verloren en moet de client opnieuw verbinding maken, de koppeling opnieuw herstellen en de overdracht opnieuw proberen.

Daarom bieden Service Bus en Event Hubs ondersteuning voor 'ten minste één keer' overdracht waarbij de afzender kan worden verzekerd dat het bericht is opgeslagen en geaccepteerd, maar niet 'exact één keer' overdrachten op AMQP-niveau ondersteunt, waarbij het systeem probeert de koppeling te herstellen en doorgaat met onderhandelen over de bezorgingsstatus om dubbele berichtenoverdracht te voorkomen.

Om mogelijke dubbele verzendingen te compenseren, ondersteunt Service Bus dubbele detectie als een optionele functie voor wachtrijen en onderwerpen. Dubbele detectie registreert de bericht-id's van alle binnenkomende berichten tijdens een door de gebruiker gedefinieerd tijdvenster, waarna alle berichten die met dezelfde bericht-id's in hetzelfde venster worden verzonden, op de achtergrond worden verwijderd.

Stoombeheer

Naast het model voor stroombeheer op sessieniveau dat eerder is besproken, heeft elke koppeling een eigen stroombeheermodel. Met het besturingselement voor stroom op sessieniveau wordt de container beschermd tegen te veel frames tegelijk te verwerken. Met stroombesturingselement op koppelingsniveau wordt de toepassing belast met het aantal berichten dat de container wil verwerken vanaf een koppeling en wanneer.

Screenshot of a log showing Source, Destination, Source Port, Destination Port, and Protocol Name. In the first row the Destination Port 10401 (0x28 A 1) is outlined in black.

Bij een koppeling kunnen overdrachten alleen plaatsvinden wanneer de afzender voldoende tegoed heeft. Het tegoed van de koppeling is een teller die door de ontvanger is ingesteld met behulp van de stroom die het bereik heeft van een koppeling. Wanneer aan de afzender een koppelingstegoed is toegewezen, wordt geprobeerd dat tegoed te gebruiken door berichten te leveren. Bij elke berichtbezorging wordt het resterende koppelingstegoed met 1 afgebroken. Wanneer het koppelingstegoed wordt gebruikt, stoppen leveringen.

Wanneer Service Bus de rol van ontvanger heeft, krijgt de afzender direct voldoende tegoed voor koppelingen, zodat berichten direct kunnen worden verzonden. Als er een koppelingstegoed wordt gebruikt, verzendt Service Bus af en toe een stroom die presteert naar de afzender om het tegoedsaldo van de koppeling bij te werken.

In de rol afzender verzendt Service Bus berichten om eventuele openstaande koppelingstegoeden te gebruiken.

Een 'receive'-aanroep op API-niveau vertaalt zich in een stroom die door de client naar Service Bus wordt verzonden. Service Bus verbruikt dat tegoed door het eerste beschikbare, ontgrendelde bericht uit de wachtrij te nemen, te vergrendelen en over te dragen. Als er geen bericht beschikbaar is voor levering, blijft een openstaand tegoed via een koppeling met die specifieke entiteit geregistreerd in de volgorde van aankomst en worden berichten vergrendeld en overgedragen wanneer ze beschikbaar komen, om een openstaand tegoed te gebruiken.

De vergrendeling van een bericht wordt vrijgegeven wanneer de overdracht wordt geregeld in een van de terminalstatussen die zijn geaccepteerd, geweigerd of vrijgegeven. Het bericht wordt verwijderd uit Service Bus wanneer de terminalstatus wordt geaccepteerd. Het blijft in Service Bus en wordt bezorgd bij de volgende ontvanger wanneer de overdracht een van de andere statussen bereikt. Service Bus verplaatst het bericht automatisch naar de wachtrij met deadletters van de entiteit wanneer het het maximum aantal toegestane leveringen voor de entiteit bereikt vanwege herhaalde afwijzingen of releases.

Hoewel de Service Bus-API's momenteel geen dergelijke optie beschikbaar maken, kan een AMQP-protocolclient op een lager niveau het koppelingstegoedmodel gebruiken om de interactie 'pull-style' van het uitgeven van één kredieteenheid voor elke ontvangstaanvraag in een 'push-style'-model te veranderen door een groot aantal koppelingstegoeden uit te geven en berichten te ontvangen zodra ze beschikbaar zijn zonder verdere interactie. Push wordt ondersteund via de instellingen van de eigenschap MessagingFactory.PrefetchCount of MessageReceiver.PrefetchCount . Wanneer ze niet nul zijn, gebruikt de AMQP-client deze als het koppelingstegoed.

In deze context is het belangrijk om te begrijpen dat de klok voor het verlopen van de vergrendeling van het bericht in de entiteit begint wanneer het bericht uit de entiteit wordt gehaald, niet wanneer het bericht op de draad wordt geplaatst. Wanneer de client aangeeft dat berichten gereed zijn om berichten te ontvangen door een koppelingstegoed uit te geven, wordt ervan uitgegaan dat berichten actief worden opgehaald in het netwerk en gereed zijn om ze te verwerken. Anders is de berichtvergrendeling mogelijk verlopen voordat het bericht zelfs wordt bezorgd. Het gebruik van het besturingselement voor een koppelingstegoedstroom moet rechtstreeks overeenkomen met de onmiddellijke gereedheid voor het verwerken van beschikbare berichten die naar de ontvanger zijn verzonden.

Kortom, de volgende secties bieden een schematisch overzicht van de performatieve stroom tijdens verschillende API-interacties. In elke sectie wordt een andere logische bewerking beschreven. Sommige van deze interacties kunnen 'luie' zijn, wat betekent dat ze alleen worden uitgevoerd wanneer dat nodig is. Het maken van een afzender van een bericht kan geen netwerkinteractie veroorzaken totdat het eerste bericht wordt verzonden of aangevraagd.

De pijlen in de volgende tabel geven de richting van de performatieve stroom weer.

Berichtontvanger maken

Client Service Bus
--> attach(<br/>name={link name},<br/>handle={numeric handle},<br/>role=**receiver**,<br/>source={entity name},<br/>target={client link ID}<br/>) Client koppelt aan entiteit als ontvanger
Service Bus-antwoorden die het einde van de koppeling bijvoegen <-- attach(<br/>name={link name},<br/>handle={numeric handle},<br/>role=**sender**,<br/>source={entity name},<br/>target={client link ID}<br/>)

Afzender van bericht maken

Client Service Bus
--> attach(<br/>name={link name},<br/>handle={numeric handle},<br/>role=**sender**,<br/>source={client link ID},<br/>target={entity name}<br/>) Geen actie
Geen actie <-- attach(<br/>name={link name},<br/>handle={numeric handle},<br/>role=**receiver**,<br/>source={client link ID},<br/>target={entity name}<br/>)

Afzender van bericht maken (fout)

Client Service Bus
--> attach(<br/>name={link name},<br/>handle={numeric handle},<br/>role=**sender**,<br/>source={client link ID},<br/>target={entity name}<br/>) Geen actie
Geen actie <-- attach(<br/>name={link name},<br/>handle={numeric handle},<br/>role=**receiver**,<br/>source=null,<br/>target=null<br/>)<br/><br/><-- detach(<br/>handle={numeric handle},<br/>closed=**true**,<br/>error={error info}<br/>)

Ontvanger/afzender van bericht sluiten

Client Service Bus
--> detach(<br/>handle={numeric handle},<br/>closed=**true**<br/>) Geen actie
Geen actie <-- detach(<br/>handle={numeric handle},<br/>closed=**true**<br/>)

Verzenden (geslaagd)

Client Service Bus
--> transfer(<br/>delivery-id={numeric handle},<br/>delivery-tag={binary handle},<br/>settled=**false**,,more=**false**,<br/>state=**null**,<br/>resume=**false**<br/>) Geen actie
Geen actie <-- disposition(<br/>role=receiver,<br/>first={delivery ID},<br/>last={delivery ID},<br/>settled=**true**,<br/>state=**accepted**<br/>)

Verzenden (fout)

Client Service Bus
--> transfer(<br/>delivery-id={numeric handle},<br/>delivery-tag={binary handle},<br/>settled=**false**,,more=**false**,<br/>state=**null**,<br/>resume=**false**<br/>) Geen actie
Geen actie <-- disposition(<br/>role=receiver,<br/>first={delivery ID},<br/>last={delivery ID},<br/>settled=**true**,<br/>state=**rejected**(<br/>error={error info}<br/>)<br/>)

Ontvangen

Client Service Bus
--> flow(<br/>link-credit=1<br/>) Geen actie
Geen actie < transfer(<br/>delivery-id={numeric handle},<br/>delivery-tag={binary handle},<br/>settled=**false**,<br/>more=**false**,<br/>state=**null**,<br/>resume=**false**<br/>)
--> disposition(<br/>role=**receiver**,<br/>first={delivery ID},<br/>last={delivery ID},<br/>settled=**true**,<br/>state=**accepted**<br/>) Geen actie

Ontvangen met meerdere berichten

Client Service Bus
--> flow(<br/>link-credit=3<br/>) Geen actie
Geen actie < transfer(<br/>delivery-id={numeric handle},<br/>delivery-tag={binary handle},<br/>settled=**false**,<br/>more=**false**,<br/>state=**null**,<br/>resume=**false**<br/>)
Geen actie < transfer(<br/>delivery-id={numeric handle+1},<br/>delivery-tag={binary handle},<br/>settled=**false**,<br/>more=**false**,<br/>state=**null**,<br/>resume=**false**<br/>)
Geen actie < transfer(<br/>delivery-id={numeric handle+2},<br/>delivery-tag={binary handle},<br/>settled=**false**,<br/>more=**false**,<br/>state=**null**,<br/>resume=**false**<br/>)
--> disposition(<br/>role=receiver,<br/>first={delivery ID},<br/>last={delivery ID+2},<br/>settled=**true**,<br/>state=**accepted**<br/>) Geen actie

Berichten

In de volgende secties wordt uitgelegd welke eigenschappen van de standaard AMQP-berichtsecties worden gebruikt door Service Bus en hoe deze worden toegewezen aan de Service Bus-API-set.

Elke eigenschap die door de toepassing moet worden gedefinieerd, moet worden toegewezen aan de kaart van application-properties AMQP.

Veldnaam Gebruik API-naam
Duurzaam - -
priority - -
ttl Time to live voor dit bericht TimeToLive
first-acquirer - -
aantal leveringen - DeliveryCount

properties

Veldnaam Gebruik API-naam
message-id Toepassingsgedefinieerde, vrije-formulier-id voor dit bericht. Wordt gebruikt voor dubbele detectie. Messageid
user-id Door de toepassing gedefinieerde gebruikers-id, niet geïnterpreteerd door Service Bus. Niet toegankelijk via de Service Bus-API.
tot Toepassingsgedefinieerde doel-id, niet geïnterpreteerd door Service Bus. Aan
Onderwerp Toepassingsgedefinieerde berichtdoel-id, niet geïnterpreteerd door Service Bus. Label
beantwoorden Toepassingsgedefinieerde indicator voor antwoordpad, niet geïnterpreteerd door Service Bus. ReplyTo
correlation-id Toepassingsgedefinieerde correlatie-id, niet geïnterpreteerd door Service Bus. CorrelationId
inhoudstype Toepassingsgedefinieerde inhoudstypeindicator voor de hoofdtekst, niet geïnterpreteerd door Service Bus. Contenttype
inhoudscodering Toepassingsgedefinieerde indicator voor inhoudscodering voor de hoofdtekst, niet geïnterpreteerd door Service Bus. Niet toegankelijk via de Service Bus-API.
absolute verlooptijd Declareert op welk absolute chatbericht het bericht verloopt. Genegeerd op invoer (header TTL wordt waargenomen), gezaghebbend voor uitvoer. ExpiresAtUtc
maaktijd Declareert op welk moment het bericht is gemaakt. Niet gebruikt door Service Bus Niet toegankelijk via de Service Bus-API.
groeps-id Toepassingsgedefinieerde id voor een gerelateerde set berichten. Wordt gebruikt voor Service Bus-sessies. Sessionid
groepsreeks Teller waarmee het relatieve volgnummer van het bericht in een sessie wordt geïdentificeerd. Genegeerd door Service Bus. Niet toegankelijk via de Service Bus-API.
reply-to-group-id - ReplyToSessionId

Berichtaantekeningen

Er zijn enkele andere eigenschappen van service bus-berichten, die geen deel uitmaken van AMQP-berichteigenschappen en worden doorgegeven als MessageAnnotations op het bericht.

Kaartsleutel voor aantekeningen Gebruik API-naam
x-opt-scheduled-enqueue-time Declareert op welk moment het bericht op de entiteit moet worden weergegeven ScheduledEnqueueTime
x-opt-partition-key Toepassingsgedefinieerde sleutel die bepaalt in welke partitie het bericht moet terechtkomen. PartitionKey
x-opt-via-partition-key Toepassingsgedefinieerde partitiesleutelwaarde wanneer een transactie moet worden gebruikt voor het verzenden van berichten via een overdrachtswachtrij. ViaPartitionKey
x-opt-enqueued-time Door de service gedefinieerde UTC-tijd die de werkelijke tijd vertegenwoordigt van het bericht. Genegeerd bij invoer. EnqueuedTimeUtc
x-opt-sequence-number Door de service gedefinieerd uniek nummer dat is toegewezen aan een bericht. SequenceNumber
x-opt-offset Door de service gedefinieerd volgnummer van het bericht. EnqueuedSequenceNumber
x-opt-locked-until Door de service gedefinieerd. De datum en tijd totdat het bericht wordt vergrendeld in de wachtrij/het abonnement. LockedUntilUtc
x-opt-deadletter-source Service gedefinieerd. Als het bericht wordt ontvangen uit de wachtrij met dode brieven, vertegenwoordigt het de bron van het oorspronkelijke bericht. DeadLetterSource

Transactiemogelijkheid

Een transactie groepeert twee of meer bewerkingen in een uitvoeringsbereik. Een dergelijke transactie moet er van nature voor zorgen dat alle bewerkingen die tot een bepaalde groep bewerkingen behoren, gezamenlijk slagen of mislukken. De bewerkingen worden gegroepeerd op een id txn-id.

Voor transactionele interactie fungeert de client als een transaction controller , waarmee de bewerkingen worden bepaald die moeten worden gegroepeerd. Service Bus Service fungeert als een transactional resource en voert werk uit zoals aangevraagd door de transaction controller.

De client en service communiceren via een control link , die door de klant tot stand is gebracht. De declare berichten discharge worden verzonden door de controller via de controlekoppeling om respectievelijk transacties toe te wijzen en te voltooien (ze vertegenwoordigen niet de afbakening van transactionele werkzaamheden). De werkelijke verzend-/ontvangst wordt niet uitgevoerd op deze koppeling. Elke aangevraagde transactionele bewerking wordt expliciet geïdentificeerd met de gewenste txn-id en kan daarom plaatsvinden op elke koppeling op de verbinding. Als de controlekoppeling wordt gesloten terwijl er niet-ontladen transacties bestaan die er zijn gemaakt, worden al deze transacties onmiddellijk teruggedraaid en worden pogingen om verdere transactionele werkzaamheden op deze transacties uit te voeren, tot fouten geleid. Berichten op de koppeling voor besturingselementen mogen niet vooraf worden geregeld.

Elke verbinding moet een eigen beheerkoppeling initiëren om transacties te kunnen starten en beëindigen. De service definieert een speciaal doel dat fungeert als een coordinator. De client/controller brengt een besturingskoppeling naar dit doel tot stand. Besturingskoppeling valt buiten de grenzen van een entiteit, dat wil gezegd, dezelfde besturingskoppeling kan worden gebruikt om transacties voor meerdere entiteiten te starten en te ontladen.

Een transactie starten

Om te beginnen met transactioneel werk. de verwerkingsverantwoordelijke moet een txn-id van de coördinator verkrijgen. Dit doet u door een declare typebericht te verzenden. Als de declaratie is geslaagd, reageert de coördinator met een verwijderingsresultaat, dat de toegewezen txn-idheeft.

Client (controller) Richting Service Bus (coördinator)
attach(
name={link name},
... ,
role=sender,
target=Coordinator
)
------>
<------ attach(
name={link name},
... ,
target=Coordinator()
)
overdracht(
delivery-id=0, ...)
{ AmqpValue (Declare()}
------>
<------ verwijdering(
first=0, last=0,
state=Declared(
txn-id={transaction ID}
))

Een transactie ontladen

De controller sluit het transactionele werk af door een discharge bericht naar de coördinator te sturen. De controller geeft aan dat het transactionele werk wil doorvoeren of terugdraaien door de fail vlag op de kwijtingstekst in te stellen. Als de coördinator de kwijting niet kan voltooien, wordt het bericht afgewezen met dit resultaat dat het transaction-errorresultaat draagt.

Opmerking: fail=true verwijst naar terugdraaien van een transactie en fail=false verwijst naar Doorvoer.

Client (controller) Richting Service Bus (coördinator)
overdracht(
delivery-id=0, ...)
{ AmqpValue (Declare()}
------>
<------ verwijdering(
first=0, last=0,
state=Declared(
txn-id={transaction ID}
))
. . .
Transactioneel werk
op andere koppelingen
. . .
overdracht(
delivery-id=57, ...)
{ AmqpValue (
Ontlading(txn-id=0,
fail=false)
}
------>
<------ verwijdering(
first=57, last=57,
state=Accepted())

Een bericht in een transactie verzenden

Alle transactionele werkzaamheden worden uitgevoerd met de transactionele leveringsstatus transactional-state die de txn-id draagt. In het geval van het verzenden van berichten wordt de transactionele status uitgevoerd door het overdrachtsframe van het bericht.

Client (controller) Richting Service Bus (coördinator)
overdracht(
delivery-id=0, ...)
{ AmqpValue (Declare()}
------>
<------ verwijdering(
first=0, last=0,
state=Declared(
txn-id={transaction ID}
))
overdracht(
handle=1,
delivery-id=1,
status=
TransactionalState(
txn-id=0)
)
{ payload }
------>
<------ verwijdering(
first=1, last=1,
state=TransactionalState(
txn-id=0,
outcome=Accepted()
))

Een bericht in een transactie verwijderen

De verwijdering van berichten bevat bewerkingen zoals CompleteDeadLetter / DeferAbandon / / . Als u deze bewerkingen binnen een transactie wilt uitvoeren, geeft u de transactional-state bewerking door aan de verwijdering.

Client (controller) Richting Service Bus (coördinator)
overdracht(
delivery-id=0, ...)
{ AmqpValue (Declare()}
------>
<------ verwijdering(
first=0, last=0,
state=Declared(
txn-id={transaction ID}
))
<------ overdracht(
handle=2,
delivery-id=11,
state=null)
{ payload }
verwijdering(
first=11, last=11,
state=TransactionalState(
txn-id=0,
outcome=Accepted()
))
------>

Geavanceerde Service Bus-mogelijkheden

In deze sectie worden geavanceerde mogelijkheden van Azure Service Bus behandeld die zijn gebaseerd op conceptextensies voor AMQP, die momenteel worden ontwikkeld in het Technische Comité van OASIS voor AMQP. Service Bus implementeert de nieuwste versies van deze concepten en neemt wijzigingen aan die zijn geïntroduceerd omdat deze concepten de standaardstatus bereiken.

Notitie

Geavanceerde bewerkingen voor Service Bus Messaging worden ondersteund via een aanvraag-/antwoordpatroon. De details van deze bewerkingen worden beschreven in het artikel AMQP 1.0 in Service Bus: bewerkingen op basis van aanvraagreacties.

AMQP-beheer

De AMQP-beheerspecificatie is de eerste van de conceptextensies die in dit artikel worden besproken. Deze specificatie definieert een set protocollen die boven op het AMQP-protocol zijn gelaagd, waarmee beheerinteracties met de berichteninfrastructuur via AMQP worden toegestaan. De specificatie definieert algemene bewerkingen zoals maken, lezen, bijwerken en verwijderen voor het beheren van entiteiten binnen een berichteninfrastructuur en een set querybewerkingen.

Al deze bewegingen vereisen een interactie tussen de client en de berichteninfrastructuur. Daarom definieert de specificatie hoe u dat interactiepatroon boven op AMQP kunt modelleren: de client maakt verbinding met de berichteninfrastructuur, start een sessie en maakt vervolgens een paar koppelingen. Op de ene koppeling fungeert de client als afzender en op de andere als ontvanger, waardoor een paar koppelingen worden gemaakt die kunnen fungeren als een bidirectioneel kanaal.

Logische bewerking Client Service Bus
Antwoordpad voor aanvraag maken --> attach(<br/>name={*link name*},<br/>handle={*numeric handle*},<br/>role=**sender**,<br/>source=**null**,<br/>target=”myentity/$management”<br/>) Geen actie
Antwoordpad voor aanvraag maken Geen actie \<-- attach(<br/>name={*link name*},<br/>handle={*numeric handle*},<br/>role=**receiver**,<br/>source=null,<br/>target=”myentity”<br/>)
Antwoordpad voor aanvraag maken --> attach(<br/>name={*link name*},<br/>handle={*numeric handle*},<br/>role=**receiver**,<br/>source=”myentity/$management”,<br/>target=”myclient$id”<br/>)
Antwoordpad voor aanvraag maken Geen actie \<-- attach(<br/>name={*link name*},<br/>handle={*numeric handle*},<br/>role=**sender**,<br/>source=”myentity”,<br/>target=”myclient$id”<br/>)

Als deze koppeling is ingesteld, is de implementatie van de aanvraag/reactie eenvoudig: een aanvraag is een bericht dat wordt verzonden naar een entiteit in de berichteninfrastructuur die dit patroon begrijpt. In dat aanvraagbericht wordt het antwoordveld in de eigenschappensectie ingesteld op de doel-id voor de koppeling waarop het antwoord moet worden geleverd. De verwerkingsentiteit verwerkt de aanvraag en levert vervolgens het antwoord via de koppeling waarvan de doel-id overeenkomt met de aangegeven antwoord-naar-id .

Het patroon vereist uiteraard dat de clientcontainer en de door de client gegenereerde id voor de antwoordbestemming uniek zijn voor alle clients en, om veiligheidsredenen, ook moeilijk te voorspellen zijn.

De berichtenuitwisselingen die worden gebruikt voor het beheerprotocol en voor alle andere protocollen die hetzelfde patroon gebruiken, vinden plaats op toepassingsniveau; ze definiëren geen nieuwe AMQP-protocolbewegingen. Dat is opzettelijk, zodat toepassingen direct kunnen profiteren van deze extensies met compatibele AMQP 1.0-stacks.

Service Bus implementeert momenteel geen van de kernfuncties van de beheerspecificatie, maar het aanvraag-/antwoordpatroon dat is gedefinieerd door de beheerspecificatie is fundamenteel voor de op claims gebaseerde beveiligingsfunctie en voor bijna alle geavanceerde mogelijkheden die in de volgende secties worden besproken:

Autorisatie op basis van claims

Het CBS-specificatieconcept (AMQP Claims-Based-Authorization) bouwt voort op het aanvraag-/antwoordpatroon voor beheerspecificaties en beschrijft een gegeneraliseerd model voor het gebruik van federatieve beveiligingstokens met AMQP.

Het standaardbeveiligingsmodel van AMQP dat in de inleiding wordt besproken, is gebaseerd op SASL en kan worden geïntegreerd met de AMQP-verbindingshandhake. Het gebruik van SASL heeft het voordeel dat het een uitbreidbaar model biedt waarvoor een set mechanismen is gedefinieerd waaruit elk protocol dat formeel op SASL leunt, kan profiteren. Onder deze mechanismen is 'PLAIN' voor de overdracht van gebruikersnamen en wachtwoorden, 'EXTERN' om verbinding te maken met TLS-beveiliging, 'ANONIEM' om de afwezigheid van expliciete verificatie/autorisatie uit te drukken, en een breed scala aan aanvullende mechanismen waarmee verificatie- en/of autorisatiereferenties of tokens kunnen worden doorgegeven.

SASL-integratie van AMQP heeft twee nadelen:

  • Alle referenties en tokens zijn gericht op de verbinding. Een berichteninfrastructuur wil mogelijk gedifferentieerd toegangsbeheer per entiteit bieden; Zo kan bijvoorbeeld de bearer van een token worden verzonden naar wachtrij A, maar niet naar wachtrij B. Als de autorisatiecontext is verankerd aan de verbinding, is het niet mogelijk om één verbinding te gebruiken en toch verschillende toegangstokens te gebruiken voor wachtrij A en wachtrij B.
  • Toegangstokens zijn doorgaans slechts gedurende een beperkte tijd geldig. Voor deze geldigheid moet de gebruiker periodiek tokens opnieuw aanvragen en kan de tokenverlener weigeren een nieuw token uit te geven als de toegangsmachtigingen van de gebruiker zijn gewijzigd. AMQP-verbindingen kunnen lange tijd duren. Het SASL-model biedt alleen de mogelijkheid om een token in te stellen op het moment van verbinding, wat betekent dat de berichteninfrastructuur de client moet loskoppelen wanneer het token verloopt of dat het het risico moet accepteren dat verdere communicatie met een client die de toegangsrechten heeft ingetrokken, in de tussentijd is ingetrokken.

De AMQP CBS-specificatie, geïmplementeerd door Service Bus, maakt een elegante tijdelijke oplossing mogelijk voor beide problemen: Hiermee kan een client toegangstokens koppelen aan elk knooppunt en deze tokens bijwerken voordat ze verlopen, zonder de berichtstroom te onderbreken.

CBS definieert een virtueel beheerknooppunt, met de naam $cbs, dat moet worden geleverd door de berichteninfrastructuur. Het beheerknooppunt accepteert tokens namens andere knooppunten in de berichteninfrastructuur.

Het protocolbeweging is een aanvraag-/antwoorduitwisseling zoals gedefinieerd door de beheerspecificatie. Dat betekent dat de client een paar koppelingen met het $cbs-knooppunt tot stand brengt en vervolgens een aanvraag doorgeeft op de uitgaande koppeling en vervolgens wacht op het antwoord op de inkomende koppeling.

Het aanvraagbericht heeft de volgende toepassingseigenschappen:

Sleutel Optioneel Waardetype Waarde-inhoud
operation No tekenreeks put-token
type No tekenreeks Het type token dat wordt geplaatst.
name No tekenreeks Het 'publiek' waarop het token van toepassing is.
expiration Ja tijdstempel De verlooptijd van het token.

De naameigenschap identificeert de entiteit waaraan het token moet worden gekoppeld. In Service Bus is het het pad naar de wachtrij of het onderwerp/abonnement. De typeeigenschap identificeert het tokentype:

Tokentype Beschrijving van token Hoofdteksttype Notities
jwt JSON Web Token (JWT) AMQP-waarde (tekenreeks)
servicebus.windows.net:sastoken Service Bus SAS-token AMQP-waarde (tekenreeks) -

Tokens verlenen rechten. Service Bus weet over drie fundamentele rechten: 'Verzenden' zorgt ervoor dat verzenden, 'Luisteren' het ontvangen inschakelt en 'Beheren' het bewerken van entiteiten mogelijk maakt. Service Bus SAS-tokens verwijzen naar regels die zijn geconfigureerd in de naamruimte of entiteit en deze regels worden geconfigureerd met rechten. Als u het token ondertekent met de sleutel die aan die regel is gekoppeld, wordt het token de respectieve rechten weergegeven. Met het token dat is gekoppeld aan een entiteit met behulp van een put-token , kan de verbonden client communiceren met de entiteit volgens de tokenrechten. Voor een koppeling waar de client de rol van afzender opneemt, is het recht Verzenden vereist; voor het overnemen van de ontvangerrol is het recht Luisteren vereist.

Het antwoordbericht heeft de volgende waarden voor toepassingseigenschappen

Sleutel Optioneel Waardetype Waarde-inhoud
status-code No int HTTP-antwoordcode [RFC2616].
status-description Yes tekenreeks Beschrijving van de status.

De client kan put-token herhaaldelijk aanroepen en voor elke entiteit in de berichteninfrastructuur. De tokens zijn afgestemd op de huidige client en verankerd op de huidige verbinding, wat betekent dat de server alle bewaarde tokens verwijdert wanneer de verbinding wordt onderbroken.

De huidige Service Bus-implementatie staat CBS alleen toe in combinatie met de SASL-methode ANONIEM. Er moet altijd een SSL/TLS-verbinding bestaan vóór de SASL-handshake.

Het ANONIEME mechanisme moet daarom worden ondersteund door de gekozen AMQP 1.0-client. Anonieme toegang betekent dat de initiële handshake van de verbinding, inclusief het maken van de eerste sessie, plaatsvindt zonder dat Service Bus weet wie de verbinding maakt.

Zodra de verbinding en sessie tot stand is gebracht, zijn het koppelen van de koppelingen aan het $cbs-knooppunt en het verzenden van de put-tokenaanvraag de enige toegestane bewerkingen. Een geldig token moet binnen 20 seconden nadat de verbinding tot stand is gebracht, worden ingesteld met behulp van een put-tokenaanvraag voor een bepaald entiteitsknooppunt, anders wordt de verbinding eenzijdig verwijderd door Service Bus.

De client is vervolgens verantwoordelijk voor het bijhouden van het verlopen van tokens. Wanneer een token verloopt, worden alle koppelingen op de verbinding met de respectieve entiteit onmiddellijk door Service Bus weggezet. Om te voorkomen dat er een probleem optreedt, kan de client het token voor het knooppunt vervangen door een nieuw knooppunt op elk gewenst moment via het virtuele $cbs-beheerknooppunt met dezelfde put-tokenbeweging en zonder dat het nettoladingverkeer dat op verschillende koppelingen stroomt, binnenkomt.

Functionaliteit voor verzenden via

Verzenden via/overdragen afzender is een functionaliteit waarmee service bus een bepaald bericht kan doorsturen naar een doelentiteit via een andere entiteit. Deze functie wordt gebruikt om bewerkingen uit te voeren tussen entiteiten in één transactie.

Met deze functionaliteit maakt u een afzender en stelt u de koppeling naar de via-entity. Tijdens het tot stand brengen van de koppeling wordt aanvullende informatie doorgegeven om de werkelijke bestemming van de berichten/overdrachten op deze koppeling tot stand te brengen. Zodra de bijlage is geslaagd, worden alle berichten die op deze koppeling worden verzonden, automatisch doorgestuurd naar de doelentiteit via entiteit.

Opmerking: verificatie moet worden uitgevoerd voor zowel via entiteit als doelentiteit voordat deze koppeling tot stand wordt gebracht.

Client Richting Service Bus
attach(<br/>name={link name},<br/>role=sender,<br/>source={client link ID},<br/>target=**{via-entity}**,<br/>**properties=map [(<br/>com.microsoft:transfer-destination-address=<br/>{destination-entity} )]** ) ------>
<------ attach(<br/>name={link name},<br/>role=receiver,<br/>source={client link ID},<br/>target={via-entity},<br/>properties=map [(<br/>com.microsoft:transfer-destination-address=<br/>{destination-entity} )] )

Volgende stappen

Zie het overzicht van Service Bus AMQP voor meer informatie over AMQP.