RabbitMQ系列(二)深入了解RabbitMQ工作原理及簡單使用

RabbitMQ簡介

在介紹RabbitMQ之前實現要介紹一下MQ,MQ是什么?

MQ全稱是Message Queue,可以理解為消息隊列的意思,簡單來說就是消息以管道的方式進行傳遞。

RabbitMQ是一個實現了AMQP(Advanced Message Queuing Protocol)高級消息隊列協議的消息隊列服務,用Erlang語言的。

使用場景

在我們秒殺搶購商品的時候,系統會提醒我們稍等排隊中,而不是像幾年前一樣頁面卡死或報錯給用戶。

像這種排隊結算就用到了消息隊列機制,放入通道里面一個一個結算處理,而不是某個時間斷突然涌入大批量的查詢新增把數據庫給搞宕機,所以RabbitMQ本質上起到的作用就是削峰填谷,為業務保駕護航。

為什么選擇RabbitMQ

現在的市面上有很多MQ可以選擇,比如ActiveMQ、ZeroMQ、Appche Qpid,那問題來了為什么要選擇RabbitMQ?

  1. 除了Qpid,RabbitMQ是唯一一個實現了AMQP標準的消息服務器;
  2. 可靠性,RabbitMQ的持久化支持,保證了消息的穩定性;
  3. 高并發,RabbitMQ使用了Erlang開發語言,Erlang是為電話交換機開發的語言,天生自帶高并發光環,和高可用特性;
  4. 集群部署簡單,正是應為Erlang使得RabbitMQ集群部署變的超級簡單;
  5. 社區活躍度高,根據網上資料來看,RabbitMQ也是首選;

工作機制

生產者、消費者和代理

在了解消息通訊之前首先要了解3個概念:生產者、消費者和代理。

生產者:消息的創建者,負責創建和推送數據到消息服務器;

消費者:消息的接收方,用于處理數據和確認消息;

代理:就是RabbitMQ本身,用于扮演“快遞”的角色,本身不生產消息,只是扮演“快遞”的角色。

消息發送原理

首先你必須連接到Rabbit才能發布和消費消息,那怎么連接和發送消息的呢?

你的應用程序和Rabbit Server之間會創建一個TCP連接,一旦TCP打開,并通過了認證,認證就是你試圖連接Rabbit之前發送的Rabbit服務器連接信息和用戶名和密碼,有點像程序連接數據庫,使用Java有兩種連接認證的方式,后面代碼會詳細介紹,一旦認證通過你的應用程序和Rabbit就創建了一條AMQP信道(Channel)。

信道是創建在“真實”TCP上的虛擬連接,AMQP命令都是通過信道發送出去的,每個信道都會有一個唯一的ID,不論是發布消息,訂閱隊列或者介紹消息都是通過信道完成的。

為什么不通過TCP直接發送命令?

對于操作系統來說創建和銷毀TCP會話是非常昂貴的開銷,假設高峰期每秒有成千上萬條連接,每個連接都要創建一條TCP會話,這就造成了TCP連接的巨大浪費,而且操作系統每秒能創建的TCP也是有限的,因此很快就會遇到系統瓶頸。

如果我們每個請求都使用一條TCP連接,既滿足了性能的需要,又能確保每個連接的私密性,這就是引入信道概念的原因。

你必須知道的Rabbit

想要真正的了解Rabbit有些名詞是你必須知道的。

包括:ConnectionFactory(連接管理器)、Channel(信道)、Exchange(交換器)、Queue(隊列)、RoutingKey(路由鍵)、BindingKey(綁定鍵)。

**ConnectionFactory(連接管理器):**應用程序與Rabbit之間建立連接的管理器,程序代碼中使用;

**Channel(信道):**消息推送使用的通道;

**Exchange(交換器):**用于接受、分配消息;

Queue(隊列):用于存儲生產者的消息;

RoutingKey(路由鍵):用于把生成者的數據分配到交換器上;

BindingKey(綁定鍵):用于把交換器的消息綁定到隊列上;

看到上面的解釋,最難理解的路由鍵和綁定鍵了,那么他們具體怎么發揮作用的,請看下圖:

關于更多交換器的信息,我們在后面再講。

消息持久化

Rabbit隊列和交換器有一個不可告人的秘密,就是默認情況下重啟服務器會導致消息丟失,那么怎么保證Rabbit在重啟的時候不丟失呢?答案就是消息持久化。

當你把消息發送到Rabbit服務器的時候,你需要選擇你是否要進行持久化,但這并不能保證Rabbit能從崩潰中恢復,想要Rabbit消息能恢復必須滿足3個條件:

  1. 投遞消息的時候durable設置為true,消息持久化,代碼:channel.queueDeclare(x, true, false, false, null),參數2設置為true持久化;
  2. 設置投遞模式deliveryMode設置為2(持久),代碼:channel.basicPublish(x, x, MessageProperties.PERSISTENT_TEXT_PLAIN,x),參數3設置為存儲純文本到磁盤;
  3. 消息已經到達持久化交換器上;
  4. 消息已經到達持久化的隊列;

持久化工作原理

Rabbit會將你的持久化消息寫入磁盤上的持久化日志文件,等消息被消費之后,Rabbit會把這條消息標識為等待垃圾回收。

持久化的缺點

消息持久化的優點顯而易見,但缺點也很明顯,那就是性能,因為要寫入硬盤要比寫入內存性能較低很多,從而降低了服務器的吞吐量,盡管使用SSD硬盤可以使事情得到緩解,但他仍然吸干了Rabbit的性能,當消息成千上萬條要寫入磁盤的時候,性能是很低的。

所以使用者要根據自己的情況,選擇適合自己的方式。

虛擬主機

每個Rabbit都能創建很多vhost,我們稱之為虛擬主機,每個虛擬主機其實都是mini版的RabbitMQ,擁有自己的隊列,交換器和綁定,擁有自己的權限機制。

vhost特性

  1. RabbitMQ默認的vhost是“/”開箱即用;

  2. 多個vhost是隔離的,多個vhost無法通訊,并且不用擔心命名沖突(隊列和交換器和綁定),實現了多層分離;

  3. 創建用戶的時候必須指定vhost;

vhost操作

可以通過rabbitmqctl工具命令創建:

rabbitmqctl add_vhost[vhost_name]

刪除vhost:

rabbitmqctl delete_vhost[vhost_name]

查看所有的vhost:

rabbitmqctl list_vhosts

環境搭建

前文我們已經介紹了Ubuntu搭建RabbitMQ的步驟:RabbitMQ在Ubuntu上的環境搭建

如果你是在Windows10上去安裝那就更簡單了,先放下載地址:

Erlang/Rabbit Server百度網盤鏈接:pan.baidu.com/s/1TnKDV-Zu… 密碼:wct9

當然也可去Erlang和Rabbit官網去下,就是速度比較慢。我的百度云Rabbit最新版本:3.7.6,Erlang版本:20.2,注意:不要下載最新的Erlang,在Windows10上打開擴展插件有問題,打不開。

  1. 安裝Erlang;

  2. 安裝Rabbit Server;

  3. 進入安裝目錄\sbin下,使用命令“rabbitmq-plugins enable rabbitmq_management”啟動網頁管理插件;

  4. 重啟Rabbit服務;

使用:http://localhost:15672進行測試,默認的登陸賬號為:guest,密碼為:guest

重復安裝Rabbit Server的坑

如果不是第一次在Windows上安裝Rabbit Server一定要把Rabbit和Erlang卸載干凈之后,找到注冊表:HKEY_LOCAL_MACHINE\SOFTWARE\Ericsson\Erlang\ErlSrv 刪除其下的所有項。

不然會出現Rabbit安裝之后啟動不了的情況,理論上卸載的順序也是先Rabbit在Erlang。

代碼實現

java版實現,使用maven項目,創建可以查看:MyEclipse2017破解設置與maven項目搭建

項目創建成功之后,添加Rabbit Client jar包,只需要在pom.xml里面配置,如下信息:

 <dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.2.0</version>
</dependency>
復制代碼

java實現代碼分為兩個類,第一個是創建Rabbit連接,第二是應用類使用最簡單的方式發布和消費消息。

Rabbit的連接,兩種方式:

方式一:

public static Connection GetRabbitConnection() {ConnectionFactory factory = new ConnectionFactory();factory.setUsername(Config.UserName);factory.setPassword(Config.Password);factory.setVirtualHost(Config.VHost);factory.setHost(Config.Host);factory.setPort(Config.Port);Connection conn = null;try {conn = factory.newConnection();} catch (Exception e) {e.printStackTrace();}return conn;
}
復制代碼

方式二:

public static Connection GetRabbitConnection2() {ConnectionFactory factory = new ConnectionFactory();// 連接格式:amqp://userName:password@hostName:portNumber/virtualHostString uri = String.format("amqp://%s:%s@%s:%d%s", Config.UserName, Config.Password, Config.Host, Config.Port,Config.VHost);Connection conn = null;try {factory.setUri(uri);factory.setVirtualHost(Config.VHost);conn = factory.newConnection();} catch (Exception e) {e.printStackTrace();}return conn;
}
復制代碼

第二部分:應用類,使用最簡單的方式發布和消費消息

public static void main(String[] args) {Publisher(); // 推送消息Consumer(); // 消費消息
}/*** 推送消息*/
public static void Publisher() {// 創建一個連接Connection conn = ConnectionFactoryUtil.GetRabbitConnection();if (conn != null) {try {// 創建通道Channel channel = conn.createChannel();// 聲明隊列【參數說明:參數一:隊列名稱,參數二:是否持久化;參數三:是否獨占模式;參數四:消費者斷開連接時是否刪除隊列;參數五:消息其他參數】channel.queueDeclare(Config.QueueName, false, false, false, null);String content = String.format("當前時間:%s", new Date().getTime());// 發送內容【參數說明:參數一:交換機名稱;參數二:隊列名稱,參數三:消息的其他屬性-routing headers,此屬性為MessageProperties.PERSISTENT_TEXT_PLAIN用于設置純文本消息存儲到硬盤;參數四:消息主體】channel.basicPublish("", Config.QueueName, null, content.getBytes("UTF-8"));System.out.println("已發送消息:" + content);// 關閉連接channel.close();conn.close();} catch (Exception e) {e.printStackTrace();}}
}/*** 消費消息*/
public static void Consumer() {// 創建一個連接Connection conn = ConnectionFactoryUtil.GetRabbitConnection();if (conn != null) {try {// 創建通道Channel channel = conn.createChannel();// 聲明隊列【參數說明:參數一:隊列名稱,參數二:是否持久化;參數三:是否獨占模式;參數四:消費者斷開連接時是否刪除隊列;參數五:消息其他參數】channel.queueDeclare(Config.QueueName, false, false, false, null);// 創建訂閱器,并接受消息channel.basicConsume(Config.QueueName, false, "", new DefaultConsumer(channel) {@Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body) throws IOException {String routingKey = envelope.getRoutingKey(); // 隊列名稱String contentType = properties.getContentType(); // 內容類型String content = new String(body, "utf-8"); // 消息正文System.out.println("消息正文:" + content);channel.basicAck(envelope.getDeliveryTag(), false); // 手動確認消息【參數說明:參數一:該消息的index;參數二:是否批量應答,true批量確認小于index的消息】}});} catch (Exception e) {e.printStackTrace();}}
}
復制代碼

代碼里面已經寫了很詳細的注釋,在這里也不過多的介紹了。

執行效果,如圖:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277708.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277708.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277708.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

四葉草社交平臺——十天沖刺(10)

姑且就這樣了&#xff0c;找了個新模板&#xff0c;這個模板先用來過關吧。轉載于:https://www.cnblogs.com/limitCM/p/10925208.html

虛擬機(Visual Machine)的云平臺的自動伸縮擴容(auto-scaling)技術

云計算平臺中允許客戶依據應用的負載進行云計算資源的彈性動態伸縮&#xff08;理想的情況是實現一個用多少付費多少的模型&#xff0c;最大限度地降低用戶的運營成本&#xff09; 在進行討論之前&#xff0c;先對幾個名詞進行定義 1&#xff09;客戶&#xff1a;使用云服務的人…

Unity 3D學習筆記之一 界面介紹

因為學校的課程&#xff0c;本學期對Unity 3D有學習的要求&#xff0c;在博客中記錄下自己的Unity學習之路&#xff08;內容摘錄自書本和視頻&#xff0c;書本為Unity 4.x從入門到精通&#xff09;一、Unity界面介紹首先進入Unity3D&#xff0c;在菜單欄&#xff0c;File中new …

Python 獲得程序 exe 的版本號

Python 獲得程序 exe 的版本號 python中需要安裝 pywin32 包 # based on http://stackoverflow.com/questions/580924/python-windows-file-version-attribute from win32com.client import Dispatchdef get_version_via_com(filename):parser Dispatch("Scripting.FileS…

Coding and Paper Letter(一)

2019獨角獸企業重金招聘Python工程師標準>>> 最近發現需要在快速閱讀背景下&#xff0c;對快餐式資源做整理與收集。以Coding&#xff08;以Github&#xff09;和Paper&#xff08;自己看到的一些論文&#xff0c;論文一般主要看題目和摘要做些簡單小結&#xff09;…

MacBook刷機勘錯篇

前一段時間突然發現自己的MacBook已經好久沒有刷過系統了&#xff0c;10.9用著還好&#xff0c;但bootcamp裝的win8.1越來越卡&#xff0c;越用越慢。想要重做一下雙系統&#xff0c;后來就演變成了兩個系統一起更新&#xff0c;再后來就演變成了一個慘案。因為自己一直也沒有使…

字典、列表、元組

1 字典2 Python內置的字典數據類型&#xff1a;全稱dictionary&#xff0c;在其他語言中也稱為map&#xff0c;使用鍵-值&#xff08;key-value&#xff09;存儲&#xff0c;具有極快的查找速度3 4 當將key-value放進dict時&#xff0c;dict會根據key算出value要存放地址&#…

Sublime Text怎么快速建立一個html5頁面模板

在編輯器中輸入一個半角英文的感嘆號&#xff08;!&#xff09;,然后按下TAB鍵

Mac OS X 10.10更新及體驗

前一陣子&#xff0c;更新了Mac OS 10.10 Yosemite&#xff0c;總體用起來感覺還是很不錯的&#xff0c;是很值得升級&#xff0c;相對于10.9 Mavericks優化了不少東西。我之前寫的使用教程有一些也就不適用了&#xff1b;比如更換Dashboard中的背景&#xff0c;10.10中Dashboa…

快速冪學習筆記

啥是快速冪 快速冪&#xff0c;顧名思義&#xff0c;就是快速算某個數的多少次冪。其時間復雜度為 \(O(\log N)\)&#xff0c; 與樸素的\(O(N)\)相比效率有了極大的提高。 原理 來自學長&#xff1a; 我們可以把 \(b\) 分解成二進制數&#xff0c;其中從小到大每一個二進制位 是…

文本處理工具sed

sed&#xff1a;stream Editor流編輯器&#xff0c;默認不編輯原文件&#xff0c;僅對模式空間中的數據做處理&#xff1b;而后&#xff0c;處理結束后&#xff0c;將模式空間打印至屏幕。語法&#xff1a; sed [option] AddressCommand file1 file2... option選項有&#xff1…

Mac OS X必備APP推薦之一

本篇博文要推薦一下裝機必備的APP&#xff0c;因為電腦的使用需求因人而異&#xff0c;這里我根據我的見解和長時間的使用經驗推薦一些我認為大家基本都用得到的APP&#xff0c;太過專業性質的我就不推薦了&#xff0c;當然我的推薦肯定會有疏漏和偏差的地方&#xff0c;還請熟…

2018-2019-2 20175235 實驗四《Android開發基礎》實驗報告

實驗目的 一、Android Studio的安裝測試 二、Activity測試 三、UI測試 四、布局測試 五、事件處理測試 一.Android Stuidio的安裝測試&#xff1a; 參考《Java和Android開發學習指南(第二版)(EPUBIT,Java for Android 2nd)》第二十四章&#xff1a; 參考http://www.cnblogs.com…

Mac OS X必備APP推薦之二

本篇接著上一篇APP推薦的博文&#xff0c;繼續為大家推薦Mac下好用的APP。 一、首先推薦一款DaisyDisk&#xff0c;磁盤分析、清理工具。前面第一篇APP推薦中&#xff0c;我們推薦過APP和系統垃圾清理工具——Cleanmymac&#xff0c;這兩個APP側重有所不同。Cleanmymac主要清理…

【編程大系】Java資源匯總

1.學習資料&#xff1a; 1&#xff09;Spring Boot 那些事&#xff1a;https://www.w3cschool.cn/springboot/ 對應的 gitHub代碼&#xff1a; https://github.com/JeffLi1993/springboot-learning-example 2&#xff09;Spring Boot基礎視頻&#xff1a;https://www.w3cschool…

Mac OSX使用VMware Fusion安裝windows虛擬機教程

安裝虛擬機之前&#xff0c;先要有兩步準備工作。第一&#xff0c;安裝并激活VMware Fusion&#xff0c;如果大家還沒有下載VMware Fusion請參照上一篇博文&#xff0c;APP推薦之二&#xff0c;下載VMware Fusion并激活。第二&#xff0c;下載你想要安裝的系統鏡像。因為已經裝…

利用CAGradientLayer自定義顏色漸變view

說個故事&#xff1a; UI設計對大家說:“我們拒絕炒現飯!"。 然后就加了一波特效。 程序員猝。 #####效果分析&#xff1a; 1.水波動畫。 2.背景顏色漸變。 #####實現思路&#xff1a; 1.水波動畫&#xff0c;用CGMutablePathRef和三角函數畫出波浪線&#xff0c;讓后利用…

【筆記】spring定時器時間配置實例

"0/10 * * * * ?" 每10秒觸發 "0 0 12 * * ?" 每天中午12點觸發 "0 15 10 ? * *" 每天上午10:15觸發 "0 15 10 * * ?" 每天上午10:15觸發 "0 15 10 * * ? *" 每天上午10:15觸發 "0 15 10 * * ? 2005" 2…

java簡介和開發環境搭建

因為本人的Java一直以來水平都不怎么樣&#xff0c;大一的時候只考了60分。所以在臨近畢業的時候&#xff0c;我選擇了重修Java&#xff0c;這些天正在慢慢的回顧Java&#xff0c;會到博客里面記錄一些Java的知識&#xff0c;不為有多少人來看&#xff0c;只希望自己有所收獲。…

第六章 函數和宏定義實驗(2)

C程序設計實驗報告 實驗項目&#xff1a; 1、利用復化梯形公式計算定積分 2、計算Ackerman函數 3、編寫計算x的y次冪的遞歸函數getpower(int x,int y)&#xff0c;并在主程序中實現輸入輸出 4、編寫計算學生年齡的遞歸函數 5、編寫遞歸函數實現Ackman函數 姓名&#xff1a;王錦…