AMQP (Advanced Message Queuing Protocol) är ett öppet applikationslagerprotokoll för att skicka meddelanden mellan systemkomponenter. Huvudtanken är att enskilda delsystem (eller oberoende applikationer) kan utbyta meddelanden godtyckligt genom en AMQP-mäklare som utför routing , eventuellt garanterar leverans, distribution av dataflöden, prenumeration på önskade typer av meddelanden.
Protokollarkitekturen utvecklades av John O'Hara från JP Morgan Chase & Co [1] .
AMQP bygger på tre koncept:
Protokollet kan delas in i två lager:
Exempel på kö:
Protokollet är inte begränsat till dessa tre typer. De ges som exempel på implementering.
Tar emot meddelanden från leverantören och dirigerar dem till meddelandekön enligt fördefinierade kriterier. Sådana kriterier kallas bindningar. Utbyte är en mekanism för meddelandeförhandling och routing. Baserat på meddelandena och deras parametrar (bindningar) fattar de ett beslut om omdirigering till en kö eller annan växel. Spara inte meddelanden.
Termen utbyte betyder algoritm och algoritminstans. De säger också utbytestyp och utbytesinstans.
AMQP definierar en uppsättning standardutbytestyper. Applikationer kan skapa sin egen utbytesinstans.
Varje börs implementerar sin egen routingalgoritm. Det finns flera standardutbytestyper som beskrivs i standardens funktionsspecifikation. Av dessa är två viktiga:
Servern kommer att skapa flera utbyten, inklusive direkt och ämne. De kommer att ha välkända namn och klientapplikationer kommer att kunna arbeta med dem.
Varje AMQP-server skapar i förväg flera instanser av utbyte. Dessa instanser finns när servern körs och kan inte förstöras. AMQP-applikationer kan också skapa sina egna börser. AMQP använder inte skapa-metoden för detta, istället deklareras instansen, vilket följer logiken: "skapa om inte skapat, fortsätt annars". Man kan säga att skapandet av utbyte är idempotent . Förmodligen kommer applikationer att skapa utbyten efter behov, och sedan förstöra dem som onödiga. AMQP tillhandahåller en metod för att förstöra utbytet.
I allmänhet undersöker utbytet meddelandets egenskaper, rubrikfälten och innehållet i dess kropp, och bestämmer med hjälp av dessa och eventuellt data från andra källor hur meddelandet ska dirigeras. I de flesta enkla fall överväger utbyte ett nyckelfält, som vi kallar Routing Key . Routing Key är en virtuell adress som Exchange-servern kan använda för att bestämma om ett meddelande ska skickas. För punkt-till-punkt routing är routingnyckeln vanligtvis namnet på meddelandekön. För pub-sub routing är routingnyckeln vanligtvis värdet av ämneshierarkin (ämne - se publikation/subscruber). I mer komplexa fall kan routingnyckeln kombineras med routing av meddelandehuvudfält och/eller meddelandeinnehåll.
När en klientapplikation skapar en meddelandekö kan den ange följande egenskaper:
Ett AMQP-meddelande består av en uppsättning egenskaper och icke-offentligt innehåll. Ett nytt meddelande skapas av producenten med hjälp av AMQP klient-API. Producenten lägger till innehåll i meddelandet och ställer eventuellt in några meddelandeegenskaper. Producenten markerar meddelandet med routinginformation som ser ut som en adress, men kan vara vad som helst. Producenten skickar sedan meddelandet till utbyte . När ett meddelande kommer till servern dirigerar exchange (vanligtvis) det till en uppsättning köer som också finns på servern. Om meddelandet inte är routbart kan Exchange släppa det eller returnera det till applikationen. Producenten bestämmer hur man ska hantera meddelanden som inte kan dirigeras.
Ett meddelande kan finnas i många meddelandeköer. Servern kan hantera detta på olika sätt, som att kopiera meddelandet med referensräkning etc. Detta påverkar inte interoperabiliteten. Men när ett meddelande dirigeras till flera meddelandeköer är det identiskt i varje meddelandekö. Det finns ingen unik identifierare här för att skilja mellan olika kopior.
När ett meddelande kommer till meddelandekön försöker det omedelbart leverera det till konsumenten via AMQP. Om detta inte är möjligt lagras meddelandet i meddelandekön (i minnet eller på disk på begäran av producenten ) och väntar på att konsumenten ska vara redo. Om det inte finns någon konsument kan kön skicka ett meddelande till producenten via AMQP (igen, om producenten bett om det).
När meddelandekön kan leverera ett meddelande till konsumenten tar den bort meddelandet från dess interna lagring. Detta kan ske omedelbart eller efter att konsumenten erkänner att han har slutfört sitt jobb framgångsrikt, behandlat meddelandet. Konsumenten väljer själv hur och när meddelanden "kvitteras". konsumenten kan också avvisa meddelandet (negativ bekräftelse).
Producentmeddelanden och konsumentbekräftelser grupperas i transaktioner. När en applikation spelar båda rollerna, vilket ofta är fallet, gör den ett blandat jobb med att skicka meddelanden och skicka bekräftelser, och sedan begå eller återställa transaktionen.
Leveransen av meddelanden från servern till konsumenten är icke-transaktionell.
Producer är en klientapplikation som publicerar meddelanden för utbyte .
I analogi med e-postenheten kan man se att producenten inte skickar meddelanden direkt till kön (meddelandekö). Alla andra beteenden skulle bryta abstraktionen i AMQ-modellen. Detta skulle likna livscykeln för ett e-postmeddelande: lösa e-postmeddelandet, kringgå MTA:s routingtabeller och slå direkt i brevlådan. Detta skulle göra det omöjligt att infoga mellanliggande filtrering och bearbetning som skräppostdetektering.
AMQ-modellen använder samma princip som e-postsystemet: alla meddelanden skickas till en enda växel eller MTA , som inspekterar meddelanden baserat på regler och information som är gömd för avsändaren, och dirigerar dem till distributionspunkter som också är dolda från avsändare. (och dirigerar dem till utlämningsställen som också är dolda för avsändaren - här är distributionsställen utlämningsställen från dokumentationen).
Konsument är klientapplikationen som tar emot meddelanden från meddelandekön.
Vår e-postanalogi börjar gå sönder när vi tittar på konsumenten (mottagarna). E-postklienter är passiva - de kan läsa brevlådor, men de har ingen effekt på hur dessa brevlådor fylls i. Med AMQP kan konsumenten också vara passiv, precis som e-postklienter. Det vill säga att vi kan skriva en applikation som lyssnar på en specifik meddelandekö och helt enkelt bearbetar den inkommande informationen. I det här fallet måste meddelandekön vara klar innan applikationen startar och måste vara "bifogad" till den.
Konsumenten har också följande egenskaper:
Det är som att ha ett e-postsystem som på protokollnivå kan:
De flesta integrationsarkitekturer behöver inte denna nivå av komplexitet. De flesta AMQP-användare behöver grundläggande funktionalitet direkt. AMQP tillhandahåller detta på följande sätt:
Som ett resultat tillåter den underliggande bindningen producenten att skicka meddelanden direkt till meddelandekön, och på så sätt emulera det enklaste schemat för att skicka ett meddelande till en mottagare som folk skulle förvänta sig av en traditionell mellanprogramvara.
Basbindningen hindrar inte användningen av meddelandekön i mer komplexa konstruktioner. Det låter dig använda AMQP utan en specifik förståelse av bindnings- och utbytesmekanismerna.
Avsnittet beskriver processen för interaktion mellan applikationen och servern
Middleware är komplext, och när de utformade protokollstrukturen försökte dess skapare tämja denna komplexitet. Deras tillvägagångssätt var att modellera ett traditionellt API baserat på klasser som innehåller metoder, där varje metod gör exakt en sak och gör det bra. Detta resulterar i en stor uppsättning kommandon, men en som är relativt lätt att förstå.
AMQP-kommandon är grupperade i klasser. Varje klass täcker ett specifikt funktionsområde. Vissa klasser är valfria - varje peer implementerar de klasser som den måste stödja.
Det finns två olika dialogmetoder:
För att förenkla metodbearbetningen definierar vi separata svar för varje synkron begäran. Det vill säga att en metod inte används för att svara på två olika förfrågningar. Detta innebär att en peer, när den skickar en synkron förfrågan, kan acceptera och behandla inkommande metoder tills ett av de giltiga synkrona svaren tas emot. Detta skiljer AMQP från mer traditionella RPC-protokoll.
En metod definieras formellt som en synkron begäran, synkront svar (på en specifik begäran) eller asynkront. Slutligen definieras varje metod formellt som klientsida (d.v.s. server-klient) eller serversida (klient-server).
AMQP är designat för att vara jämförbart med API:et för mellanprogram. Matchningsprocessen är något intellektuell, d.v.s. förstår att inte alla metoder och inte alla argument är vettiga för applikationen, men det är också mekaniskt, d.v.s. genom att sätta vissa regler kan alla metoder matchas utan manuellt ingripande.
Fördelarna med detta är att genom att lära sig semantiken i AMQP, kommer utvecklare att hitta samma semantik som tillhandahålls i vilket ramverk de än använder.
Ett exempel på metoden Queue.Declare:
Kö . deklarera kö = min . kö auto - radera = TRUE exklusiv = FALSKDen kan konverteras till en nätverksram:
+--------+--------+-----------+------------+------- ----+ | Kö | förklara | min . kö | 1 | 0 | +--------+--------+-----------+------------+------- ----+ klass metodnamn auto - radera exklusiv _Eller i en API-metod på hög nivå
Kö . Deklarera ( "my.queue" , TRUE , FALSE );Asynkron metodmatchningslogik i pseudokod:
skicka metod till servernSynkron metodmatchningslogik i pseudokod:
skicka begäran till servern _ upprepa vänta på svar från servern om respons är en asynkron metod processmetod ( vanligtvis , levererat eller returnerat innehåll ) _ annan hävda att metoden är ett giltigt svar på begäran avsluta upprepa slut - om avsluta - upprepaDet är värt att notera att för de flesta applikationer kan mellanprogram vara helt dold i de tekniska lagren i systemet, och att själva API:et som används är mindre viktigt än att mellanvaran är robust och funktionell.
Det chattiga protokollet är långsamt. Vi använder aktivt asynkron i de fall det finns ett prestandaproblem. Det är vanligtvis där vi skickar innehåll från en peer till en annan. Vi skickar metoder så snabbt som möjligt utan att vänta på bekräftelser. Vid behov implementerar vi fönster och strypning på en högre nivå, till exempel konsumentnivå.
Protokollet avstår från meddelanden, eftersom implementerar en påståendemodell för alla händelser. Antingen lyckas det eller så kastas ett undantag? som stänger en kanal eller anslutning.
Det finns inga aviseringar i AMQP. En lyckad händelse - tyst, ett misslyckande - förklarar sig själv. När en applikation behöver explicit spårning av framgångar och misslyckanden bör den använda transaktioner.
Anslutningen är designad för att vara hållbar och hantera många kanaler.
Anslutningens livscykelInformation utbyts inte mot fel av ofullständigt öppnade anslutningar. Värden som stötte på felet bör stänga uttaget utan ytterligare meddelande.
AMQP är ett flerkanalsprotokoll. Kanaler ger möjlighet att multiplexa en tung TCP/IP-anslutning till flera lätta anslutningar. Detta gör protokollet mer "brandväggsvänligt" eftersom portanvändningen är förutsägbar. Det betyder också att trafikformning och andra QoS-funktioner för nätverk enkelt kan användas.
Kanaler är oberoende av varandra och kan utföra olika funktioner samtidigt med andra kanaler, medan den tillgängliga bandbredden är uppdelad på samtidiga uppgifter.
Det förväntas och uppmuntras att flertrådiga klientapplikationer ofta använder "kanal-per-tråd"-modellen för att underlätta utvecklingen. Men att öppna flera anslutningar till en eller flera AMQP-servrar från en enda klient är också helt acceptabelt. Livscykeln för en kanal är som följer:
Tillåter en app att hantera utbytesinstanser på servern. Denna klass tillåter ett program att skriva sitt eget meddelandehanteringsskript utan att förlita sig på någon konfiguration.
Obs: De flesta applikationer behöver inte denna komplexitetsnivå, och äldre mellanprogram kommer sannolikt inte att stödja denna semantik.
Exchange livscykelKöklassen tillåter en applikation att hantera meddelandeköer på en server. Detta är ett grundläggande steg i nästan alla applikationer som tar emot meddelanden, åtminstone för att verifiera att den förväntade meddelandekön faktiskt existerar.
Protokollet tillhandahåller två kölivscykler:
AMQP implementerar ämnesprenumerationsmekanismen i form av meddelandeköer. Detta möjliggör intressanta strukturer där ett abonnemang kan lastbalanseras över en pool av samarbetande abonnentapplikationer.
PrenumerationslivscykelBasklassen implementerar meddelandefunktionerna som beskrivs i denna specifikation. Den stöder följande semantik:
AMQP stöder två typer av transaktioner:
Klassen Transaction (“tx”) ger applikationer tillgång till den andra typen av transaktioner, lokala servertransaktioner. Klassens semantik är som följer:
Transaktioner handlar om innehållspublicering och bekräftelser, inte leverans. Därför återställer inte återställningen och utlöser återleverans. Kunden kan kvittera dessa meddelanden i nästa transaktion.
Det här avsnittet förklarar hur kommandon mappas till protokollet på trådnivå .
AMQP är ett binärt protokoll. Informationen är organiserad i ramar av olika slag. Ramar innehåller protokollmetoder och annan information. Alla ramar har samma generella format: ramhuvud, nyttolast och bildslut. Ramens nyttolastformat beror på ramtypen.
På transportnivån antas användningen av TCP / IP-stacken eller analoger.
Inom en enda uttagsanslutning kan det finnas flera oberoende kontrollflöden, så kallade kanaler. Varje bildruta är numrerad med ett kanalnummer. Genom att interfoliera sina ramar delar de olika kanalerna denna koppling. För varje given kanal exekveras ramar i en strikt sekvens som kan användas för att driva en protokollanalysator (vanligtvis en tillståndsmaskin).
Vi bygger ramar med en liten uppsättning datatyper som bitar, heltal, strängar och fälttabeller. Ramfält är tätt packade utan att göra dem långsamma eller svåra att analysera. Det är relativt enkelt att skapa ett ramlager mekaniskt från protokollspecifikationer.
Trådnivåformatering är designad för att vara skalbar och mångsidig nog att användas i godtyckliga högnivåprotokoll (inte bara AMQP). Vi räknar med att AMQP kommer att expandera, förbättra och på annat sätt förändras över tiden, och trådnivåformatet kommer att stödja detta.
AMQP-datatyper som används i ramar:
Klienten och servern förhandlar fram ett protokoll. Detta innebär att när en klient ansluter erbjuder servern vissa alternativ som klienten kan acceptera eller ändra. När båda är överens om resultatet anses kopplingen upprättad. Förhandling är användbart eftersom det låter dig ställa in anslutningsförinställningar.
Samordning sker på ett antal aspekter:
Överenskomna gränser kan tillåta båda parter att i förväg tilldela nyckelbuffertar, vilket undviker dödläge. Varje inkommande ram följer antingen de förhandlade gränserna och är därför säker, eller överskrider dem, i vilket fall den andra sidan har misslyckats och måste inaktiveras. Detta stämmer mycket väl överens med AMQP:s filosofi om "det fungerar antingen som det ska eller så fungerar det inte alls".
Båda noderna förhandlar gränser till det lägsta överenskomna värdet enligt följande:
TCP/IP-stack - fungerar med strömmar, den har ingen inbyggd ramavgränsningsmekanism. Befintliga protokoll löser detta problem på flera olika sätt:
Alla ramar består av en rubrik (7 oktetter), en godtycklig nyttolast och en "end of frame"-oktett som upptäcker felaktiga ramar:
0 1 3 7 storlek + 7 storlek + 8 +------+--------+-------------+ +-----------+ +--- --------+ | typ | kanal | storlek | | nyttolast | | ram - slut | +------+--------+-------------+ +-----------+ +--- --------+ oktett kort lång storlek oktetter oktettRamen läses så här:
I realistiska implementeringar när det gäller prestanda kommer vi att använda "read-ahead buffering" eller "gathering reads" för att undvika att göra tre separata systemanrop för att läsa en ram.
Metodramar bär protokollkommandon på hög nivå (som vi kallar "metoder"). En metodram innehåller en instruktion. Metodens nyttolast har följande format:
0 2 4 +----------+------------+-------------- - - | klass - id | metod - id | argument ... +----------+------------+-------------- - - kort kort ...Metodramen hanteras så här:
1. Läsa nyttolastmetodens ram.
2. Dess uppackning i en struktur. Denna metod har alltid samma struktur, så du kan snabbt packa upp den
3. Kontrollera att denna metod är tillåten i det aktuella sammanhanget.
4. Kontrollera att metodargumenten är giltiga.
5. Utförande av denna metod.
Metodens ramkropp är konstruerad som en lista med AMQP-datafält (bitar, heltal, strängar och strängtabeller). Rangeringskoden genereras trivialt direkt från protokollspecifikationer och kan vara mycket snabb.
Innehåll är applikationsdata som vi överför från klient till klient via AMQP-servern. Innehållet är, grovt sett, en uppsättning egenskaper plus en binär del av datan. Uppsättningen av tillåtna egenskaper definieras av basklassen, och de bildar "innehållsrubrikramen". Data kan vara av vilken storlek som helst och delas upp i flera (eller många) block, som vart och ett bildar ett "innehållskroppsskelett".
Om vi tittar på ramarna för en viss kanal när den sänds över tråden, kan vi se något i stil med detta:
[ metod ] [ metod ] [ header ] [ body ] [ body [ metod ] ...Vissa metoder (som Basic.Publish , Basic.Deliver , etc.) definieras formellt som innehållsbärande. När en peer skickar en sådan metodram, följer den alltid den med en innehållsrubrik och med eller utan några innehållskroppsramar. Innehållsramhuvudet har följande format:
0 2 4 12 14 +----------+--------+-----------+----------------+ ------------- - - | klass - id | vikt | kroppsstorlek | _ egendomsflaggor | _ fastighetslista ... _ +----------+--------+-----------+----------------+ ------------- - - kort kort lång lång kort återstod ...Vi placerar innehållskroppen i separata ramar (snarare än att inkludera den i en metod) så att AMQP kan stödja "nollkopiering"-metoder där innehållet aldrig raderas eller kodas. Vi lägger innehållsegenskaper i sin egen ram så att mottagarna selektivt kan kassera innehåll de inte vill bearbeta.
Heartbeat är en teknik designad för att åsidosätta en av funktionerna i TCP/IP, nämligen dess förmåga att återhämta sig från en bruten fysisk anslutning, först efter en ganska lång timeout. I vissa scenarier behöver vi veta mycket snabbt om peeren är nere eller inte svarar av andra anledningar (till exempel fastnar den i en loop). Eftersom hjärtslag kan göras på en låg nivå kommer vi att implementera detta som en speciell typ av ram som byts ut mellan noder i transportlagret, snarare än som en klassmetod.
AMQP använder undantag för felhantering. Alla operativa fel (meddelandekö hittades inte, otillräckliga åtkomsträttigheter, etc.) kommer att utlösa ett kanalundantag. Alla strukturella fel (dåligt argument, dålig metodsekvens, etc.) resulterar i ett anslutningsundantag. Undantaget stänger kanalen eller anslutningen och returnerar en svarskod och svarskropp till klientapplikationen. Vi använder en 3-siffrig svarskod plus svarstexttextschemat som används i HTTP och många andra protokoll.
Anslutningen eller kanalen sägs vara "öppen" för klienten när den skickar ett Open, och för servern när den skickar ett Open-Ok. Från och med nu måste en peer som vill stänga en kanal eller anslutning göra det med hjälp av handskakningsprotokollet, som beskrivs här.
Att stänga en kanal eller anslutning av någon anledning - normal eller exceptionell - måste göras försiktigt. Plötsliga stängningar upptäcks inte alltid snabbt, och efter ett undantag kan vi förlora felsvarskoder. Den korrekta designen är att manuellt förhandla om stängningen så att kanalen/anslutningen stängs först efter att vi är säkra på att den andra sidan är medveten om situationen.
När en peer bestämmer sig för att stänga en kanal eller anslutning skickar den stängningsmetoden. Den mottagande noden måste svara på stängningen med ett Close-Ok, och sedan kan båda sidor stänga sin kanal eller anslutning. Observera att om peers ignorerar Close, kan ett dödläge uppstå om båda peers skickar Close samtidigt.
Det är möjligt att läsa och skriva AMQP-ramar direkt från applikationen, men det skulle vara dålig design. Även den enklaste AMQP-konversationen är mycket mer komplex än till exempel HTTP, och applikationsutvecklare behöver inte förstå saker som binära ramformat för att skicka ett meddelande till en meddelandekö. Den rekommenderade AMQP-klientarkitekturen består av flera abstraktionsnivåer:
Dessutom finns det vanligtvis någon nivå av I/O, som kan vara mycket enkel (Synchronous socket read and write) eller komplex (helt asynkron flertrådad I/O). Detta diagram visar den allmänna rekommenderade arkitekturen:
+------------------------+ | ansökan | +-----------+-------------+ | +------------------------+ +---| API -lager |---- Klient- API -lager -----+ | +-----------+------------+ | | | | | +------------------------------+ +----------------+ | | | Anslutningshanterare + ----+ Framing Layer | | | +-----------+------------+ +-------+ | | | | | +------------------------------+ | +---| Asynkront I / O -lager |------------------------+ +-----------+-------------+ | ------- - - - - Nätverk - - - - -------När vi i det här dokumentet talar om "klient-API" menar vi alla lager under applikationen (i/o, framing, anslutningshanterare och API-lager. Vi brukar tala om "klient-API" och "applikation" som två separata saker där applikationen använder klient-API:et för att prata med mellanprogramservern.
Ett meddelande är den atomära bearbetningsenheten i ett routing- och middleware-kösystem. Meddelanden innehåller innehåll som består av en innehållsrubrik som innehåller en uppsättning egenskaper och en innehållskropp som innehåller ett ogenomskinligt block med binär data.
Ett meddelande kan motsvara många olika applikationsenheter:
Meddelanden kan vara permanenta. Ett beständigt meddelande lagras säkert på disken och levereras garanterat även vid ett större nätverksavbrott, serverfel, spill osv.
Meddelanden kan ha företräde. Ett meddelande med hög prioritet skickas före meddelanden med lägre prioritet som väntar i samma meddelandekö. När meddelanden behöver släppas för att bibehålla en viss servicekvalitet, kommer servern först att släppa meddelanden med låg prioritet.
Servern FÅR INTE ändra innehållet i meddelanden som den tar emot och skickar till konsumentapplikationer. Servern KAN lägga till information till innehållsrubriker, men den FÅR INTE ta bort eller ändra befintlig information.
Virtuella värdarEn virtuell värd är en del av data på en server, en administrativ bekvämlighet som kommer att visa sig användbar för dem som vill tillhandahålla AMQP som en tjänst på en delad infrastruktur.
Den virtuella värden innehåller sitt eget namnområde, uppsättning utbyten, meddelandeköer och alla relaterade objekt. Varje anslutning måste vara associerad med en virtuell värd.
Klienten väljer den virtuella värden i metoden Connection.Open efter autentisering. Detta innebär att serverns autentiseringsschema är gemensamt för alla virtuella noder på den servern. Det auktoriseringsschema som används kan dock vara unikt för varje virtuell värd. Detta bör vara användbart för en delad värdinfrastruktur. Administratörer som kräver olika autentiseringsscheman för varje virtuell värd måste använda separata servrar
Alla kanaler inom en anslutning fungerar med samma virtuella värd. Det finns inget sätt att kontakta en annan virtuell värd på samma anslutning, och det finns inget sätt att byta till en annan virtuell värd utan att tappa anslutningen och börja om.
Protokollet erbjuder inga mekanismer för att skapa eller konfigurera virtuella värdar - detta görs på ett ospecificerat sätt inom servern och är helt implementeringsberoende.
UtbytenExchange är en meddelandedirigeringsagent inuti en virtuell värd. Exchange-instansen (som vi vanligtvis refererar till som en "exchange") tar emot meddelanden och routinginformation - främst routingnyckeln - och skickar antingen meddelandena till meddelandeköer eller till interna tjänster. Utbytena namnges på en per virtuell värdbasis.
Applikationer är fria att skapa, dela och förstöra utbytesinstanser inom deras behörighet.
Utbyten kan vara permanenta, tillfälliga eller automatiskt raderade. Permanenta utbyten finns tills de tas bort. Tillfälliga utbyten existerar tills servern stängs av. Automatiskt borttagna utbyten finns tills de inte längre används.
Servern tillhandahåller en specifik uppsättning utbytestyper. Varje utbytestyp implementerar en specifik mappning och algoritm, som definieras i nästa avsnitt. AMQP föreskriver ett litet antal bytestyper och rekommenderar några fler. Dessutom kan varje serverimplementering lägga till sina egna utbytestyper.
En växel kan dirigera ett enda meddelande till flera meddelandeköer parallellt. Detta skapar flera meddelandeinstanser som konsumeras oberoende av varandra.
Direktbytestypendirektbytestyp fungerar så här:
Servern MÅSTE implementera en direkt echange och MÅSTE fördefiniera i varje virtuell värd minst två direkta växlar: en som heter amqp.direct och en utan ett publikt namn som fungerar som standardväxel för att hantera offentliga metoder.
Observera att meddelandeköer kan kontaktas med vilket giltigt routingnyckelvärde som helst, men oftast kommer meddelandeköer att kontaktas med sitt eget namn som routingnyckel.
I synnerhet SKA alla meddelandeköer automatiskt bindas till en växel utan ett offentligt namn, med användning av meddelandekönamnet som routingnyckel.
Fanout Exchange TypeFanout Exchange fungerar så här:
Fanout Exchange är trivialt att designa och implementera. Denna typ av utbyte, och det fördeklarerade namnet amq.fanout , krävs.
ÄmnesbytestypenÄmnesutbyte fungerar så här:
Routingnyckeln som används för ämnesutbyte måste bestå av ord separerade med punkter. Minsta ordstorlek är 0 tecken. Varje ord kan innehålla bokstäverna AZ och az, samt siffrorna 0-9.
Routningsmönstret följer samma regler som routingnyckeln, med tillägget att * matchar ett ord och # matchar noll eller fler ord. Således matchar routningsschemat *.stock.# routingnycklarna usd.stock och eur.stock.db, men inte stock.nasdaq.
Ett föreslaget schema för Topic Exchange är att behålla en uppsättning av alla kända routingnycklar och uppdatera den när utgivare använder nya routingnycklar. Du kan definiera alla bindningar för en given routingnyckel och på så sätt snabbt hitta meddelandeköerna för ett meddelande. Denna typ av utbyte är valfritt.
Servern måste implementera ämnesutbytestypen, i vilket fall servern först måste deklarera minst ett ämnesutbyte med namnet amq.topic i varje virtuell värd.
Typen Headers Exchangeheader exchange-typ fungerar så här:
Matchningsalgoritmen styrs av ett speciellt bindningsargument som skickas som ett namn-värdepar i argumenttabellen. Detta argument kallas "X-match". Det kan ta ett av två värden, som dikterar hur andra namnvärdespar i tabellen hanteras under matchning:
Ett fält i bindningsargumenten matchar ett fält i meddelandet om följande villkor är sant: antingen har fältet i bindningsargumenten inget värde och fältet med samma namn finns i meddelandehuvuden, eller om fältet i bindningen argument har ett värde och fältet med samma namn finns i rubrikmeddelandena och har samma betydelse.
Alla fält som börjar med 'x -' förutom 'X-match' är reserverade för framtida användning och kommer att ignoreras
Servern MÅSTE implementera Headers Exchange Type, och servern MÅSTE fördeklarera minst en Headers Exchange Type som heter amq.match i varje virtuell värd.
SystemutbytestypenSystemutbytestypen fungerar så här:
Systemtjänster som börjar med "amq." reserverad för AMQP. Alla andra namn kan användas. Denna typ av utbyte är valfritt.
Anpassade utbytestyperAlla anpassade utbytestypnamn måste börja med "x -". Utbytestyper som inte börjar med "x -" är reserverade för framtida användning i AMQP-standarden.
MeddelandeköerEn meddelandekö är en namngiven FIFO som innehåller meddelanden från applikationer. Applikationer är fria att skapa, dela, använda och förstöra meddelandeköer inom deras behörighet.
Observera att när det finns flera läsare från en kö, eller klienttransaktioner, eller använder prioritetsfält, eller använder meddelandeväljare, eller implementeringsspecifik leveransoptimering, kanske kön inte har riktiga FIFO-egenskaper. Det enda sättet att garantera FIFO är att bara ha en konsument ansluten till kön. I dessa fall kan kön beskrivas som "svag-FIFO".
Meddelandeköer kan vara permanenta, tillfälliga eller automatiskt raderade. Beständiga meddelandeköer finns tills de tas bort. Tillfälliga meddelandeköer finns tills servern stängs av. Autodelete-köer varar tills de inte längre används.
Meddelandeköer lagrar sina meddelanden i minnet, på disken eller någon kombination av de två. Meddelandeköer namnges baserat på den virtuella värden.
Meddelandeköer innehåller meddelanden och distribuerar dem till en eller flera konsumentkunder. Ett meddelande som skickas till en meddelandekö skickas aldrig till mer än en klient om det inte har avvisats
En meddelandekö kan innehålla olika typer av innehåll samtidigt och oberoende. Det vill säga, om huvudinnehållet och filinnehållet skickas till samma meddelandekö, kommer de att levereras till konsumerande applikationer oberoende på begäran.
BindningarBindning är kopplingen mellan meddelandekö och datautbyte. Bindningen definierar routingargumenten som talar om för växeln vilka meddelanden kön ska ta emot. Applikationer skapar och förstör bindningar efter behov för att styra flödet av meddelanden till deras meddelandeköer. Livslängden för en bindning beror på de meddelandeköer som de är definierade för - när en meddelandekö förstörs förstörs även dess bindning. Den specifika semantiken för Queue.Bind-metoden beror på utbytestypen.
Konsumenter - konsumenterVi använder termen konsument för att hänvisa till både klientapplikationen och den enhet som kontrollerar hur en viss klientapplikation tar emot meddelanden från meddelandekön. När en klient "startar en konsument" skapar den en konsumentenhet på servern. När en klient "avbryter en konsument" förstör den konsumentenheten på servern. Konsumenter tillhör samma klientkanal och tvingar meddelandekön att skicka meddelanden till klienten asynkront.
ServicekvalitetKvaliteten på tjänsten avgör hastigheten med vilken meddelanden skickas. Kvaliteten på tjänsten beror på vilken typ av innehåll som distribueras. I allmänhet använder QoS konceptet "förhämtning" för att indikera hur många meddelanden eller hur många oktetter av data som kommer att skickas innan klienten bekräftar meddelandet. Målet är att skicka meddelandedata i förväg för att minska latensen.
AcknowledgementsEn bekräftelse är en formell signal från en klientapplikation till meddelandekön att den framgångsrikt har bearbetat ett meddelande. Det finns två möjliga valideringsmodeller:
Klientlager kan själva implementera explicita bekräftelser på olika sätt, till exempel direkt efter att ha tagit emot ett meddelande eller när en applikation indikerar att den har behandlat det. Dessa skillnader påverkar inte AMQP eller interoperabilitet.
flödeskontrollFlödeskontroll är en nödprocedur som används för att stoppa flödet av meddelanden från en peer. Det fungerar på samma sätt mellan klient och server och implementeras av kommandot Channel.Flow. Flödeskontroll är den enda mekanismen som kan stoppa en överproduktiv utgivare. En konsument kan använda en mer elegant mekanism för förhämtning av fönster om den använder bekräftelser (vilket vanligtvis innebär att använda transaktioner).
NamnkonventionDessa konventioner reglerar namngivningen av AMQP-enheter. Servern och klienten måste respektera dessa konventioner:
AMQP-metoder kan definiera minimivärden (som antalet konsumenter i en meddelandekö) av kompatibilitetsskäl. Dessa minimivärden definieras i beskrivningen av varje klass.
Överensstämmande AMQP-implementeringar bör implementera ganska generösa värden för sådana fält, minimivärdena är endast avsedda att användas på de minst kapabla plattformarna.
Grammatik använder denna notation:
Vi definierar metoder som:
Standard AMQP-portnumret har tilldelats av IANA som 5672 för både TCP och UDP. UDP-port reserverad för användning i framtida multicast-implementationer
Vi tillhandahåller en komplett grammatik för AMQP (detta tillhandahålls som referens, och du kanske är mer intresserad av att följa avsnitten som beskriver de olika typerna av ramar och deras format):
amqp = protokoll - header * amqp - enhet protokoll - header = bokstavlig - AMQP- protokoll - id - protokoll - version literal - AMQP = % d65 .77.81.80 ; "AMQP" protokoll - id = % d0 ; Måste vara 0 protokoll - version = % d0.9.1 ; _ 0-9-1 metod = metod - ram [ innehåll ] metod - ram = % d1 ram - egenskaper metod - nyttolast ram - slut ram - egenskaper = kanal nyttolast - storlek kanal = kort - uint ; icke - noll nyttolast - storlek = lång - uint metod - nyttolast = klass - id metod - id * amqp - fält class - id = % x00 .01 - % xFF . FF metod - id = % x00 .01 - % xFF . FF amqp - fält = BIT / OCTET / kort - uint / lång - uint / lång - lång - uint / kort - sträng / lång - sträng / tidsstämpel / fält - tabell kort - uint = 2 * OCTET lång - uint = 4 * OCTET lång - lång - uint = 8 * OCTET kort - sträng = OCTET * sträng - char ; längd + innehåll sträng - char = % x01 .. % xFF lång - sträng = lång - uint * OCTET ; längd + innehåll timestamp = long - long - uint ; 64 - bitars POSIX fält - tabell = lång - uint * fält - värde - par fält - värde - par = fält - namnfält - värde _ fält - namn = kort - sträng fält - värde = 't' booleskt / 'b' kort - kort - int / 'B' kort - kort - uint / 'U' kort - int / 'u' kort - uint / 'I' long - int / 'jag' lång - uint / 'L' lång - lång - int / 'l' long - long - uint / 'f' flyta / 'd' dubbelt / 'D' decimal - värde / 's' kort - sträng / 'S' lång - sträng / 'A' fält - array / 'T' tidsstämpel / 'F'- fält - tabell / 'V' ; inget fält boolean = OCTET ; 0 = FALSK , annars SANT kort - kort - int = OCTET kort - kort - uint = OCTET kort - int = 2 * OCTET lång - int = 4 * OCTET lång - lång - int = 8 * OCTET flyta = 4 * OCTET ; IEEE -754 dubbel = 8 * OCTET ; rfc1832 XDR dubbel decimal - värde = skala lång - uint skala = OCTET ; antal decimalsiffror _ _ fält - array = long - int * fält - värde ; rad värden _ ram - slut = % xCE innehåll = % d2 innehåll - rubrik * innehåll - brödtext innehåll - rubrik = ram - egenskaper header - nyttolast ram - slut header - nyttolast = innehåll - klassinnehåll - viktinnehåll - kropp - storlek _ _ egenskap - flaggar egenskap - lista innehåll - klass = oktett innehåll - vikt = % x00 innehåll - kropp - storlek = lång - lång - uint egenskap - flaggor = 15 * BIT % b0 / 15 * BIT % b1 egenskap - flaggor egenskap - lista = * amqp - fält innehåll - kropp = % d3 ram - egenskaper kropp - nyttolast ram - slut kropp - nyttolast = * OCTET hjärtslag = % d8 % d0 % d0 frame - end
Vi använder den utökade BNF-syntaxen som definieras i IETF RFC 2234. Sammanfattningsvis:
Klienten måste starta en ny anslutning genom att skicka protokollhuvudet. Detta är en 8 oktettsekvens:
+---+---+---+---+----+---+---+---+ | 'A' | 'M' | 'Q' | 'P' | 0 | 0 | 9 | 1 | +---+---+---+---+----+---+---+---+ 8 oktetterProtokollhuvudet består av de stora bokstäverna "AMQP" följt av konstanten %d0 följt av:
Protokollförhandlingsmodellen är kompatibel med befintliga protokoll som HTTP, som initierar en anslutning med en konstant textsträng, och med brandväggar, som tittar på början av ett protokoll för att avgöra vilka regler som ska gälla för det.
Klienten och servern förhandlar om protokollet och versionen enligt följande:
Exempel:
Klienten skickar : Servern svarar : AMQP % d0 .0.9.1 Anslutning . startmetoden _ AMQP % d0 .1.0.0 AMQP % d0 .0.9.1 < Stäng anslutning > HTTP AMQP % d0.0.9.1 < Stäng anslutning > _Principer för implementering av protokollet:
Alla ramar börjar med en 7-oktettshuvud som består av ett typfält (oktett), ett kanalfält (kort heltal) och ett längdfält (långt heltal):
0 1 3 7 storlek + 7 storlek + 8 +------+---------+--------+ +---------+ +------ -----+ | typ | kanal | storlek | | nyttolast | | ram - slut | +------+---------+--------+ +---------+ +------ -----+ oktett kort lång ' storlek ' oktetter oktettAMQP definierar följande ramtyper:
Kanalnumret är 0 för alla ramar som är globala för anslutningen och 1-65535 för ramar som refererar till specifika kanaler.
Storleksfältet är storleken på nyttolasten, exklusive end-of-frame-oktetten. Medan AMQP antar ett tillförlitligt anslutet protokoll, använder vi slutet av ramen för att upptäcka inramningsfel orsakade av felaktiga klient- eller serverimplementationer.
Principer för implementering av protokollet:
Metodramkroppar består av en oföränderlig lista av datafält som kallas "argument". Alla metodkroppar börjar med klass- och metodidentifierare:
0 2 4 +----------+------------+-------------- - - | klass - id | metod - id | argument ... +----------+------------+-------------- - - kort kort ...Principer för implementering av protokollet:
AMQP har två nivåer av datafältsspecifikation: inbyggda datafält som används för metodargument och datafält som skickas mellan applikationer i fälttabeller. Fälttabeller innehåller en upphöjd uppsättning av inbyggda datafält.
AMQP definierar följande inbyggda heltalstyper:
Heltal och stränglängder är alltid osignerade och lagras i nätverksbyteordning. Vi försöker inte optimera fallet där två låg-höga system (t.ex. två Intel-processorer) pratar med varandra.
Principer för implementering av protokollet:
AMQP definierar sin egen typ av bitfält. Bitarna ackumuleras till hela oktetter. När två eller flera bitar berörs i en ram, kommer de att packas i en eller flera oktetter, med början med den lägsta biten i varje oktett. Det finns inget krav på att alla bitvärden i en ram ska vara sammanhängande, men detta görs vanligtvis för att minimera ramstorlekar.
SträngarAMQP-strängar har variabel längd och representeras av en heltalslängd följt av noll eller fler datoktetter. AMQP definierar två inbyggda radtyper:
Tidsstämplar lagras i 64-bitars POSIX time_t-format med en precision på en sekund. Genom att använda 64 bitar undviker vi framtida inpackningsproblem associerade med 31-bitars och 32-bitars time_t-värden.
TabellmarginalerTabellfält är långa strängar som innehåller packade namn-värdepar. Namnvärdespar kodas som en kort sträng som anger namnet och en oktett som anger värdetypen, följt av själva värdet. Giltiga fälttyper för tabeller är tillägg av de ursprungliga typerna heltal, bit, sträng och tidsstämpel, och visas i grammatiken. Heltalsfält med flera oktetter lagras alltid i nätverksbyteordning.
Principer för implementering av protokollet:
Vissa specifika metoder (Publicera, Leverera, etc.) bearbetar innehållet. Se kapitlet "Funktionella specifikationer" för specifikationerna för varje metod. Metoder som bearbetar innehåll gör det ovillkorligt.
Innehållet består av en lista med 1 eller flera ramar enligt följande:
Innehållsramar på en viss kanal är strikt sekventiella. Det vill säga, de kan blandas med ramar för andra kanaler, men inga två innehållsramar från samma kanal kan blandas och kan inte "överlappa" varandra, och innehållsramar för samma innehåll kan inte blandas med metodramar på samma kanal ... (orig. Innehållsramar på en specifik kanal är strikt sekventiella. Det vill säga, de kan blandas med ramar för andra kanaler, men inga två innehållsramar från samma kanal får blandas eller överlappas, inte heller får innehållsramar för ett enda innehåll vara blandat med metodramar på samma kanal.)
Observera att alla ramar som inte innehåller innehåll uttryckligen markerar slutet på innehållet. Även om storleken på innehållet är välkänd från innehållsrubriken (och därmed antalet innehållsramar), tillåter detta avsändaren att avbryta innehållet utan att behöva stänga kanalen.
Principer för implementering av protokollet:
Innehållets nyttolasthuvud har följande format:
0 2 4 12 14 +----------+--------+-----------+----------------+ ------------- - - | klass - id | vikt | kroppsstorlek | _ egendomsflaggor | _ fastighetslista ... _ +----------+--------+-----------+----------------+ ------------- - - kort kort lång lång kort återstod ...Principer för implementering av protokollet:
Innehållskroppens nyttolast är ett "ogenomskinligt" binärt block som slutar med en ramslutoktett:
+----------------------------+ +-----------+ | Ogenomskinlig binär nyttolast | | ram - slut | +----------------------------+ +-----------+Innehållskroppen kan delas upp i så många ramar som behövs. Den maximala ramnyttolasten förhandlas fram av båda peers under anslutningsförhandling.
Principer för implementering av protokollet:
Hjärtslagsramar berättar för mottagaren att avsändaren fortfarande lever. Frekvensen och timingen för Heartbeat-ramar förhandlas under anslutningsinstallationen.
Principer för implementering av protokollet:
AMQP tillåter kamrater att skapa flera oberoende kontrollflöden. Varje kanal fungerar som en virtuell anslutning som delar ett uttag:
ramar ramar ramar ramar +-----------+------------+------------+------------+ | kanal | kanal | kanal | kanal | +-----------+------------+------------+------------+ | uttag | +------------------------------------------------ ----+Principer för implementering av protokollet:
Servern måste säkerställa att klientens observationer av serverns tillstånd är konsekventa.
Följande exempel visar vad klientobservation betyder i detta sammanhang:
Synlighetsgarantin säkerställer att klient 2 ser kön
Servern kommer att betrakta kanalen som stängd om något av följande inträffar:
När servern stänger en kanal markeras alla obekräftade meddelanden på kanalen för återleverans. När servern stänger en anslutning tar den bort alla automatiskt borttagna enheter som hör till den anslutningen.
I vissa fall påverkar synkrona förfrågningssvarsmetoder asynkron leverans av innehåll över samma kanal, inklusive:
Principer för implementering av protokollet:
Ordningen i vilken metoder passerar genom en kanal är stabil: metoder tas emot i samma ordning som de skickas. I transportskiktet tillhandahålls detta av TCP/IP-protokollet. Dessutom bearbetas innehållet stabilt av servern. Framför allt kommer innehåll som följer samma sökväg inom servern att förbli beställt. För innehåll med en given prioritet som passerar genom en enda väg, definierar vi innehållsbehandlingsvägen som bestående av en inkommande kanal, en växel, en kö och en utgående kanal.
Principer för implementering av protokollet:
Genom att använda standardprogrammeringsmodellen "undantag" signalerar AMQP inte framgång, bara misslyckande. AMQP definierar två nivåer av uteslutningar:
Vi dokumenterar formellt påståendena i definitionen av varje klass och metod.
SvarskodsformatAMQP-svarskoder följer definitionen av "svarskodens allvarlighetsgrad och teori" i IETF RFC 2821.