您好,登錄后才能下訂單哦!
AMQP協議及RabbitMQ原理是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
AMQP:是具有現代特征的二進制協議。是一個提供統一消息服務的應用層標準高級消息 隊列協議,是應用層協議的一個開放標準,為面向消息的中間件設計。
Publisher
消息的生產者。也是一個向交換器Exchange發送消息的客戶端應用程序。
Consumer
消息的消費者。表示一個從消息隊列中取得消息的客戶端應用程序。
Server/Broker
又稱Broker,接受客戶端的連接,實現AMQP實體服務。
Virtual host
虛擬地址,用于進行邏輯隔離,最上層的消息路由。
表示一批交換器,消息隊列和相關對象。一個Virtual Host里面可以有若干個Exchange和Queue,同一個Virtual Host里面不能有相同名稱的Exchange和Queue。
虛擬主機是共享相同的身份認證和加密環境的獨立服務器域,每個vhost本質上就是一個mini版本的RabbitMQ服務器,擁有自己的隊列、交換器、綁定和權限機制。vhost是AMQP概念的基礎,必須在鏈接時指定,RabbitMQ默認的vhost是“/”。
Message
消息,服務器和應用程序之間傳送的數據。消息是不具名的,由Properties和Body組成(消息頭和消息體)。Properties可以對消息進行修飾,比如消息的優先級、延遲等高級特性;Body這就是消息體內容。
Exchange
交換機,接收生產者發送的消息,根據路由鍵轉發消息到綁定的隊列。
三種常見的交換機類型:
1、direct(發布與訂閱,完全匹配)
2、fanout(廣播)
3、topic(主題,規則匹配)
Binding
綁定。Exchange和Queue之間的虛擬連接,binding中可以包含routing key。
一個綁定就是基于路由鍵將交換器和消息隊列連接起來的路由規則,所以可以將交換器理解成一個由綁定構成的路由表。
Routing key
路由鍵。一個路由規則,虛擬機可用它來確定如何路由一個特定消息。
隊列通過路由鍵綁定到交換機。
消息發送到MQ服務器時,消息將擁有一個路由鍵,即便是空的。RabbitMQ也會將其和綁定使用的路由鍵進行匹配。
如果匹配,消息將投遞到該隊列;如果不匹配,消息將會進入黑洞。
Connection
連接,應用程序與Broker的TCP網絡連接。
Channel
網絡信道,是TCP里面的虛擬連接。幾乎所有的操作都在Channel中進行, Channel是進行消息讀寫的通道。客戶端可以建立多個Channel,每個Channel代表一個會話任務(類似數據庫中Connection中的session)。例如:電纜相當于TCP,信道是一個獨立光纖束,一條TCP連接上創建多條信道是沒有問題的。
TCP一旦打開,就會創建AMQP信道。
無論是發布消息、接收消息、訂閱隊列,這些動作都是通過信道完成的。
RabbitMQ為什么需要信道?為什么不是直接通信?
1、TCP的創建和銷毀開銷特別大。創建需要3次握手,銷毀需要4次分手;
2、如果不用信道,那應用程序就會以TCP連接RabbitMQ,高峰時每秒成千上萬條連接會造成資源巨大浪費,而且操作系統每秒處理TCP連接數也是有限制的,必定造成性能瓶頸;
3、信道的原理是一條線程一條通道,多條線程多條通道同用一條TCP連接。一條TCP連接可以容納無限的信道,即使每秒成千上萬的請求也不會成為性能瓶頸。
Queue
也稱為Message Queue(消費者創建),消息隊列,保存消息并將它們轉發給消費者。它是消息的容器,也是消息的終點。一個消息可以投入一個或多個隊列。消息一直在隊列里面,等待消費者連接到這個隊列上將其取走。
RabbitMQ(Advanced Message Queuing Protocol,高級消息隊列協議)是一個開源的消息代理和隊列服務器,用來通過普通協議在完全不同的應用之間共享數據,RabbitMQ是使用Erlang語言來編寫的,并且RabbitMQ是基于AMQP協議的。
RabbitMQ高性能的原因:
Erlang語言是一種通用的面向并發的編程語言,最初在于交換機領域的架構模式,這樣使得RabbitMQ在Broker之間通過數據交互的性能是非常優秀的,Erlang有著和原生Socket一樣的延遲。
發消息的時候需要指定發往哪個Exchange,然后借助routing key發送到對應的消息隊列queue,消費者從訂閱的消息隊列上取消息。
可以從架構圖看出,RabbitMQ是典型的生產者-消費者模型。
Exchange交換機,接收消息,并根據路由鍵轉發消息所綁定的隊列。
交換機屬性:
Name:交換機名稱
Type:交換機類型direct、topic、fanout、headers
Durability:是否需要持久化(true表示需要持久化)
Auto Delete:當最后一個綁定到Exchange上的隊列刪除后,自動刪除該Exchange
Internal:當前Exchange是否用于RabbitMQ內部使用,默認為false(很多場景都不會用到該設置)
Arguments:擴展參數,用于擴展AMQP協議自制定化使用
所有發送到Direct Exchange的消息被轉發到RouteKey中指定Queue。
注意:Direct模式可以使用RabbitMQ自帶的Exchange:default Exchange,所以不需要將Exchange進行任何綁定(binding)操作,消息傳遞時,RouteKey必須完全匹配才會被隊列接收,否則該消息會拋棄。
所有發送到Topic Exchange的消息被轉發到所有關心RouteKey中指定Topic的Queue上。
Exchange將RouteKey和某個Topic進行模糊匹配,此時隊列需要綁定一個Topic。
注:可以使用通配符進行模糊匹配。
Fanout(群發)不處理路由鍵,只需要簡單的將隊列綁定到交換機上。
發送到交換機的消息都會被轉發到與該交換機綁定的所有隊列上。
Fanout交換機轉發消息是最快的。
什么是生產端的可靠性投遞?
1、保障消息的成功發出;
2、保障MQ節點的成功接收;
3、發送端收到MQ節點(Broker)確認應答ACK;
4、完善的消息進行補償機制。
互聯網大廠的解決方案:
消息落庫,對消息狀態進行打標;
消息的延遲投遞,做二次確認,回調檢查。
1、消息落庫/持久化
消息信息落庫(即消息持久化),對消息狀態進行打標:
注:這種方案需要對數據庫進行兩次持久化操作。
2、延遲投遞
消息落庫在高并發場景下,數據庫IO壓力大,不適用。互聯網大廠一般采用的是延遲投遞,做二次檢查,回調檢查。
注:upstream表示生產端,downstream表示消費端。
1、首先,數據庫持久化,然后發送first send消息;
2、同時發送一個延遲的檢查消息(檢查第一次發送消息消費情況);
3、消費端消費消息;
4、消費端發送一個確認消息給Broker;
5、回調服務檢測到消費端的確認消息,進行數據庫的狀態持久化(這樣相當于數據庫一次操作,異步持久化);
6、回調服務響應第二個延時消息,確認消息成功消費,如果出現異常,回調服務調用RPC給生產者,再次發送。
冪等性即對數據進行若干次操作,仍然保證正確。
消費端實現冪等性,就意味著,我們的消息永遠不會消費多次,即使收到多條一樣的消息。
業界主流的冪等性操作:
唯一ID+指紋碼機制
利用Redis的原子性實現
1、唯一ID+指紋碼機制
使用唯一ID不能保證唯一性(用戶可能在短時間內執行多次消費),還需要一個指紋碼(這個可能是業務規則,比如時間戳等生成的,也可以是數據庫主鍵)。
執行SQL:
SELECTCOUNT(1)FROMT_ORDERWHEREID=唯一ID+指紋碼
如果返回0可以執行ISNERT操作,如果返回1則不執行。
優點:
實現簡單
缺點:
高并發下有數據庫寫入的性能瓶頸
解決方案:
跟進ID進行分庫分表進行算法路由
2、利用Redis的原子性實現
借助Redis本身的原子性操作實現。使用Redis進行冪等,需要考慮的問題:
1、我們是否要進行數據落庫,如果落庫的話,關鍵解決的問題是數據庫和緩存如何做到原子性?
2、如果不進行落庫,那么都存儲在緩存中,如何設置定時同步的策略?
消息的確認,是指生產者投遞消息后,如果Broker收到消息,則會給我們生產者一個應答。
生產者進行接收應答,用來確定這個消息是否正常的發送到Broker,這種方式也是消息的可靠性投遞的核心保證!
如何實現Confirm確認消息?
1、在channel上開啟確認模式:channel.confirmSelect()
2、在channel上添加監聽addConfirmListener,監聽成功和失敗的返回結果,根據具體的結果對消息進行重新發送、或記錄日志等后續處理。
Return Listener用于處理一些不可路由的消息!
我們的消息生產者通過指定一個Exchange和RoutingKey,把消息送到到某一個隊列中去,然后我們的消費者監聽隊列,進行消費處理操作。
但是在某些情況下,如果我們在發送消息的時候,當前的Exchange不存在或者指定的路由key路由不到,這個時候如果我們需要監聽這種不可達的消息,就要使用Return Listener。
假設這樣一個場景,首先,RabbitMQ服務器有上萬條未處理的消息,我們隨便打開一個消費者客戶端,會出現下面情況:巨量的消息瞬間全部推送過來,但是我們單個客戶端無法同時處理這么多數據。
RabbitMQ提供了一種QOS(服務質量保證)功能,即在非自動確認消息的前提下,如果一定數目的消息(通過基于consumer或者channel設置Qos的值)未被確認前,不進行消費新的消息。
消費端進行消費的時候,如果由于業務異常我們可以進行日志的記錄,然后進行補償。如果由于服務器宕機等嚴重問題,那我們就需要手工進行ACK保障消費端消費成功。
消息確認ACK:如果在處理消息的過程中,消費者的服務器在處理消息時出現異常,那可能這條正在處理的消息就沒有完成消息消費,數據就會丟失。為了確保數據不會丟失,RabbitMQ支持消息確認ACK。
ACK的消息確認機制是消費者從RabbitMQ收到消息并處理完成后,反饋給RabbitMQ,RabbitMQ收到反饋后才將此消息從隊列中刪除。
1、如果一個消費者在處理消息出現了網絡不穩定、服務器異常等現象,那么就不會有ACK反饋,RabbitMQ會認為這個消息沒有正常消費,會將消息重新放入隊列中。
2、如果在集群的情況下:RabbitMQ會立即將這個消息推送給這個在線的其他消費者。這種機制保證了在消費者服務器故障的時候,不丟失任何消息和任務。
3、消息永遠不會從RabbitMQ中刪除:只有當消費者正確發送ACK反饋,RabbitMQ確認收到后,消息才會從RabbitMQ服務器的數據中刪除;
4、消息的ACK確認機制默認是打開的。
ACK機制的開發注意事項:
如果忘記了ACK,那么后果很嚴重。當Consumer退出時,Message會一直重新分發,然后RabbitMQ會占用越來越多的額內存,由于RabbitMQ會長時間運行,因此這個“內存泄露”是致命的。
消費端重回隊列是為了對沒有處理成功的消息,把消息重新遞給Broker。
一般在實際應用中,都會關閉重回隊列,也就是設置為false。
TTL是Time To Live的縮寫,也就是生存時間。
RabbitMQ支持消息的過期時間,在消息發送時可以進行指定。
RabbitMQ支持隊列的過期時間,從消息入隊列開始計算,只要超過了隊列的超時時間配置,那么消息會自動的清除。
死信隊列(DLX,Dead-Letter-Exchange)。利用DLX,當消息在一個隊列中變成死信(dead message)之后,它能被重新publish到另一個Exchange,這個Exchange就是DLX。
消息變成死信的幾種情況:
1、 消息被拒絕(basic.reject/basic.nack)并且request=false;
2、 消息TTL過期;
3、 隊列達到最大長度。
DLX也是一個正常的Exchange,和一般的Exchange沒有區別,它能在任何的隊列上被指定,實際上就是設置某個隊列的屬性。
當這個隊列中有死信時,RabbitMQ就會自動的將這個消息重新分布到設置的Exchange上去,進而被路由到另一個隊列。
可以監聽這個隊列中消息做相應的處理,這個特性可以彌補RabbitMQ3.0以前的immediate參數的功能。
死信隊列的設置:
1、首先,需要設置死信隊列的Exchange和queue,然后進行綁定:
Exchange:dlx.exchangeQueue:dlx.queueRoutingKey:#
2、然后,我們進行正常聲明交換機、隊列、綁定,只不過我們需要在隊列機上一個參數即可:arguments.put(“x-dead-letter-exchange”,”dlx.exchange”);這樣消息在過期、requeue、隊列在達到最大長度時,消息就可以直接路由到死信隊列。
rabbitmqctl stop_app:關閉應用
rabbitmqctl start_app:啟動應用
rabbitmqctl status:節點狀態
rabbitmqctl add_user username password:添加用戶
rabbitmqctl list_users:列出所有用戶
rabbitmqctl delete_user username:刪除用戶
rabbitmqctl clear_permissions -p vhostpath username:清除用戶權限
rabbitmqctl list_user_permissions username:列出用戶權限
rabbitmqctl change_password username newpassword:修改密碼
rabbitmqctlset_permission -p vhostpath username “.*”“.*”“.*”:設置用戶權限
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。