AMQP

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 17. juni 2020; kontroller kræver 107 redigeringer .

AMQP (Advanced Message Queuing Protocol)  er en åben applikationslagsprotokol til at sende meddelelser mellem systemkomponenter. Hovedideen er, at individuelle undersystemer (eller uafhængige applikationer) kan udveksle beskeder vilkårligt gennem en AMQP-mægler, der udfører routing , muligvis garanterer levering, distribution af datastrømme, abonnement på de ønskede typer af beskeder.

Protokolarkitekturen blev udviklet af John O'Hara fra JP Morgan Chase & Co [1] .

Protokol

AMQP er baseret på tre koncepter:

  1. Besked (meddelelse) - en enhed af transmitterede data, dens hoveddel (indhold) fortolkes ikke af serveren på nogen måde, strukturerede overskrifter kan vedhæftes meddelelsen.
  2. Exchange point - beskeder sendes til det. Centralen distribuerer beskeder til en eller flere køer . Samtidig gemmes beskeder ikke på udvekslingspunktet. Udvekslingspunkter er af tre typer:
    • fanout - beskeden overføres til alle køer knyttet til den;
    • direkte - beskeden sendes til køen med et navn, der matcher routingnøglen (routingnøglen) (routingnøglen angives ved afsendelse af meddelelsen);
    • emne - noget mellem fanout og direkte, beskeden sendes i køer, hvor masken for routing nøglen matcher, for eksempel app.notification.sms # - alle beskeder sendt med nøgler, der starter med app.notification.sms, vil blive leveret til køen.
  3. Kø - beskeder gemmes her, indtil de bliver afhentet af klienten. Klienten trækker altid beskeder fra en eller flere køer.


Protokollen kan opdeles i to lag:

  1. Funktionelt lag - definerer et sæt kommandoer, der udfører arbejde på vegne af applikationen.
  2. Transport Layer - håndterer anmodninger fra applikationen til serveren og serveren til applikationen, administrerer kanalmultipleksing, framing, kodning, hjerteslag, datapræsentation, fejlhåndtering.


Eksempler på kø:

Protokollen er ikke begrænset til disse tre slags. De er givet som eksempler på implementering.

Terminologi

Exchange

Modtager beskeder fra udbyderen og dirigerer dem til beskedkøen i henhold til foruddefinerede kriterier. Sådanne kriterier kaldes bindinger. Udveksling er en beskedforhandlings- og routingmekanisme. På baggrund af beskederne og deres parametre (bindinger) træffer de en beslutning om omdirigering til en kø eller en anden central. Gem ikke beskeder.

Udtrykket udveksling betyder algoritme og algoritmeinstans. De siger også byttetype og bytteinstans.

AMQP definerer et sæt standardudvekslingstyper. Applikationer kan oprette deres egen udvekslingsinstans.


Hver børs implementerer sin egen routingalgoritme. Der er flere standardudvekslingstyper beskrevet i standardens funktionsspecifikation. Af disse er to vigtige:

Serveren vil oprette flere udvekslinger, inklusive direkte og emne. De vil have velkendte navne, og klientapplikationer vil kunne arbejde med dem.

Exchange livscyklus

Hver AMQP-server præ-opretter flere forekomster af udveksling. Disse forekomster eksisterer, når serveren kører og kan ikke ødelægges. AMQP-applikationer kan også oprette deres egne udvekslinger. AMQP bruger ikke create-metoden til dette, i stedet er instansen erklæret, som følger logikken: "create if not created, fortsæt ellers". Det kan siges, at skabelsen af ​​udveksling er idempotent . Sandsynligvis vil applikationer skabe udvekslinger efter behov og derefter ødelægge dem som unødvendige. AMQP giver en metode til at ødelægge udvekslingen.

Routing Key

Generelt undersøger udvekslingen meddelelsens egenskaber, overskriftsfelterne og indholdet af dens krop, og ved hjælp af disse og muligvis data fra andre kilder beslutter den, hvordan meddelelsen skal rutes. I de fleste simple tilfælde betragter exchange ét nøglefelt, som vi kalder Routing Key . Routing-nøglen er en virtuel adresse, som udvekslingsserveren kan bruge til at beslutte, om der skal sendes en besked. For punkt-til-punkt routing er routing nøglen normalt navnet på beskedkøen. For pub-sub routing er routing nøglen normalt værdien af ​​emnehierarkiet (emne - se publikation/subscruber). I mere komplekse tilfælde kan routingnøglen kombineres med routing efter meddelelseshovedfelter og/eller meddelelsesindhold.

Meddelelseskø

Når en klientapplikation opretter en beskedkø, kan den angive følgende egenskaber:

Livscyklus for en meddelelse

En AMQP-meddelelse består af et sæt egenskaber og ikke-offentligt indhold. En ny besked oprettes af producenten ved hjælp af AMQP klient API. Producenten tilføjer indhold til beskeden og angiver muligvis nogle beskedegenskaber. Producenten markerer beskeden med ruteinformation, der ligner en adresse, men kan være hvad som helst. Producenten sender derefter beskeden til udveksling . Når en besked ankommer til serveren, dirigerer exchange den (normalt) til et sæt køer, der også findes på serveren. Hvis meddelelsen ikke kan dirigeres, kan Exchange droppe den eller returnere den til applikationen. Producenten bestemmer, hvordan man skal håndtere meddelelser, der ikke kan dirigeres.

Én besked kan eksistere i mange beskedkøer. Serveren kan håndtere dette på forskellige måder, såsom at kopiere beskeden ved hjælp af referencetælling osv. Dette påvirker ikke interoperabiliteten. Men når en besked dirigeres til flere beskedkøer, er den identisk i hver beskedkø. Der er ingen entydig identifikator her til at skelne mellem forskellige kopier.

Når en besked ankommer til beskedkøen, forsøger den straks at levere den til forbrugeren via AMQP. Hvis dette ikke er muligt, så gemmes beskeden i beskedkøen (i hukommelsen eller på disk efter anmodning fra producenten ) og venter på, at forbrugeren er klar. Hvis der ikke er nogen forbruger , kan køen returnere en besked til producenten via AMQP (igen, hvis producenten bad om det).

Når beskedkøen kan levere en besked til forbrugeren , fjerner den beskeden fra dens interne lager. Dette kan ske umiddelbart eller efter, at forbrugeren anerkender, at han har fuldført sit job, behandlet beskeden. Forbrugeren vælger selv, hvordan og hvornår budskaber "bekræftes". forbrugeren kan også afvise beskeden (negativ bekræftelse).

Producentmeddelelser og forbrugerbekræftelser er grupperet i transaktioner. Når en applikation spiller begge roller, hvilket ofte er tilfældet, udfører den et blandet stykke arbejde med at sende beskeder og sende bekræftelser og derefter forpligte eller rulle transaktionen tilbage.

Leveringen af ​​meddelelser fra serveren til forbrugeren er ikke-transaktionel.

Producer

Producer er en klientapplikation, der udgiver beskeder til udveksling .

Analogt med e-mail-enheden kan du se, at producenten ikke sender beskeder direkte til køen (meddelelseskø). Enhver anden adfærd ville bryde abstraktionen i AMQ-modellen. Dette ville svare til livscyklussen for en e-mail-meddelelse: at løse e-mailen, omgå MTA's routingtabeller og trykke direkte på postkassen. Dette ville gøre det umuligt at indsætte mellemliggende filtrering og behandling såsom spam-detektion.

AMQ-modellen bruger samme princip som e-mail-systemet: alle beskeder sendes til en enkelt central eller MTA , som inspicerer beskeder baseret på regler og information, der er skjult for afsenderen, og dirigerer dem til distributionspunkter, der også er skjult for afsender. (og dirigerer dem til afleveringssteder, der også er skjult for afsender - her er distributionssteder afleveringssteder fra dokumentationen).

forbruger

Forbruger er den klientapplikation, der modtager beskeder fra beskedkøen.

Vores e-mail-analogi begynder at gå i stykker, når vi ser på forbrugeren (modtagerne). E-mail-klienter er passive - de kan læse postkasser, men de har ingen indflydelse på, hvordan disse postkasser udfyldes. Med AMQP kan forbrugeren også være passiv, ligesom e-mail-klienter. Det vil sige, at vi kan skrive en applikation, der lytter til en bestemt beskedkø og blot behandler de indgående oplysninger. I dette tilfælde skal beskedkøen være klar, før applikationen starter, og skal være "vedhæftet" til den.

Forbrugeren har også følgende funktioner:

Det er som at have et mailsystem, der på protokolniveau kan:

Automatisk tilstand

De fleste integrationsarkitekturer har ikke brug for dette kompleksitetsniveau. De fleste AMQP-brugere har brug for grundlæggende funktionalitet ud af æsken. AMQP giver dette på følgende måde:

Som et resultat heraf giver den underliggende binding producenten mulighed for at sende beskeder direkte til beskedkøen, og dermed emulere den enkleste ordning for at sende en besked til en modtager, som folk ville forvente af en traditionel middleware.

Basisbindingen forhindrer ikke brugen af ​​beskedkøen i mere komplekse designs. Det giver dig mulighed for at bruge AMQP uden en specifik forståelse af bindings- og udvekslingsmekanismerne.

AMQP Command Architecture

Afsnittet beskriver processen med interaktion mellem applikationen og serveren

Protokolkommandoer (klasser og metoder)

Middleware er komplekst, og ved design af protokolstrukturen forsøgte dets skabere at tæmme denne kompleksitet. Deres tilgang var at modellere en traditionel API baseret på klasser, der indeholder metoder, hvor hver metode gør præcis én ting og gør det godt. Dette resulterer i et stort sæt kommandoer, men en der er relativt let at forstå.

AMQP-kommandoer er grupperet i klasser. Hver klasse dækker et specifikt funktionsområde. Nogle klasser er valgfrie - hver peer implementerer de klasser, den skal understøtte.

Der er to forskellige dialogmetoder:

For at forenkle metodebehandlingen definerer vi separate svar for hver synkron anmodning. Det vil sige, at én metode ikke bruges til at besvare to forskellige anmodninger. Det betyder, at en peer, når den sender en synkron anmodning, kan acceptere og behandle indgående metoder, indtil et af de gyldige synkrone svar modtages. Dette adskiller AMQP fra mere traditionelle RPC-protokoller.

En metode er formelt defineret som en synkron anmodning, synkron respons (på en specifik anmodning) eller asynkron. Endelig er hver metode formelt defineret som klient-side (dvs. server-klient) eller server-side (klient-server).

Kortlægning af AMQP til Middleware API

AMQP er designet til at være sammenlignelig med middleware API. Matchingsprocessen er noget intellektuel, dvs. forstår, at ikke alle metoder og ikke alle argumenter giver mening for anvendelsen, men det er også mekanisk, dvs. ved at sætte visse regler, kan alle metoder matches uden manuel indgriben.

Fordelene ved dette er, at udviklere ved at lære AMQP's semantik vil finde den samme semantik, uanset hvilken ramme de bruger.

Et eksempel på Queue.Declare-metoden:

. erklære = min . auto - slet = SAND eksklusiv = FALSK

Det kan konverteres til en netværksramme:

+--------+--------------------------- ----+ | | erklære | min . | 1 | 0 | +--------+--------------------------- ----+ klasse metodenavn auto - slet eksklusiv _

Eller i en API-metode på højt niveau

. Erklære ( "min.kø" , ​​TRUE , FALSE );

Asynkron metode, der matcher logik i pseudokode:

send metode til server

Synkron metode matchende logik i pseudokode:

send anmodningsmetode til serveren _ gentage vente svar fra serveren hvis respons er en asynkron metode procesmetode ( normalt leveret eller returneret indhold ) _ _ andet hævde , at metoden er et gyldigt svar anmodning afslutte gentag ende - hvis slut - gentag

Det er værd at bemærke, at for de fleste applikationer kan middleware være fuldstændig skjult i de tekniske lag af systemet, og at selve den anvendte API er mindre vigtig end det faktum, at middlewaren er robust og funktionel.

Manglende meddelelser

Den chatty-protokollen er langsom. Vi bruger aktivt asynkron i tilfælde, hvor der er et præstationsproblem. Det er normalt her, vi sender indhold fra en peer til en anden. Vi sender metoder så hurtigt som muligt uden at vente på bekræftelser. Hvor det er nødvendigt, implementerer vi vindues- og drosling på et højere niveau, såsom forbrugerniveau.

Protokollen undlader meddelelser, pga implementerer en påstandsmodel for alle begivenheder. Enten lykkes det eller bliver der kastet en undtagelse? der lukker en kanal eller forbindelse.

Der er ingen meddelelser i AMQP. En vellykket begivenhed - stille, en fiasko - erklærer sig selv. Når en applikation har brug for eksplicit sporing af succeser og fiaskoer, bør den bruge transaktioner.

Forbindelsesklasse

Forbindelsen er designet til at være holdbar og håndtere mange kanaler.

Forbindelsens livscyklus
  • Klienten åbner en TCP/IP-forbindelse til serveren og sender en protokolheader. Dette er den eneste tilgængelige information til at blive sendt af klienten, som ikke er formateret som en metode.
  • Serveren svarer med en protokolversion og andre egenskaber, inklusive listen over sikkerhedsmekanismer, den understøtter (Startmetoden)
  • Klienten vælger en sikkerhedsmekanisme (Start-Ok).
  • Serveren starter en godkendelsesproces, der bruger SASL -modellen , den sender en udfordring (sikker) til klienten.
  • Klienten sender et godkendelsessvar (Secure-Ok). For eksempel, ved at bruge den 'almindelige' godkendelsesmekanisme, indeholder svaret et brugernavn og en adgangskode.
  • Serveren gentager udfordringen (Secure) eller fortsætter til forhandlinger ved at sende et sæt parametre, inklusive maksimal rammestørrelse (Tune).
  • Klienten accepterer eller sænker disse parametre (Tune-Ok).
  • Klienten åbner formelt en forbindelse og vælger en virtuel vært (Åben).
  • Serveren bekræfter valg af virtuelle vært (Open-Ok).
  • Nu bruger klienten forbindelsen, som den finder passende.
  • Én node (klient eller server) lukker forbindelsen (Luk).
  • Den anden node sender data om lukning af forbindelsen (Luk-Ok).
  • Serveren og klienten lukker de stik, der svarer til forbindelsen.

Der udveksles ikke oplysninger for fejl ved ufuldstændigt åbnede forbindelser. Værten, der stødte på fejlen , bør lukke stikket uden yderligere varsel.

Kanalklasse

AMQP er en flerkanalsprotokol. Kanaler giver mulighed for at multiplekse en tung TCP/IP-forbindelse til flere lette forbindelser. Dette gør protokollen mere "firewall-venlig", fordi portbrugen er forudsigelig. Det betyder også, at trafikformning og andre netværks QoS-funktioner nemt kan bruges.

Kanaler er uafhængige af hinanden og kan udføre forskellige funktioner samtidigt med andre kanaler, mens den tilgængelige båndbredde er opdelt på samtidige opgaver.

Det forventes og opmuntres, at flertrådede klientapplikationer ofte kan bruge "kanal-per-tråd"-modellen for at lette udviklingen. Det er dog også helt acceptabelt at åbne flere forbindelser til en eller flere AMQP-servere fra en enkelt klient. En kanals livscyklus er som følger:

  • Klienten åbner en ny kanal (Åben)
  • Serveren bekræfter åbningen af ​​kanalen (Open-Ok)
  • Klienten og serveren bruger kanalen, som de finder passende.
  • En af noderne (klient eller server) lukker kanalen (Luk)
  • Den anden knude bekræfter, at kanalen lukker (Luk-Ok)

Exchange-klassen

Tillader en applikation at administrere udvekslingsforekomster på serveren. Denne klasse tillader et program at skrive sit eget meddelelseshåndteringsscript uden at stole på nogen konfiguration.

Bemærk: De fleste programmer har ikke brug for dette kompleksitetsniveau, og det er usandsynligt, at ældre middleware understøtter denne semantik.

Exchange livscyklus
  • Klienten beder serveren om at sikre sig, at udvekslingen eksisterer (Declare). Klienten kan angive dette som følger: "opret børsen, hvis den ikke eksisterer" eller "advar mig, men opret den ikke, hvis den ikke eksisterer".
  • Klienten udgiver beskeder for at udveksle
  • Kunden kan beslutte at slette udvekslingen (Slet)

Køklasse

Køklassen tillader en applikation at administrere beskedkøer på en server. Dette er et grundlæggende trin i næsten alle applikationer, der modtager beskeder, i det mindste for at verificere, at den forventede beskedkø faktisk eksisterer.


Køens livscyklus

Protokollen giver mulighed for to kølivscyklusser:

  • Holdbare beskedkøer - bruges af flere forbrugere og eksisterer uanset tilstedeværelsen af ​​forbrugere, der kunne modtage beskeder
  • Midlertidige beskedkøer - private køer til en bestemt forbruger. Køen slettes, når der ikke er forbrugere.


Holdbar meddelelseskø livscyklus
  • Klienten erklærer en beskedkø (Erklærer med "passivt" argument)
  • Serveren anerkender eksistensen af ​​køen (Declare-Ok)
  • Klienten læser beskeder fra køen
Livscyklus for midlertidige beskedkøer
  • Klienten opretter en beskedkø (Erklærer ofte uden et kønavn, så serveren vil give den et navn). Serveren bekræfter oprettelsen (Erklær-Ok)
  • Klienten initialiserer forbrugeren til den oprettede kø.
  • Klienten stopper forbrugeren enten eksplicit eller ved at lukke kanalen og/eller forbindelsen
  • Når den sidste forbruger forsvinder fra beskedkøen og efter en høflig timeout, fjerner serveren beskedkøen

AMQP implementerer emneabonnementsmekanismen i form af beskedkøer. Dette giver mulighed for interessante strukturer, hvor et abonnement kan belastningsbalanceres på tværs af en pulje af samarbejdende abonnentapplikationer.

Abonnementets livscyklus
  • Klienten opretter en beskedkø (Declare), serveren bekræfter (Declare-Ok)
  • Klienten matcher meddelelseskøen med udvekslingsemnet (Bind), og serveren bekræfter overensstemmelsen (Bind-Ok)
  • Klienten bruger meddelelseskøen som beskrevet ovenfor

Grundklasse

Basisklassen implementerer meddelelsesfunktionerne beskrevet i denne specifikation. Det understøtter følgende semantik:

  • Sende beskeder fra klient til server, der sker asynkront (Udgiv)
  • Start og stop forbrugere (Forbrug, Annuller)
  • Sende beskeder fra server til klient, der sker asynkront (Lever, Retur)
  • Beskedbekræftelse (bekræft, afvis)
  • Få beskeder fra køen på en synkron måde (Get)

Transaktionsklasse

AMQP understøtter to typer transaktioner:

  1. Automatiske transaktioner, hvor hver offentliggjort meddelelse og bekræftelse behandles som en selvstændig transaktion.
  2. Lokale servertransaktioner, hvor serveren buffer publicerede meddelelser og bekræftelser og begår dem efter anmodning fra klienten.

Klassen Transaction ("tx") giver applikationer adgang til den anden type transaktion, lokale servertransaktioner. Klassens semantik er som følger:

  1. Applikationen anmoder om servertransaktioner i hver kanal, hvor den ønsker at modtage sådanne transaktioner (Vælg)
  2. Applikation, der virker (Publicer, Ack)
  3. Applikationen udfører commit- eller rollback-arbejde (Commit, Roll-back)
  4. Applikationen fortsætter med at virke

Transaktioner handler om indholdspublicering og bekræftelser, ikke levering. Derfor sætter rollback ikke i kø og udløser genlevering. Klienten kan bekræfte disse meddelelser i den næste transaktion.

Transportarkitektur AMQP

Dette afsnit forklarer, hvordan kommandoer knytter sig til wire-level- protokollen.

Beskrivelse

AMQP er en binær protokol. Information er organiseret i rammer af forskellige typer. Rammer indeholder protokolmetoder og anden information. Alle frames har det samme generelle format: frame header, payload og end of frame. Rammens nyttelastformat afhænger af rammetypen.

På transportniveau forudsættes brugen af ​​TCP/IP-stakken eller analoger.

Inden for en enkelt stikforbindelse kan der være flere uafhængige kontrolstrømme, kaldet kanaler. Hver frame er nummereret med et kanalnummer. Ved at sammenflette deres rammer deler de forskellige kanaler denne forbindelse. For enhver given kanal udføres frames i en streng sekvens, der kan bruges til at drive en protokolanalysator (normalt en tilstandsmaskine).

Vi bygger rammer ved hjælp af et lille sæt datatyper såsom bits, heltal, strenge og felttabeller. Rammefelter er tæt pakket uden at gøre dem langsomme eller svære at parse. Det er relativt nemt at skabe et rammelag mekanisk ud fra protokolspecifikationer.

Wire-level formatering er designet til at være skalerbar og alsidig nok til at blive brugt i vilkårlige højniveau protokoller (ikke kun AMQP). Vi forventer, at AMQP vil udvide, forbedre og på anden måde ændre sig over tid, og wire-level formatet vil understøtte dette.

Datatyper

AMQP datatyper brugt i frames:

  • Heltal (fra 1 til 8 oktetter) bruges til at repræsentere størrelser, størrelser, grænser osv. Heltal er altid uden fortegn og kan være forkert justeret inden for en ramme.
  • stykker
  • Korte strenge, der bruges til at gemme egenskaber for korte tekster. Korte strenge er begrænset til 255 oktetter og kan parses uden risiko for bufferoverløb. (Jeg formoder, at vi taler om en oktet i 255 stater og ikke om 255 oktetter)
  • Lange strenge, der bruges til at gemme dele af binære data
  • Tabelfelter, der indeholder navn-værdi-par. Feltværdier indtastes som strenge, heltal osv.

Protokolforhandling

Klienten og serveren forhandler en protokol. Det betyder, at når en klient opretter forbindelse, tilbyder serveren visse muligheder, som klienten kan acceptere eller ændre. Når begge er enige om resultatet, anses forbindelsen for etableret. Forhandling er nyttigt, fordi det giver dig mulighed for at indstille forbindelsesforudindstillinger.

Koordinering foregår på en række aspekter:

  • Den aktuelle protokol og dens version. En server MÅ håndtere flere protokoller på en enkelt port.
  • Krypteringsargumenter og autentificering af begge sider. Det er en del af det funktionelle lag i protokollen.
  • Maksimal rammestørrelse, antal kanaler og andre operationelle begrænsninger

Aftalte grænser kan give begge parter mulighed for at forhåndstildele nøglebuffere og undgå dødvande. Hver indkommende ramme overholder enten de forhandlede grænser og er derfor sikker eller overskrider dem, i hvilket tilfælde den anden side har fejlet og skal deaktiveres. Dette stemmer meget godt overens med AMQP-filosofien om "enten fungerer det, som det skal, eller også virker det slet ikke".

Begge noder forhandler grænser til den laveste aftalte værdi som følger:

  • Serveren SKAL fortælle klienten hvilke grænser den tilbyder.
  • Klienten reagerer og KAN reducere forbindelsesgrænserne

Rammeafgrænsning

TCP/IP-stak - fungerer med streams, den har ikke en indbygget rammeafgrænsningsmekanisme. Eksisterende protokoller løser dette problem på flere forskellige måder:

  • Sender én ramme pr. forbindelse. Det er enkelt, men langsomt
  • Tilføjelse af en rammeafgrænser til en strøm. Det er enkelt, men gør parsing langsom
  • Tæl rammestørrelse og send størrelse før hver ramme. Det er enkelt og hurtigt, og denne tilgang er implementeret i AMQP.


Optaget i detaljer

Alle frames består af en header (7 oktetter), en vilkårlig størrelse nyttelast og en "end of frame"-oktet, der registrerer misdannede rammer:

0 1 3 7 størrelse + 7 størrelse + 8 +------+---------+-------------+ +-----------+ +--- --------+ | type | kanal | størrelse | | nyttelast | | ramme - ende | +------+---------+-------------+ +-----------+ +--- --------+ oktet kort lang størrelse oktet oktet

Rammen læses som følger:

  1. Læs header og kontroller rammetype og kanal
  2. Afhængigt af typen af ​​ramme læses data fra nyttelasten og behandles
  3. Læseramme-ende.

I realistiske implementeringer, hvad angår ydeevne, vil vi bruge "read-ahead buffering" eller "gathering reads" for at undgå at lave tre separate systemkald for at læse en ramme.

Method Frames

Metoderammer bærer protokolkommandoer på højt niveau (som vi kalder "metoder"). Én metoderamme indeholder én instruktion. Metodens nyttelast har følgende format:

0 2 4 +-----------+------------+-------------- - - | klasse - id | metode - id | argumenter ... +-----------+------------+-------------- - - kort kort ...

Metoderammen håndteres således:

1. Læsning af nyttelastmetoderammen.

2. Dens udpakning i en struktur. Denne metode har altid samme struktur, så du hurtigt kan pakke den ud

3. Tjek, at denne metode er tilladt i den aktuelle kontekst.

4. Kontrol af at metodeargumenterne er gyldige.

5. Udførelse af denne metode.

Metodens rammelegeme er opbygget som en liste over AMQP-datafelter (bits, heltal, strenge og strengtabeller). Marshaling-koden er trivielt genereret direkte fra protokolspecifikationer og kan være meget hurtig.

Indholdsrammer

Indhold er applikationsdata, som vi overfører fra klient til klient gennem AMQP-serveren. Indholdet er groft sagt et sæt egenskaber plus en binær del af dataene. Sættet af tilladte egenskaber er defineret af basisklassen, og de danner "content header frame". Dataene kan være af enhver størrelse og opdelt i flere (eller mange) blokke, som hver danner et "indholdskropsskelet".

Ser vi på rammerne for en bestemt kanal, mens den transmitteres over ledningen, kan vi se noget som dette:

[ metode ] [ metode ] [ header ] [ body ] [ body [ metode ] ...

Nogle metoder (såsom Basic.Publish , Basic.Deliver osv.) er formelt defineret som indholdsbærende. Når en peer sender en sådan metoderamme, følger den altid den med en indholdsheader og med eller uden nogle få indholdstekstramme. Indholdsrammeoverskriften har følgende format:

0 2 4 12 14 +--------+--------+-----------+----------------+ -------------- - - | klasse - id | vægt | kropsstørrelse | _ ejendomsflag | _ ejendomsliste ... _ +--------+--------+-----------+----------------+ -------------- - - kort kort lang lang kort rest ...

Vi sætter indholdsteksten i separate rammer (i stedet for at inkludere den i en metode), så AMQP kan understøtte "nul kopi"-metoder, hvor indholdet aldrig er marshaleret eller kodet. Vi sætter indholdsegenskaber i deres egen ramme, så modtagere selektivt kan kassere indhold, de ikke ønsker at behandle.

Heartbeat Frames

Heartbeat er en teknik designet til at tilsidesætte en af ​​funktionerne i TCP/IP, nemlig dens evne til at komme sig efter en brudt fysisk forbindelse, der først lukker efter en ret lang timeout. I nogle scenarier skal vi meget hurtigt vide, om peeren er nede eller ikke reagerer af andre årsager (f.eks. sætter den sig fast i en løkke). Da hjerteslag kan udføres på et lavt niveau, vil vi implementere dette som en speciel type frame, der udveksles mellem noder i transportlaget, snarere end som en klassemetode.

Fejlhåndtering

AMQP bruger undtagelser til fejlhåndtering. Enhver driftsfejl (meddelelseskø ikke fundet, utilstrækkelige adgangsrettigheder osv.) vil udløse en kanalundtagelse. Enhver strukturel fejl (dårligt argument, dårlig metodesekvens osv.) resulterer i en forbindelsesundtagelse. Undtagelsen lukker kanalen eller forbindelsen og returnerer en svarkode og svartekst til klientapplikationen. Vi bruger en 3-cifret svarkode plus svarteksttekstskemaet, der bruges i HTTP og mange andre protokoller.


Lukning af kanaler og forbindelser

Forbindelsen eller kanalen siges at være "åben" for klienten, når den sender en Open, og for serveren, når den sender en Open-Ok. Fra nu af skal en peer, der ønsker at lukke en kanal eller forbindelse, gøre det ved hjælp af handshake-protokollen, som er beskrevet her.

Lukning af en kanal eller forbindelse af en eller anden grund - normal eller usædvanlig - skal gøres omhyggeligt. Pludselige lukninger opdages ikke altid hurtigt, og efter en undtagelse kan vi miste fejlsvarkoder. Det korrekte design er at forhandle lukningen manuelt, så kanalen/forbindelsen først lukkes, når vi er sikre på, at den anden side er klar over situationen.

Når en peer beslutter at lukke en kanal eller forbindelse, sender den Luk-metoden. Den modtagende node skal svare på lukningen med et Close-Ok, og så kan begge sider lukke deres kanal eller forbindelse. Bemærk, at hvis peers ignorerer Luk, kan der opstå et dødvande, hvis begge peers sender Luk på samme tid.


AMQP Client Architecture

Det er muligt at læse og skrive AMQP-rammer direkte fra applikationen, men det ville være dårligt design. Selv den enkleste AMQP-samtale er langt mere kompleks end f.eks. HTTP, og applikationsudviklere behøver ikke at forstå ting som binære framing-formater for at sende en besked til en beskedkø. Den anbefalede AMQP-klientarkitektur består af flere abstraktionsniveauer:

  1. Fraiming Layer - tager AMQP-protokolmetoder i et eller andet sprogformat (strukturer, klasser osv.) og serialiserer dem som wire-level frames. Rammelaget kan genereres mekanisk ud fra AMQP-specifikationer (som er defineret i et protokolmodelleringssprog, implementeret i XML og specifikt designet til AMQP).
  2. forbindelseshåndteringslag - læser og skriver AMQP-rammer og styrer den overordnede forbindelses- og sessionslogik. I dette lag kan vi indkapsle den komplette logik for åbning af en forbindelse og session, fejlhåndtering, afsendelse og modtagelse af indhold og så videre. Store dele af dette lag kan laves automatisk ud fra AMQP-specifikationer. For eksempel definerer specifikationer, hvilke metoder der bærer indhold, så logikken "send en metode og derefter eventuelt send indhold" kan oprettes mekanisk.
  3. API Layer - giver en specifik API til at arbejde med applikationer. API-laget kan afspejle en eksisterende standard, eller det kan give AMQP-metoder på højere niveau ved at oprette en kortlægning som beskrevet tidligere. AMQP-metoderne er designet til at gøre denne kortlægning enkel og nyttig. Selve API-laget kan være sammensat af flere lag, såsom en højere niveau API bygget oven på AMQP Method API.

Der er også normalt et niveau af I/O, som kan være meget simpelt (Synchronous socket read and write) eller kompleks (fuldt asynkron multi-threaded I/O). Dette diagram viser den generelle anbefalede arkitektur:

+------------------------+ | ansøgning | +-----------+-------------+ | +------------------------+ +---| API Layer |---- Client API Layer -----+ | +-----------+------------+ | | | | | +------------------------------+ +----------------+ | | | Connection Manager +----+ Framing Layer | | | +-----------+------------+ +-------+ | | | | | +------------------------------+ | +---| Asynkront I / O- lag |------------------------+ +-----------+-------------+ | ------- - - - - Netværk - - - - -------

Når vi i dette dokument taler om "klient-API" mener vi alle lagene under applikationen (i/o, framing, forbindelsesadministrator og API-lag. Vi taler normalt om "klient-API" og "applikation" som to separate ting, hvor applikationen bruger klient-API'en til at tale med middleware-serveren.

Funktionel specifikation

Server funktionel specifikation

Beskeder og indhold

En besked er den atomare behandlingsenhed i et routing- og middleware-køsystem. Meddelelser indeholder indhold, der består af en indholdsoverskrift, der indeholder et sæt egenskaber, og en indholdstekst, der indeholder en uigennemsigtig blok af binære data.

En besked kan svare til mange forskellige applikationsenheder:

  • Besked om applikationslag
  • Sender fil
  • datastrømsramme

Beskeder kan være permanente. En vedvarende besked gemmes sikkert på disken og er garanteret leveret selv i tilfælde af et større netværksudfald, serverfejl, overløb osv.

Beskeder kan have forrang. En besked med høj prioritet sendes før beskeder med lavere prioritet, der venter i den samme beskedkø. Når beskeder skal droppes for at opretholde et vist servicekvalitetsniveau, vil serveren først slippe beskeder med lav prioritet.

Serveren MÅ IKKE ændre indholdet af meddelelser, den modtager og videregiver til forbrugerapplikationer. Serveren MÅ tilføje information til indholdsoverskrifterne, men den MÅ IKKE fjerne eller ændre de eksisterende oplysninger.

Virtuelle værter

En virtuel vært er en del af data på en server, en administrativ bekvemmelighed, der vil vise sig nyttig for dem, der ønsker at levere AMQP som en service på en delt infrastruktur.

Den virtuelle vært indeholder sit eget navneområde, sæt af udvekslinger, beskedkøer og alle relaterede objekter. Hver forbindelse skal være tilknyttet én virtuel vært.

Klienten vælger den virtuelle vært i Connection.Open-metoden efter godkendelse. Dette betyder, at serverens godkendelsesskema er fælles for alle virtuelle noder på den server. Det anvendte autorisationsskema kan dog være unikt for hver virtuel vært. Dette burde være nyttigt for en delt hosting-infrastruktur. Administratorer, der kræver forskellige godkendelsesskemaer for hver virtuel vært, skal bruge separate servere

Alle kanaler i en forbindelse arbejder med den samme virtuelle vært. Der er ingen måde at kontakte en anden virtuel vært på den samme forbindelse, og der er ingen måde at skifte til en anden virtuel vært uden at droppe forbindelsen og starte forfra.

Protokollen tilbyder ingen mekanismer til at oprette eller konfigurere virtuelle værter - dette gøres på en uspecificeret måde inden for serveren og er fuldstændig implementeringsafhængig.

Udvekslinger

Exchange er en besked-routing-agent inde i en virtuel vært. Exchange-instansen (som vi almindeligvis omtaler som en "udveksling") modtager meddelelser og routinginformation - hovedsageligt routing-nøglen - og sender enten beskederne til meddelelseskøer eller til interne tjenester. Udvekslingerne er navngivet på en per virtuel vært basis.

Applikationer er gratis til at oprette, dele og ødelægge udvekslingsforekomster inden for deres autoritet.

Udvekslinger kan være permanente, midlertidige eller automatisk slettet. Permanente udvekslinger eksisterer, indtil de fjernes. Midlertidige udvekslinger eksisterer, indtil serveren lukkes ned. Automatisk slettede udvekslinger eksisterer, indtil de ikke længere bruges.

Serveren giver et specifikt sæt udvekslingstyper. Hver udvekslingstype implementerer en specifik kortlægning og algoritme, som defineret i næste afsnit. AMQP foreskriver et lille antal udvekslingstyper og anbefaler nogle flere. Derudover kan hver serverimplementering tilføje sine egne udvekslingstyper.

En central kan dirigere en enkelt besked til flere beskedkøer parallelt. Dette skaber flere meddelelsesforekomster, der forbruges uafhængigt af hinanden.

Den direkte udvekslingstype

direkte udvekslingstype fungerer sådan her:

  1. Meddelelseskøen tilknyttes udvekslingsserveren ved hjælp af routingnøglen K.
  2. Udgiveren sender en udvekslingsmeddelelse med routingnøglen R.
  3. Meddelelsen sendes til beskedkøen, hvis K = R.

Serveren SKAL implementere en direkte ekchange og SKAL foruddefinere i hver virtuel vært mindst to direkte udvekslinger: en ved navn amqp.direct og en uden et offentligt navn , der fungerer som standardudveksling til håndtering af offentlige metoder.

Bemærk, at meddelelseskøer kan kontaktes ved hjælp af en hvilken som helst gyldig routingnøgleværdi, men oftest vil meddelelseskøer blive kontaktet med deres eget navn som routingnøgle.

Især SKAL alle meddelelseskøer automatisk bindes til en udveksling uden et offentligt navn, ved at bruge meddelelseskønavnet som routingnøgle.

Fanout Exchange Type

Fanout Exchange fungerer sådan her:

  1. Meddelelseskøen er bundet til udvekslingsserveren uden nogen argumenter.
  2. udgiver sender en besked til udveksling.
  3. Beskeden sendes ubetinget videre til meddelelseskøen.

Fanout Exchange er trivielt at designe og implementere. Denne type udveksling og det forudangivne navn amq.fanout , er påkrævet.

Emneudvekslingstypen

Emneudveksling fungerer således:

  1. Meddelelseskøen er bundet til udvekslingsserveren ved hjælp af P-routingmønsteret.
  2. Udgiveren sender en udvekslingsmeddelelse med routingnøglen R.
  3. Beskeden sendes til beskedkøen, hvis R matcher P.

Routing-nøglen, der bruges til emneudveksling, skal bestå af ord adskilt af prikker. Den mindste ordstørrelse er 0 tegn. Hvert ord kan indeholde bogstaverne AZ og az, samt tallene 0-9.

Routingmønsteret følger de samme regler som routingnøglen med tilføjelsen, at * matcher et ord og # matcher nul eller flere ord. Således matcher *.stock.#-ruteskemaet usd.stock og eur.stock.db-rutingsnøglerne, men ikke stock.nasdaq.

En foreslået ordning for Topic Exchange er at beholde et sæt af alle kendte routing-nøgler og opdatere det, når udgivere bruger nye routing-nøgler. Du kan definere alle bindinger for en given rutenøgle og dermed hurtigt finde beskedkøerne til en besked. Denne type udveksling er valgfri.

Serveren skal implementere emneudvekslingstypen, i hvilket tilfælde serveren først skal erklære mindst én emneudveksling ved navn amq.topic i hver virtuel vært.

Overskriftsudvekslingstypen

udvekslingstypen for overskrifter fungerer sådan her:

  1. Meddelelseskøen er bundet til at udveksle med en argumenttabel, der indeholder de overskrifter, der skal matches for denne binding, og eventuelt de værdier, de skal indeholde. Routing-nøglen bruges ikke.
  2. Udgiveren sender en besked til børsen, hvor headers-egenskaben indeholder en tabel med navne og værdier.
  3. Meddelelsen sendes til køen, hvis headers-egenskaben matcher de argumenter, som køen var knyttet til.

Matchningsalgoritmen styres af et specielt bindingsargument, der sendes som et navn-værdi-par i argumenttabellen. Dette argument kaldes "X-match". Det kan tage en af ​​to værdier, der dikterer, hvordan andre navneværdipar i tabellen håndteres under matchning:

  • 'alle' indebærer, at alle andre par skal matche meddelelsens headers-egenskab, for at denne meddelelse kan omdirigeres (AND)
  • 'any' betyder, at meddelelsen skal omdirigeres, hvis nogen af ​​felterne i headers-egenskaben matcher et af felterne i argumenttabellen (OR)

Et felt i bindingsargumenterne matcher et felt i meddelelsen, hvis følgende betingelse er sand: enten har feltet i bindingsargumenterne ingen værdi, og feltet med samme navn er til stede i meddelelseshovederne, eller hvis feltet i bindingen argumenter har en værdi, og feltet med samme navn findes i header-meddelelserne og har samme betydning.

Ethvert felt, der starter med 'x -' bortset fra 'X-match', er reserveret til fremtidig brug og vil blive ignoreret

Serveren SKAL implementere Headers Exchange Type, og serveren SKAL foruderklære mindst én Headers Exchange Type ved navn amq.match i hver virtuel vært.

Systemudvekslingstypen

Systemudvekslingstypen fungerer således:

  1. Udgiveren sender en besked til udveksling med routingnøglen S.
  2. Systemudvekslingen sender den til systemtjenesten S.

Systemtjenester, der starter med "amq." reserveret til AMQP. Alle andre navne kan bruges. Denne type udveksling er valgfri.

Brugerdefinerede udvekslingstyper

Alle brugerdefinerede udvekslingstypenavne skal begynde med "x -". Udvekslingstyper, der ikke begynder med "x -", er reserveret til fremtidig brug i AMQP-standarden.

Meddelelseskøer

En beskedkø er en navngivet FIFO, der indeholder beskeder fra applikationer. Programmer er gratis at oprette, dele, bruge og ødelægge meddelelseskøer inden for deres autoritet.

Bemærk, at når der er flere læsere fra en kø, eller klienttransaktioner, eller bruger prioritetsfelter, eller bruger meddelelsesvælgere eller implementeringsspecifik leveringsoptimering, har køen muligvis ikke ægte FIFO-karakteristika. Den eneste måde at garantere FIFO på er kun at have én forbruger forbundet til køen. I disse tilfælde kan køen beskrives som "svag-FIFO".

Beskedkøer kan være permanente, midlertidige eller automatisk slettet. Vedvarende beskedkøer eksisterer, indtil de fjernes. Der eksisterer midlertidige beskedkøer, indtil serveren lukkes ned. Autoslet-køer varer, indtil de ikke længere er i brug.

Meddelelseskøer gemmer deres beskeder i hukommelsen, på disken eller en kombination af de to. Meddelelseskøer navngives baseret på den virtuelle vært.

Beskedkøer indeholder beskeder og distribuerer dem til en eller flere forbrugerkunder. En besked sendt til en beskedkø sendes aldrig til mere end én klient, medmindre den er blevet afvist

Én beskedkø kan indeholde forskellige typer indhold samtidigt og uafhængigt. Det vil sige, at hvis hovedindholdet og filindholdet sendes til den samme beskedkø, vil de blive leveret til forbrugende applikationer uafhængigt efter anmodning.

Indbindinger

Binding er forbindelsen mellem beskedkø og dataudveksling. Bindingen definerer routing-argumenterne, der fortæller udvekslingen, hvilke beskeder køen skal modtage. Applikationer opretter og ødelægger bindinger efter behov for at dirigere strømmen af ​​beskeder til deres beskedkøer. En bindings levetid afhænger af de meddelelseskøer, som de er defineret for - når en meddelelseskø ødelægges, ødelægges dens binding også. Den specifikke semantik af Queue.Bind-metoden afhænger af udvekslingstypen.

Forbrugere - forbrugere

Vi bruger udtrykket forbruger til at henvise til både klientapplikationen og den enhed, der kontrollerer, hvordan en bestemt klientapplikation modtager meddelelser fra meddelelseskøen. Når en klient "starter en forbruger", opretter den en forbrugerentitet på serveren. Når en klient "annullerer en forbruger", ødelægger den forbrugerenheden på serveren. Forbrugere tilhører den samme kundekanal og tvinger beskedkøen til at sende beskeder til kunden asynkront.

Servicekvalitet

Tjenestens kvalitet bestemmer hastigheden, hvormed beskeder sendes. Kvaliteten af ​​servicen afhænger af typen af ​​indhold, der distribueres. Generelt bruger QoS konceptet "prefetch" til at angive, hvor mange meddelelser eller hvor mange oktetter af data, der vil blive sendt, før klienten anerkender meddelelsen. Målet er at sende beskeddataene før tid for at reducere latens.

Anerkendelser

En bekræftelse er et formelt signal fra en klientapplikation til meddelelseskøen om, at den har behandlet en meddelelse. Der er to mulige valideringsmodeller:

  1. Automatisk - hvor serveren fjerner indholdet fra meddelelseskøen, så snart det er leveret til applikationen (ved hjælp af Deliver eller Get-Ok metoderne).
  2. Eksplicit - hvor klientapplikationen skal sende Ack-metoden for hver meddelelse eller batch af meddelelser, den har behandlet

Klientlag kan selv implementere eksplicitte bekræftelser på forskellige måder, såsom umiddelbart efter at have modtaget en besked, eller når en applikation angiver, at den har behandlet den. Disse forskelle påvirker ikke AMQP eller interoperabilitet.

flowkontrol

Flowkontrol er en nødprocedure, der bruges til at stoppe strømmen af ​​beskeder fra en peer. Det fungerer på samme måde mellem klient og server og implementeres af Channel.Flow-kommandoen. Flow Control er den eneste mekanisme, der kan stoppe en overproduktiv udgiver. En forbruger kan bruge en mere elegant vindues-forhentningsmekanisme, hvis den bruger anerkendelser (hvilket normalt betyder brug af transaktioner).

Navngivningskonvention

Disse konventioner regulerer navngivningen af ​​AMQP-enheder. Serveren og klienten skal respektere disse konventioner:

  • Tilpassede udvekslinger skal starte med "x-" præfiks
  • Standardudvekslingsforekomster skal begynde med præfikset "amq."
  • Standard systemtjenester skal begynde med præfikset "amq."
  • Standard meddelelseskøer skal begynde med præfikset "amq."

Specifikation af AMQP-kommandoer (klasser og metoder)

Noter

AMQP-metoder kan definere minimumsværdier (såsom antallet af forbrugere i en beskedkø) af kompatibilitetsårsager. Disse minimumskrav er defineret i beskrivelsen af ​​hver klasse.

Overensstemmende AMQP-implementeringer bør implementere ret generøse værdier for sådanne felter, minimumsværdierne er kun beregnet til at blive brugt på de mindst egnede platforme.

Grammatikker bruger denne notation:

  • 'S:' angiver data eller metode sendt fra serveren til klienten;
  • 'C:' angiver data eller metode sendt fra klienten til serveren;
  • +betingelse eller +(...) udtryk betyder "1 eller flere forekomster";
  • *betingelse eller *(...) udtryk betyder "nul eller flere forekomster".

Vi definerer metoder som:

  • synkron anmodning ("syn request"). Den afsendende vært skal vente på en specifik svarmetode, men kan implementere denne asynkront;
  • synkront svar ("syn svar for XYZ");
  • asynkron anmodning eller svar ("asynkron")

Teknisk specifikation

Portnumre defineret af IANA

Standard AMQP-portnummeret er blevet tildelt af IANA som 5672 for både TCP og UDP. UDP-port reserveret til brug i fremtidige multicast-implementeringer

Trådniveauformat til AMQP

Officiel grammatikprotokol

Vi leverer en komplet grammatik til AMQP (dette er givet til reference, og du kan være mere interesseret i at følge sektionerne, der beskriver de forskellige typer rammer og deres formater):

amqp = protokol - header * amqp - enhed protokol - header = bogstavelig - AMQP -protokol - id -protokol - version literal - AMQP = % d65 .77.81.80 ; "AMQP" protokol - id = % d0 ; Skal være 0 protokol - version = % d0.9.1 ; _ 0-9-1 metode = metode - ramme [ indhold ] metode - ramme = % d1 ramme - egenskaber metode - nyttelast ramme - slut ramme - egenskaber = kanal nyttelast - størrelse kanal = short - uint ; ikke - nul nyttelast - størrelse = lang - uint metode - nyttelast = klasse - id metode - id * amqp - felt klasse - id = % x00 .01 - % xFF . FF metode - id = % x00 .01 - % xFF . FF amqp - felt = BIT / OCTET / kort - uint / lang - uint / lang - lang - uint / kort - streng / lang - streng / tidsstempel / felt - tabel kort - uint = 2 * OCTET lang - uint = 4 * OCTET lang - lang - uint = 8 * OCTET kort - streng = OCTET * streng - char ; længde + indhold streng - char = % x01 .. % xFF lang - streng = lang - uint * OCTET ; længde + indhold timestamp = lang - lang - uint ; 64 - bit POSIX felt - tabel = lang - uint * felt - værdi - par felt - værdi - par = felt - navn felt - værdi felt - navn = kort - streng felt - værdi = 't' boolesk / 'b' kort - kort - int / 'B' kort - kort - uint / 'U' kort - int / 'u' kort - uint / 'Jeg' længe - int / 'jeg' lang - uint / 'L' lang - lang - int / 'l' lang - lang - uint / 'f' flyder / 'd' dobbelt / 'D' decimal - værdi / 's' kort - streng / 'S' lang - streng / 'A' felt - array / 'T' tidsstempel / 'F' felt - tabel / 'V' ; intet felt boolean = OCTET ; 0 = FALSK , ellers SAND kort - kort - int = OCTET kort - kort - uint = OCTET kort - int = 2 * OCTET lang - int = 4 * OCTET lang - lang - int = 8 * OCTET flyde = 4 * OCTET ; IEEE -754 dobbelt = 8 * OCTET ; rfc1832 XDR dobbelt decimal - værdi = skala lang - uint skala = OCTET ; antal decimaler _ _ felt - matrix = lang - int * felt - værdi ; række af værdier ramme - ende = % xCE indhold = % d2 indhold - overskrift * indhold - brødtekst indhold - overskrift = ramme - egenskaber overskrift - nyttelastramme - slutning _ header - nyttelast = indhold - klasseindhold - vægtindhold - krop - størrelse _ _ ejendom - flag ejendom - liste indhold - klasse = oktet indhold - vægt = % x00 indhold - krop - størrelse = lang - lang - uint egenskab - flag = 15 * BIT % b0 / 15 * BIT % b1 egenskab - flag ejendom - liste = * amqp - felt content - body = % d3 frame - egenskaber body - payload frame - end krop - nyttelast = * OCTET hjerteslag = % d8 % d0 % d0 frame - end


Vi bruger den udvidede BNF-syntaks defineret i IETF RFC 2234. Som konklusion:

  • Navnet på reglen er blot selve navnet
  • Terminaler er specificeret med et eller flere numeriske tegn, med basisfortolkningen af ​​disse tegn angivet som "d" eller "x"
  • En regel kan definere en simpel ordnet streng af værdier ved at angive en sekvens af regelnavne
  • En række alternative numeriske værdier kan specificeres kompakt ved at bruge en bindestreg ( " - " ) for at angive området
  • Elementer anført i parentes behandles som et enkelt element, hvis indhold er strengt ordnet.
  • Elementer adskilt af en skråstreg (" / " ) er alternativer.
  • Operatoren * foran et element angiver gentagelse. Lang form: "<a>*< b>element", hvor <a> og <b> er valgfri decimalværdier, mindst <a> og højst <b> elementforekomster.
Protokoloverskrift

Klienten skal starte en ny forbindelse ved at sende protokolhovedet. Dette er en 8 oktet sekvens:

+---+---+---+---+----+---+---+---+ | 'A' | 'M' | 'Q' | 'P' | 0 | 0 | 9 | 1 | +---+---+---+---+----+---+---+---+ 8 oktetter

Protokolhovedet består af de store bogstaver "AMQP" efterfulgt af konstanten %d0 efterfulgt af:

  1. Hovedversionen af ​​protokollen, der anvendes i overensstemmelse med afsnit 1.4.2. (off. dokumentation version 0-9-1)
  2. Mindre version af protokollen anvendt i overensstemmelse med afsnit 1.4.2. (off. dokumentation version 0-9-1)
  3. Protokolrevision anvendt i overensstemmelse med afsnit 1.4.2. (off. dokumentation version 0-9-1)

Protokolforhandlingsmodellen er kompatibel med eksisterende protokoller såsom HTTP, som initierer en forbindelse med en konstant tekststreng, og med firewalls, som overvåger begyndelsen af ​​en protokol for at beslutte, hvilke regler der skal gælde for den.

Klienten og serveren forhandler protokollen og versionen som følger:

  • Klienten åbner en ny socketforbindelse til AMQP-serveren og sender en protokolheader.
  • Serveren enten accepterer eller afviser protokolheaderen. Hvis den afviser protokolheaderen, skriver den en gyldig protokolheader til soklen og lukker derefter soklen.
  • Ellers efterlader den stikket åben og implementerer protokollen korrekt.

Eksempel:

Klienten sender : Serveren svarer : AMQP % d0 .0.9.1 Tilslutning . start metode AMQP % d0 .1.0.0 AMQP % d0 .0.9.1 < Luk forbindelse > HTTP AMQP % d0.0.9.1 < Luk forbindelse > _

Principper for implementering af protokollen:

  • Serveren kan acceptere ikke-AMQP-protokoller såsom HTTP
  • Hvis serveren ikke genkender de første 5 oktetter af data på socket, eller ikke understøtter den bestemte protokolversion, klienten anmoder om, skal den skrive en gyldig protokolheader til socket, og derefter skylle socket (for at sikre, at klienten applikationen modtager dataene) og luk derefter forbindelsen med stikkontakten. Serveren kan udskrive en diagnosticeringsmeddelelse til fejlfindingsformål.
  • En klient kan bestemme serverens protokolversion ved at forsøge at oprette forbindelse til dens højest understøttede version og genoprette forbindelsen til en lavere version, hvis den modtager sådanne oplysninger tilbage fra serveren.
  • Klienter og servere, der implementerer flere versioner af AMQP, SKAL bruge alle otte oktetter i protokolheaderen til at identificere protokollen.


Grundlæggende rammeformat

Alle frames starter med en 7-oktet-header bestående af et typefelt (oktet), et kanalfelt (kort heltal) og et længdefelt (langt heltal):

0 1 3 7 størrelse + 7 størrelse + 8 +------+---------+---------+ +---------+ +------ -----+ | type | kanal | størrelse | | nyttelast | | ramme - ende | +------+---------+---------+ +---------+ +------ -----+ oktet kort lang ' størrelse ' oktet oktet

AMQP definerer følgende rammetyper:

  • Type = 1, "METHOD": metoderamme.
  • Type = 2, "HEADER": indholdsoverskriftsramme
  • Type = 3, "BODY": indholdstekstramme.
  • Type = 4, "HEARTBEAT": hjerteslagsramme.

Kanalnummeret er 0 for alle frames, der er globale for forbindelsen og 1-65535 for frames, der refererer til specifikke kanaler.

Størrelsesfeltet er størrelsen på nyttelasten, eksklusive end-of-frame-oktetten. Mens AMQP antager en pålidelig forbundet protokol, bruger vi slutningen af ​​rammen til at detektere rammefejl forårsaget af forkerte klient- eller serverimplementeringer.

Principper for implementering af protokollen:

  • End-of-frame-oktetten skal altid have den hexadecimale værdi %xCE.
  • Hvis en peer modtager en ramme med en type, der ikke er en af ​​disse definerede typer, bør den behandle dette som en fatal protokolfejl og lukke forbindelsen uden at sende yderligere data om det.
  • Når en peer læser en ramme, skal den kontrollere, at slutningen af ​​rammen er gyldig, før den forsøger at afkode rammen. Hvis slutningen af ​​rammen ikke er gyldig, bør den behandle dette som en fatal protokolfejl og lukke forbindelsen uden at sende yderligere data om det. Det bør logge oplysninger om problemet, da dette indikerer en fejl i implementeringen af ​​serveren eller klientens rammekode.
  • En peer MÅ IKKE sende rammer større end den forhandlede størrelse. En peer, der modtager en ramme, der er for stor, SKAL signalere en forbindelsesundtagelse med en 501 (rammefejl) svarkode.
  • Kanalnummeret skal være nul for alle hjerteslagsrammer og for metode-, header- og bodyframes, der refererer til Connection-klassen. En peer, der modtager et ikke-nul kanalnummer for en af ​​disse frames, SKAL signalere en forbindelsesundtagelse med en 503 (kommando ugyldig) svarkode.
Metode Nyttelast

Metoderammelegemer består af en invariant liste over datafelter kaldet "argumenter". Alle metodelegemer starter med klasse- og metodeidentifikatorer:

0 2 4 +-----------+------------+-------------- - - | klasse - id | metode - id | argumenter ... +-----------+------------+-------------- - - kort kort ...

Principper for implementering af protokollen:

  • Klasse-id'et og metode-id'et er konstanter defineret i AMQP-klasse- og metodespecifikationerne.
  • Argumenter er et sæt AMQP-felter, der er specifikke for hver metode
  • Værdiklasseidentifikatoren %x00.01 til %xEF.FF er reserveret til standard AMQP-klasser.
  • Klasse-id'er fra %xF0.00 til %xFF.FF (%d61440-%d65535) kan bruges, når de er implementeret til ikke-standardudvidelsesklasser.
AMQP-datafelter

AMQP har to niveauer af datafeltspecifikation: native datafelter, der bruges til metodeargumenter, og datafelter, der sendes mellem applikationer i felttabeller. Felttabeller indeholder et hævet sæt af indbyggede datafelter.

Heltal

AMQP definerer følgende native heltalstyper:

  • Usigneret oktet (8 bit).
  • Korte heltal uden fortegn (16 bit).
  • Lange heltal uden fortegn (32 bit).
  • Lange lange heltal uden fortegn (64 bit).

Heltal og strenglængder er altid usignerede og gemt i netværksbyterækkefølge. Vi forsøger ikke at optimere tilfældet, hvor to lav-høj-systemer (f.eks. to Intel-processorer) taler med hinanden.

Principper for implementering af protokollen:

  • Designere bør ikke antage, at de heltal, der er kodet i en ramme, er justeret på hukommelsesordgrænser.
Bits

AMQP definerer sin egen type bitfelt. Bitsene akkumuleres i hele oktetter. Når to eller flere bits rører hinanden i en ramme, vil de blive pakket i en eller flere oktetter, begyndende med den laveste bit i hver oktet. Der er intet krav om, at alle bitværdier i en ramme skal være sammenhængende, men dette gøres normalt for at minimere rammestørrelser.

Strings

AMQP-strenge har variabel længde og er repræsenteret af en heltalslængde efterfulgt af nul eller flere dataoktetter. AMQP definerer to indbyggede rækketyper:

  • Korte strenge gemt som en 8-bit heltalslængde uden fortegn efterfulgt af nul eller flere oktetter af data. Korte strenge kan indeholde op til 255 oktetter UTF-8-data, men kan ikke indeholde binære null-oktetter.
  • Lange strenge gemt som en 32-bit heltalslængde uden fortegn efterfulgt af nul eller flere oktetter af data. Lange strenge kan indeholde alle data
Tidsstempler

Tidsstempler gemmes i 64-bit POSIX time_t-formatet med en præcision på et sekund. Ved at bruge 64 bit undgår vi fremtidige indpakningsproblemer forbundet med 31-bit og 32-bit time_t-værdier.

Tabelmargener

Tabelfelter er lange strenge, der indeholder pakkede navn-værdi-par. Navneværdipar er kodet som en kort streng, der angiver navnet, og en oktet, der angiver værditypen, efterfulgt af selve værdien. Gyldige felttyper for tabeller er udvidelser af de oprindelige typer heltal, bit, streng og tidsstempel og vises i grammatikken. Heltalsfelter med flere oktetter gemmes altid i netværksbyterækkefølge.

Principper for implementering af protokollen:

  • Feltnavne skal begynde med bogstavet "$" eller "#" og kan fortsætte med bogstaverne "$" eller "#", tal eller understregninger, op til en maksimal længde på 128 tegn.
  • Serveren SKAL validere feltnavnene, og når den modtager et ugyldigt feltnavn, SKAL den signalere en forbindelsesundtagelse med en 503 (syntaksfejl) svarkode.
  • Decimalværdier er ikke designet til at understøtte flydende kommaværdier, men til at understøtte forretningsværdier med faste kommaer såsom valutakurser og beløb. De er kodet som en oktet, der repræsenterer antallet af pladser efterfulgt af et langt heltal med fortegn. Oktet "decimaler" - ikke underskrevet.
  • Duplikerede felter er ulovlige. En peers adfærd i forhold til en tabel, der indeholder duplikerede felter, er udefineret.
Indholdsbeskæring

Visse specifikke metoder (Publicer, Lever osv.) behandler indholdet. Se kapitlet "Funktionelle specifikationer" for specifikationer for hver metode. Metoder, der behandler indhold, gør det ubetinget.

Indholdet består af en liste med 1 eller flere rammer som følger:

  1. Præcis én indholdsoverskriftsramme, der giver egenskaber for indholdet.
  2. Eventuelt en eller flere indholdstekstrammer

Indholdsrammer på en bestemt kanal er strengt sekventielle. Det vil sige, at de kan blandes med frames for andre kanaler, men ikke to indholdsframes fra samme kanal kan blandes og kan ikke "overlappe" hinanden, og indholdsframes for det samme indhold kan ikke blandes med metodeframes på samme kanal ... (orig. Indholdsrammer på en specifik kanal er strengt sekventielle. Det vil sige, at de kan blandes med frames for andre kanaler, men ikke to indholdsrammer fra samme kanal må blandes eller overlappes, og indholdsframes for et enkelt indhold må heller ikke være blandet. blandet med metoderammer på samme kanal.)

Bemærk, at enhver ikke-indholdsramme eksplicit markerer slutningen af ​​indholdet. Mens størrelsen af ​​indholdet er velkendt fra indholdsoverskriften (og dermed antallet af indholdsrammer), giver dette afsenderen mulighed for at afbryde indholdet uden at skulle lukke kanalen.

Principper for implementering af protokollen:

  • En peer, der modtager ufuldstændig eller dårligt formateret indhold, bør afgive en forbindelsesundtagelse med en 505 (Unexpected Frame)-svarkode. Dette inkluderer manglende indholdsoverskrifter, forkerte klasse-id'er i indholdsoverskrifter, manglende indholdstekstrammer osv.
Indholdstitel

Indholdsnyttelast-headeren har følgende format:

0 2 4 12 14 +--------+--------+-----------+----------------+ -------------- - - | klasse - id | vægt | kropsstørrelse | _ ejendomsflag | _ ejendomsliste ... _ +--------+--------+-----------+----------------+ -------------- - - kort kort lang lang kort rest ...

Principper for implementering af protokollen:

  • Klasse-id'et skal matche metoderammens klasse-id. Peeren skal svare på en ugyldig klasseidentifikator ved at sende en forbindelsesundtagelse med en 501 (rammefejl) svarkode.
  • Vægtfeltet bruges ikke og skal være nul.
  • Body Size er en 64-bit værdi, der specificerer den samlede størrelse af indholdets brødtekst, som er summen af ​​brødtekststørrelserne af de følgende rammer i indholdsteksten. Nul angiver ingen indhold-body frames.
  • Egenskabsflag er et array af bit, der angiver tilstedeværelsen eller fraværet af hver egenskabsværdi i sekvensen. Bitsene er ordnet fra højeste til laveste. Bit 15 peger på den første ejendom.
  • Ejendomsflag kan angive mere end 16 ejendomme. Hvis den sidste bit (0) er sat, betyder det, at den efterfølges af et andet egenskabsflagfelt. Der er mange ejendomsflagfelter.
  • Ejendomsværdier er klassespecifikke AMQP-datafelter.
  • Bitegenskaber er kun angivet med det tilsvarende egenskabsflag (1 eller 0) og er aldrig til stede i egenskabslisten.
  • Kanalnummeret i indholdsrammer må ikke være nul. En peer, der modtager et kanalnummer på nul i en indholdsramme, SKAL signalere en forbindelsesundtagelse med en 504 (kanalfejl) svarkode.
Indholdstekst

Indholdstekstens nyttelast er en "ugennemsigtig" binær blok, der slutter med en frame-oktet:

+----------------------------+ +-----------+ | Uigennemsigtig binær nyttelast | | ramme - ende | +----------------------------+ +-----------+

Indholdsteksten kan opdeles i så mange rammer, som det er nødvendigt. Den maksimale frames nyttelaststørrelse forhandles af begge peers under forbindelsesforhandling.

Principper for implementering af protokollen:

  • Peeren skal behandle indholdet, der er opdelt i flere frames, gemme disse frames som et enkelt sæt og enten gentransmittere dem, som de er, opdele dem i mindre frames eller flette dem til en enkelt blok til levering til applikationen.
hjerteslag rammer

Hjerteslagsrammer fortæller modtageren, at afsenderen stadig er i live. Frekvensen og timingen af ​​Heartbeat-frames forhandles under forbindelsesopsætningen.

Principper for implementering af protokollen:

  • Heartbeat-rammer skal have et kanalnummer på nul. En peer, der modtager en ugyldig Heartbeat-ramme, SKAL afgive en forbindelsesundtagelse med en 501 (Frame Error)-svarkode.
  • Hvis peeren ikke understøtter Heartbeat, SKAL den kassere Heartbeat-rammen uden at signalere nogen fejl eller funktionsfejl.
  • Klienten skal begynde at sende Heartbeat efter at have modtaget Connection.Tune-metoden og begynde at overvåge Heartbeat efter at have modtaget Connection.Open. Serveren skal begynde at sende og overvåge Heartbeat efter at have modtaget Connection.Tune-Ok
  • Noden skal gøre alt for at sende Heartbeat med bestemte intervaller. Hjerteslag kan sendes til enhver tid. Enhver sendt oktet er en gyldig Heartbeat-erstatning, så Heartbeats bør kun sendes, hvis AMQP-trafik uden et Heartbeat ikke sendes i mere end et Heartbeat-interval. Hvis peeren registrerer ingen indgående trafik (dvs. modtagne oktetter) i to eller flere Heartbeat-intervaller, SKAL den lukke forbindelsen uden at kalde Connection.Close/Close-Ok-handshaking og logge fejlen
  • Hjerteslag bør fortsætte, indtil stikkontakten er lukket, inklusive under og efter tilslutning. Luk/Luk-Ok håndtryk

Kanalmultipleksing

AMQP giver peers mulighed for at skabe flere uafhængige kontrolstrømme. Hver kanal fungerer som en virtuel forbindelse, der deler et stik:

rammer rammer rammer rammer +-----------+------------+------------+-------+ | kanal | kanal | kanal | kanal | +-----------+------------+------------+-------+ | fatning | +------------------------------------------------ ----+

Principper for implementering af protokollen:

  • En AMQP-peer understøtter MÅSKE flere kanaler. Det maksimale antal kanaler bestemmes ved forhandling af en forbindelse, og en peer kan forhandle dette antal op til 1.
  • Hver peer SKAL balancere trafikken på alle åbne kanaler på en rimelig måde. Denne afbalancering kan udføres pr. frame-basis eller baseret på mængden af ​​trafik pr. kanal. En peer MÅ IKKE tillade, at en meget travl kanal begrænser fremskridtet for en mindre travl kanal.

Garanteret synlighed

Serveren skal sikre, at klientobservationer af serverens tilstand er konsistente.

Følgende eksempel viser, hvad klientobservation betyder i denne sammenhæng:

  • Klient 1 og klient 2 er forbundet til den samme virtuelle vært
  • Klient 1 erklærer en kø
  • Klient 1 modtager Declare.Ok
  • Kunde 1 fortæller klient 2 om det
  • Klient 2 laver en passiv erklæring af den samme kø

Synlighedsgarantien sikrer, at klient 2 ser køen

Lukning af kanalen

Serveren vil betragte kanalen som lukket, hvis noget af følgende sker:

  • Enten lukker peeren kanalen eller forældreforbindelsen ved hjælp af Luk/Luk-Ok-håndtrykket
  • Enten kaster peeren en undtagelse på kanalen eller forældreforbindelsen.
  • Enten lukker noden den overordnede forbindelse uden Luk/Luk-Ok-håndtryk

Når serveren lukker en kanal, markeres alle ikke-bekræftede beskeder på kanalen til genlevering. Når serveren lukker en forbindelse, fjerner den alle automatisk slettede enheder, der hører til den forbindelse.

Indholdssynkronisering

I nogle tilfælde påvirker synkrone anmodningssvar-metoder asynkron levering af indhold over den samme kanal, herunder:

  • Metoder Basic.Consume og Basic.Cancel, der starter og stopper strømmen af ​​beskeder fra beskedkøen
  • Basic.Recover-metoden, der anmoder om omlevering af beskeder til kanalen
  • Queue.Bind, Queue.Unbind og Queue.Purge metoder, der påvirker strømmen af ​​meddelelser, der dirigeres til meddelelseskøen

Principper for implementering af protokollen:

  • Effekterne af anmodning-svar bør ikke være synlige på kanalen før svarmetoden og bør være synlige efter den.

Indholdsbestillingsgaranti

Rækkefølgen, hvori metoder passerer gennem en kanal, er stabil: metoder modtages i samme rækkefølge, som de sendes. På transportlaget leveres dette af TCP/IP-protokollen. Derudover behandles indholdet stabilt af serveren. Især indhold, der følger samme sti inden for serveren, forbliver bestilt. For indhold med en given prioritet, der går gennem en enkelt sti, definerer vi indholdsbehandlingsstien som bestående af én indgående kanal, én central, én kø og én udgående kanal.

Principper for implementering af protokollen:

  • Serveren SKAL bevare rækkefølgen af ​​indhold, der passerer gennem en enkelt indholdsbehandlingssti, medmindre genleveringsfeltet er blevet ændret i Basic.Deliver eller Basic.Get-Ok metoderne og i overensstemmelse med de regler, der definerer de betingelser, hvorunder feltet kan blive indstillet.

Fejlhåndtering

Undtagelser

Ved at bruge standardprogrammeringsmodellen "undtagelser" signalerer AMQP ikke succes, kun fiasko. AMQP definerer to niveauer af ekskluderinger:

  1. Kanalekskluderinger. De lukker den kanal, der forårsagede fejlen. Kanalundtagelser skyldes normalt "bløde" fejl, der ikke påvirker resten af ​​applikationen.
  2. Forbindelsesundtagelser . De lukker stikkontakten og skyldes normalt "hårde" fejl, som indikerer en programmeringsfejl, dårlig konfiguration eller anden hændelse, der kræver opmærksomhed.

Vi dokumenterer formelt påstandene i definitionen af ​​hver klasse og metode.

Svarkodeformat

AMQP-svarkoder følger definitionen af ​​"svarkodes alvorlighed og teori" i IETF RFC 2821.

Implementeringer

Funktioner i AMQP-protokollen

  • Strenge i AMQP skelner mellem store og små bogstaver
  • Versioneringskonvention - versionsnummeret består af to eller tre cifre: major.minor.revision I dette tilfælde er revision valgfri. Tal kan have værdier fra 0 til 99. Tal fra 100 og opefter er reserveret til internt brug. Version 1.1 svarer til version 1.1.0

Noter

  1. Mod en varevirksomheds-middleware . Hentet 14. juni 2010. Arkiveret fra originalen 5. marts 2010.

Litteratur

  • Emrah Ayanoglu; Yusuf Aytas; Dotan Nahum. Mastering RabbitMQ. - Packt Publishing, 2016. - 286 s. — ISBN 978-1-78398-153-3 .

Links