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] .
AMQP er baseret på tre koncepter:
Protokollen kan opdeles i to lag:
Eksempler på kø:
Protokollen er ikke begrænset til disse tre slags. De er givet som eksempler på implementering.
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.
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.
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.
Når en klientapplikation opretter en beskedkø, kan den angive følgende egenskaber:
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 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 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:
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.
Afsnittet beskriver processen med interaktion mellem applikationen og serveren
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).
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:
Kø . erklære kø = min . kø auto - slet = SAND eksklusiv = FALSKDet kan konverteres til en netværksramme:
+--------+--------------------------- ----+ | Kø | erklære | min . kø | 1 | 0 | +--------+--------------------------- ----+ klasse metodenavn auto - slet eksklusiv _Eller i en API-metode på højt niveau
Kø . Erklære ( "min.kø" , TRUE , FALSE );Asynkron metode, der matcher logik i pseudokode:
send metode til serverSynkron metode matchende logik i pseudokode:
send anmodningsmetode til serveren _ gentage vente på svar fra serveren hvis respons er en asynkron metode procesmetode ( normalt leveret eller returneret indhold ) _ _ andet hævde , at metoden er et gyldigt svar på anmodning afslutte gentag ende - hvis slut - gentagDet 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.
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.
Forbindelsen er designet til at være holdbar og håndtere mange kanaler.
Forbindelsens livscyklusDer udveksles ikke oplysninger for fejl ved ufuldstændigt åbnede forbindelser. Værten, der stødte på fejlen , bør lukke stikket uden yderligere varsel.
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:
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 livscyklusKø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.
Protokollen giver mulighed for to kølivscyklusser:
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 livscyklusBasisklassen implementerer meddelelsesfunktionerne beskrevet i denne specifikation. Det understøtter følgende semantik:
AMQP understøtter to typer transaktioner:
Klassen Transaction ("tx") giver applikationer adgang til den anden type transaktion, lokale servertransaktioner. Klassens semantik er som følger:
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.
Dette afsnit forklarer, hvordan kommandoer knytter sig til wire-level- protokollen.
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.
AMQP datatyper brugt i frames:
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:
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:
TCP/IP-stak - fungerer med streams, den har ikke en indbygget rammeafgrænsningsmekanisme. Eksisterende protokoller løser dette problem på flere forskellige måder:
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 oktetRammen læses som følger:
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.
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.
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 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.
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.
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.
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:
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.
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:
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ærterEn 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.
UdvekslingerExchange 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 udvekslingstypedirekte udvekslingstype fungerer sådan her:
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 TypeFanout Exchange fungerer sådan her:
Fanout Exchange er trivielt at designe og implementere. Denne type udveksling og det forudangivne navn amq.fanout , er påkrævet.
EmneudvekslingstypenEmneudveksling fungerer således:
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.
Overskriftsudvekslingstypenudvekslingstypen for overskrifter fungerer sådan her:
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:
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.
SystemudvekslingstypenSystemudvekslingstypen fungerer således:
Systemtjenester, der starter med "amq." reserveret til AMQP. Alle andre navne kan bruges. Denne type udveksling er valgfri.
Brugerdefinerede udvekslingstyperAlle brugerdefinerede udvekslingstypenavne skal begynde med "x -". Udvekslingstyper, der ikke begynder med "x -", er reserveret til fremtidig brug i AMQP-standarden.
MeddelelseskøerEn 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.
IndbindingerBinding 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 - forbrugereVi 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.
ServicekvalitetTjenestens 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.
AnerkendelserEn bekræftelse er et formelt signal fra en klientapplikation til meddelelseskøen om, at den har behandlet en meddelelse. Der er to mulige valideringsmodeller:
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.
flowkontrolFlowkontrol 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).
NavngivningskonventionDisse konventioner regulerer navngivningen af AMQP-enheder. Serveren og klienten skal respektere disse konventioner:
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:
Vi definerer metoder som:
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
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:
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 oktetterProtokolhovedet består af de store bogstaver "AMQP" efterfulgt af konstanten %d0 efterfulgt af:
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:
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:
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 oktetAMQP definerer følgende rammetyper:
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:
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:
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.
AMQP definerer følgende native heltalstyper:
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:
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.
StringsAMQP-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:
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.
TabelmargenerTabelfelter 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:
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:
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:
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:
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:
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:
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:
Serveren skal sikre, at klientobservationer af serverens tilstand er konsistente.
Følgende eksempel viser, hvad klientobservation betyder i denne sammenhæng:
Synlighedsgarantien sikrer, at klient 2 ser køen
Serveren vil betragte kanalen som lukket, hvis noget af følgende sker:
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.
I nogle tilfælde påvirker synkrone anmodningssvar-metoder asynkron levering af indhold over den samme kanal, herunder:
Principper for implementering af protokollen:
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:
Ved at bruge standardprogrammeringsmodellen "undtagelser" signalerer AMQP ikke succes, kun fiasko. AMQP definerer to niveauer af ekskluderinger:
Vi dokumenterer formelt påstandene i definitionen af hver klasse og metode.
SvarkodeformatAMQP-svarkoder følger definitionen af "svarkodes alvorlighed og teori" i IETF RFC 2821.