RabbitMQ進階攻略,分析RabbitMQ的典型應用場景秽梅,詳解RabbitMQ的運作流程

RabbitMQ進階攻略抹蚀,分析RabbitMQ的典型應用場景,詳解RabbitMQ的運作流程

0企垦、引言

上次課我們僅說了RabbitMQ是一種消息中間件环壤,可以異步的處理客戶端發(fā)送的消息,但是我們并沒有將什么是消息中間件钞诡,使用消息中間件會給我們的系統帶來怎樣的性能提升郑现?這次課我們就來說一下什么是消息中間件,我們通過一個案例來引出消息中間件荧降,說明消息中間件在我們這個系統中扮演什么樣重要的角色接箫?

1、什么是消息中間件

上節(jié)課我們僅說了什么是RabbitMQ朵诫,但并沒有說什么是消息中間件辛友,為什么要使用消息中間件?

1)問題引入:

假設我們現在需要設計這樣一個用戶注冊系統:用戶注冊完成后剪返,需要給用戶發(fā)送激活郵件瞎领,開通用戶賬號,記錄用戶IP随夸、用戶設備、時間等信息震放。

起初的設計:

2)但存在的問題是

由于多個系統強耦合在一起宾毒,用戶注冊響應會非常慢,嚴重影響了用戶的體驗殿遂,當流量大的時候诈铛,性能會更差乙各。

3)引入消息中間件:

為了解決上述問題,我們引入消息中間件幢竹,來實現系統的解耦耳峦,多個系統間通過消息中間件進行異步通信,最終的設計圖如下:

即實現了系統解耦焕毫,又提升了系統響應的速度

4)消息中間件介紹:

消息中間件(Message Queue Middleware蹲坷,簡稱MQ)又稱為消息隊列,是指利用高效可靠的消息傳遞機制進行與平臺無關的數據交流邑飒,并基于數據通信來進行分布式系統的構建循签。

2、應用場景分析

1)異步通信

在很多時候疙咸,為了加快應用系統整體運轉速度县匠,并不需要立即響應某些請求,消息中間件提供了異步處理機制撒轮,允許將一些請求信息放入消息中間件中乞旦,但并不立即處理它,而是慢慢處理题山。在有限資源下兰粉,使用消息中間件能夠使系統性能從容倍增!

如:用戶注冊成功的郵件通知臀蛛;用戶購物下單的信息通知亲桦;大數據日志收集處理

2)削峰

以防突發(fā)劇增流量瞬間沖垮系統,使用消息中間件可以支撐突發(fā)訪問壓力

3)業(yè)務系統解耦

系統間的耦合關系太強浊仆,會對系統的設計產生束縛客峭,也會增加系統的復雜性,通過消息中間件可以更好的設計系統抡柿,是一個系統完成指定的功能舔琅,而不是將所有的功能融合在同一個系統中。

3洲劣、回顧下上節(jié)課的內容

關于上節(jié)課說的binding key备蚓、routing key,我這里再解釋下囱稽,有點難以理解

其實兩者是一樣的郊尝,只不過是不同的叫法而已,我們可以統一叫它routing key

4战惊、詳解RabbitMQ運作流程

相對于上節(jié)課講的概念流昏,又增加了virtual host、connection、channel

Virtual Host:?每個virtual host本質上都是一個RabbitMQ Server(但是一個server中可以有多個virtual host)况凉,擁有它自己若干的個Exchange谚鄙、Queue和bings rule等等。其實這是一個虛擬概念刁绒,類似于權限控制組闷营。Virtual Host是權限控制的最小粒度。

Connection:??就是一個TCP的連接知市。Producer和Consumer都是通過TCP連接到RabbitMQ Server的傻盟。接下來的實踐案例中我們就可以看到,producer和consumer與exchange的通信的前提是先建立TCP連接初狰。

僅僅創(chuàng)建了TCP連接莫杈,producer和consumer與exchange還是不能通信的。我們還需要為每一個Connection創(chuàng)建Channel奢入。

Channel:??它是建立在上述TCP連接之上的虛擬連接筝闹。數據傳輸都是在Channel中進行的。AMQP協議規(guī)定只有通過Channel才能執(zhí)行AMQP的命令腥光。一個Connection可以包含多個Channel关顷。

有人要問了,為什么要使用Channel呢武福,直接用TCP連接不就好了么议双?

對于一個消息服務器來說,它的任務是處理海量的消息捉片,當有很多線程需要從RabbitMQ中消費消息或者生產消息平痰,那么必須建立很多個connection,也就是許多個TCP連接伍纫。然而對于操作系統而言宗雇,建立和關閉TCP連接是非常昂貴的開銷,而且TCP的連接數也有限制莹规,頻繁的建立關閉TCP連接對于系統的性能有很大的影響赔蒲,如果遇到高峰,性能瓶頸也隨之顯現良漱。RabbitMQ采用類似NIO的做法舞虱,選擇TCP連接服用,不僅可以減少性能開銷母市,同時也便于管理矾兜。在TCP連接中建立Channel是沒有上述代價的,可以復用TCP連接患久。對于Producer或者Consumer來說椅寺,可以并發(fā)的使用多個Channel進行Publish或者Receive舶沿。

有實驗表明,在Channel中配并,1秒可以Publish10K的數據包。對于普通的Consumer或者Producer來說高镐,這已經足夠了溉旋。除非有非常大的流量時,一個connection可能會產生性能瓶頸嫉髓,此時就需要開辟多個connection观腊。

5、實戰(zhàn)演練生產算行、消費梧油,串講整個運作流程

代碼倉庫:https://gitee.com/jikeh/JiKeHCN-RELEASE.git

項目名:rabbitmqdemo

項目代碼中有詳細的運轉流程注釋,這里就不細講了……

查看Tcp連接:

查看信道連接:

6州邢、拓展:使用默認交換器完成最簡單的案例

代碼倉庫:https://gitee.com/jikeh/JiKeHCN-RELEASE.git

項目名:

生產者(producer)把消息發(fā)送到一個名為“hello”的隊列中儡陨。

消費者(consumer)從這個隊列中獲取消息。

(1)引入jar包


<dependency>

<groupId>com.rabbitmq</groupId>

<artifactId>amqp-client</artifactId>

<version>LATEST</version>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>1.6.6</version>

</dependency>

(2)生產者發(fā)送消息

0)聲明常量參數


privatestaticfinalStringQUUE_NAME="hello";

privatestaticfinalStringIP_ADDRESS="localhost";

privatestaticfinalintPORT=5672;//默認端口號為5672

?

privatestaticfinalStringUSER_NAME="guest";

privatestaticfinalStringUSER_PWD="guest";

1)創(chuàng)建和RabbitMQ的連接


//初始化TCP連接參數

ConnectionFactoryfactory=newConnectionFactory();

factory.setHost(IP_ADDRESS);

factory.setPort(PORT);

factory.setUsername(USER_NAME);

factory.setPassword(USER_PWD);

factory.setVirtualHost("/");

?

//創(chuàng)建連接

Connectionconnection=factory.newConnection();

?

//創(chuàng)建信道

Channelchannel=connection.createChannel();

2)聲明隊列


/**

* 語法格式:queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

* 創(chuàng)建一個持久化量淌、非排他的骗村、非自動刪除的隊列

* exclusive:排他的 由該客戶端獨占,一般設為false

* autoDelete:消息消費完呀枢,該隊列就會被刪除胚股,一般為false

*/

channel.queueDeclare(QUUE_NAME,true,false,false,null);

3)發(fā)送消息


//發(fā)送一條持久化的消息

//MessageProperties.PERSISTENT_TEXT_PLAIN:是以純文本格式發(fā)送

Stringmessage="Hello World!";

channel.basicPublish("",QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());

4)關閉連接,信道


//關閉信道

channel.close();

?

//關閉連接

connection.close();

(3)消費者獲取消息

0)聲明常量參數


privatestaticfinalStringQUUE_NAME="hello";

privatestaticfinalStringIP_ADDRESS="localhost";

privatestaticfinalintPORT=5672;//默認端口號為5672

?

privatestaticfinalStringUSER_NAME="guest";

privatestaticfinalStringUSER_PWD="guest";

1)創(chuàng)建和RabbitMQ的連接裙秋,并且聲明隊列


//初始化TCP連接參數

ConnectionFactoryfactory=newConnectionFactory();

factory.setUsername(USER_NAME);

factory.setPassword(USER_PWD);

?

Address[]addresses=newAddress[]{

newAddress(IP_ADDRESS,PORT)

};

?

//創(chuàng)建連接

Connectionconnection=factory.newConnection(addresses);

?

//創(chuàng)建信道

finalChannelchannel=connection.createChannel();

2)需要為隊列定義一個回調(callback)函數琅拌。當我們獲取到消息的時候,就會調用此回調函數


Consumerconsumer=newDefaultConsumer(channel) {

@Override

publicvoidhandleDelivery(StringconsumerTag,Envelopeenvelope,AMQP.BasicPropertiesproperties,byte[]body)throwsIOException{

System.out.printf("receive message:"+newString(body));

?

/**

* true to acknowledge all messages up to and including the supplied delivery tag; false to acknowledge just the supplied delivery tag.

* true:確認包括傳輸標記之前的所有信息摘刑;

* false:僅確認該傳輸標記的消息

*/

channel.basicAck(envelope.getDeliveryTag(),false);

?? }

};

3)我們需要告訴RabbitMQ這個回調函數將會從名為"hello"的隊列中接收消息


//channel.basicConsume(QUEUE_NAME, true, consumer);//自動確認消息

channel.basicConsume(QUUE_NAME,consumer);

4)關閉連接进宝,信道


channel.close();

connection.close();

多資料分享下載,請關注:

極客慧:http://www.jikeh.cn

QQ群:375412858

默認交換器泣侮,默認綁定關系:

The default exchange is implicitly bound to every queue, with a routing key equal to the queue name. It is not possible to explicitly bind to, or unbind from the default exchange. It also cannot be deleted.

參看文章:https://www.cloudamqp.com/blog/2015-05-18-part1-rabbitmq-for-beginners-what-is-rabbitmq.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末即彪,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子活尊,更是在濱河造成了極大的恐慌隶校,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛹锰,死亡現場離奇詭異深胳,居然都是意外死亡,警方通過查閱死者的電腦和手機铜犬,發(fā)現死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門舞终,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轻庆,“玉大人,你說我怎么就攤上這事敛劝∮啾” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵夸盟,是天一觀的道長蛾方。 經常有香客問我,道長上陕,這世上最難降的妖魔是什么桩砰? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮释簿,結果婚禮上亚隅,老公的妹妹穿的比我還像新娘。我一直安慰自己庶溶,他們只是感情好煮纵,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著渐尿,像睡著了一般醉途。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上砖茸,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天隘擎,我揣著相機與錄音,去河邊找鬼凉夯。 笑死货葬,一個胖子當著我的面吹牛,可吹牛的內容都是我干的劲够。 我是一名探鬼主播震桶,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼征绎!你這毒婦竟也來了蹲姐?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤人柿,失蹤者是張志新(化名)和其女友劉穎柴墩,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體凫岖,經...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡江咳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了哥放。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歼指。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡爹土,死狀恐怖,靈堂內的尸體忽然破棺而出踩身,到底是詐尸還是另有隱情胀茵,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布挟阻,位于F島的核電站宰掉,受9級特大地震影響,放射性物質發(fā)生泄漏赁濒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一孟害、第九天 我趴在偏房一處隱蔽的房頂上張望拒炎。 院中可真熱鬧,春花似錦挨务、人聲如沸击你。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丁侄。三九已至,卻和暖如春朝巫,著一層夾襖步出監(jiān)牢的瞬間鸿摇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工劈猿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拙吉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓揪荣,卻偏偏與公主長得像筷黔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子仗颈,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理佛舱,服務發(fā)現,斷路器挨决,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 什么叫消息隊列请祖? 消息(Message)是指在應用間傳送的數據。消息可以非常簡單凰棉,比如只包含文本字符串损拢,也可以更復...
    Agile_dev閱讀 2,370評論 0 24
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981閱讀 15,892評論 2 11
  • 本文章翻譯自http://www.rabbitmq.com/api-guide.html,并沒有及時更新撒犀。 術語對...
    joyenlee閱讀 7,645評論 0 3
  • 文/剪甯 目 錄 |【歷史仙俠】《仙旅三國之魔神董卓》簡介&目錄 上一章 | 【歷史仙俠】仙旅三國之魔神董卓(...
    剪甯閱讀 2,575評論 62 51