RabbitMQ的 AMQP協(xié)議都是些什么內(nèi)容呢
阿粉之前也講述過(guò)關(guān)于 RabbitMQ 的相關(guān)內(nèi)容,比如他們的配置,以及 RabbitMQ 整合 SpringBoot 使用,而且自己使用過(guò)之后,就會(huì)在自己的簡(jiǎn)歷上面寫(xiě)上自己使用 RabbitMQ 實(shí)現(xiàn)了什么功能,但是這就會(huì)導(dǎo)致,有些面試官就會(huì)問(wèn)一些關(guān)于 RabbitMQ 的一些相關(guān)的問(wèn)題,比如, RabbitMQ 中的交換機(jī)是什么, RabbitMQ 中的路由都有哪些?
反正諸如此類(lèi)的問(wèn)題,都是屬于相對(duì)簡(jiǎn)單的問(wèn)題,但是也不排除會(huì)有一些相對(duì)高級(jí)一點(diǎn)的問(wèn)題,就比如接下來(lái)的關(guān)于 RabbitMQ 的協(xié)議的問(wèn)題。
AMQP 協(xié)議
AMQP(高級(jí)消息隊(duì)列協(xié)議)是一個(gè)網(wǎng)絡(luò)協(xié)議。它支持符合要求的客戶(hù)端應(yīng)用(application)和消息中間件代理(messaging middleware broker)之間進(jìn)行通信。
消息代理(message brokers)從發(fā)布者(publishers)亦稱(chēng)生產(chǎn)者(producers)那兒接收消息,并根據(jù)既定的路由規(guī)則把接收到的消息發(fā)送給處理消息的消費(fèi)者(consumers)。
由于A(yíng)MQP是一個(gè)網(wǎng)絡(luò)協(xié)議,所以這個(gè)過(guò)程中的發(fā)布者,消費(fèi)者,消息代理 可以存在于不同的設(shè)備上。
這就是使用消息隊(duì)列最好的地方,消息的發(fā)布者,也就是生產(chǎn)者和消息費(fèi)可以不在相同的設(shè)備上,但是可以保持通信。
AMQP協(xié)議是一個(gè)二進(jìn)制協(xié)議,擁有一些現(xiàn)代特點(diǎn):多信道、協(xié)商式、異步、安全、跨平臺(tái)、中立、高效。
AMQP通常被劃分為三層:
模型層定義了一套命令(按功能分類(lèi)),客戶(hù)端應(yīng)用可以利用這些命令來(lái)實(shí)現(xiàn)它的業(yè)務(wù)功能。
會(huì)話(huà)層負(fù)責(zé)將命令從客戶(hù)端應(yīng)用傳遞給服務(wù)器,再將服務(wù)器的應(yīng)答傳遞給客戶(hù)端應(yīng)用,會(huì)話(huà)層為這個(gè)傳遞過(guò)程提供可靠性、同步機(jī)制和錯(cuò)誤處理。
傳輸層提供幀處理、信道復(fù)用、錯(cuò)誤檢測(cè)和數(shù)據(jù)表示。
實(shí)現(xiàn)者可以將傳輸層替換成任意傳輸協(xié)議,只要不改變AMQP協(xié)議中與客戶(hù)端應(yīng)用程序相關(guān)的功能。實(shí)現(xiàn)者還可以使用其他高層協(xié)議中的會(huì)話(huà)層。
如果你要是去百度上所有 AMQP 反正各大博主上來(lái)就說(shuō) AMQP 0-9-1 ,但是也不說(shuō) 這個(gè) 0-9-1 到底是什么意思,反正都是書(shū)中找的,直接介紹就完事。
這個(gè)東西,阿粉專(zhuān)門(mén)找了一些書(shū)籍,才了解這個(gè)東西指的是什么。
實(shí)際上 AMQP 后面所攜帶的 0-9-1 指的是他的版本號(hào),主版本號(hào)和次版本號(hào)。我們約定版本由主版本號(hào)后面加小數(shù)點(diǎn)再加上次版本號(hào)組成(比如1-3表示主版本號(hào)為1,次版本號(hào)為3)。
主版本號(hào)保持不變,次版本號(hào)遞增。當(dāng)AMQP工作組提升主版本號(hào)時(shí),次版本號(hào)將被設(shè)置為0。因此,有可能出現(xiàn)這樣的版本序列:1-2,1-3,1-4,2-0,2-1……
旦本協(xié)議發(fā)布之后(主版本號(hào)大于1),應(yīng)盡量防止次版本號(hào)遞增到9。不過(guò)在發(fā)布之前(版本0-x),由于會(huì)對(duì)本協(xié)議進(jìn)行頻繁的修訂,可以不遵守這條約定。
而這也是大家在百度上所有 AMQP 協(xié)議中的 AMQP 0-9-1 的由來(lái)。
AMQP 模型
一個(gè)由關(guān)鍵實(shí)體和語(yǔ)義表示的邏輯框架,遵從AMQP規(guī)范的服務(wù)器必須提供這些實(shí)體和語(yǔ)義。為了實(shí)現(xiàn)本規(guī)范中定義的語(yǔ)義,客戶(hù)端可以發(fā)送命令來(lái)控制AMQP服務(wù)器。
實(shí)際上這個(gè)就是一個(gè)工作過(guò)程的簡(jiǎn)介。
消息的生產(chǎn)者,將消息發(fā)送到交換機(jī),然后交換機(jī)收到消息之后,根據(jù)不同的路由規(guī)則,發(fā)給綁定的隊(duì)列,最后 AMQP 代理會(huì)將消息投遞給訂閱了此隊(duì)列的消費(fèi)者,或者消費(fèi)者按照需求自行獲取。
也就是從 product ->exchange -> queue ->consumer
其實(shí) AMQP 也是一個(gè)可編程的協(xié)議。
可編程協(xié)議是什么?
某種意義上說(shuō)AMQP的實(shí)體和路由規(guī)則是由應(yīng)用本身定義的,而不是由消息代理定義。包括像聲明隊(duì)列和交換機(jī),定義他們之間的綁定,訂閱隊(duì)列等等關(guān)于協(xié)議本身的操作。
這雖然能讓開(kāi)發(fā)人員自由發(fā)揮,但也需要他們注意潛在的定義沖突。當(dāng)然這在實(shí)踐中很少會(huì)發(fā)生,如果發(fā)生,會(huì)以配置錯(cuò)誤(misconfiguration)的形式表現(xiàn)出來(lái)。
應(yīng)用程序(Applications)聲明AMQP實(shí)體,定義需要的路由方案,或者刪除不再需要的AMQP實(shí)體。
至于 RabbitMQ 中的 隊(duì)列,交換機(jī),后還有路由啥的,阿粉就不說(shuō)了,那個(gè)東西自己理解反而比別人說(shuō)的有效。
唯一需要注意的是, 當(dāng)一條消息發(fā)布的時(shí)候,發(fā)布者可能會(huì)指定一些消息屬性message attributes(也叫message meta-data消息元數(shù)據(jù)),其中有一些消息屬性是用于消息中間件處理消息,其余的部分則是用于消息消費(fèi)者對(duì)于消息中間件完全透明。
由于網(wǎng)絡(luò)的不穩(wěn)定性,消息在傳輸過(guò)程中可能出現(xiàn)失敗的情況,鑒于此AMQP 0-9-1提供了一種消息確認(rèn)機(jī)制message acknowledgements: 當(dāng)一條消息傳遞給消費(fèi)者后該消費(fèi)者發(fā)送一條通知notifies給消息中間件來(lái)確認(rèn)消息,無(wú)論是自動(dòng)的還是開(kāi)發(fā)者自己這樣做,當(dāng)消息確認(rèn)機(jī)制使用時(shí),只有當(dāng)消息代理收到通知后才會(huì)將該條或該組消息從消息隊(duì)列中移除。
在一些特定情況下,比如當(dāng)消息不能被路由時(shí),消息可能會(huì)被返回給消息發(fā)布者,或者刪除,或者如果消息代理實(shí)現(xiàn)了某種擴(kuò)展插件,則這些無(wú)法被路由的消息可能會(huì)被放入一個(gè)稱(chēng)之為dead letter queue(死亡標(biāo)記隊(duì)列)的隊(duì)列中,發(fā)布者可以通過(guò)指定一些確定的消息屬性 message attributes來(lái)響應(yīng)出現(xiàn)這種情景時(shí)消息應(yīng)該如何被處理。