RabbitMQ是采用Erlang語(yǔ)言實(shí)現(xiàn)AMQP(Advanced Message Queuing Protocol岖食,高級(jí)消息隊(duì)列協(xié)議)冰肴。
RabbitMQ的具體特定包括下面幾點(diǎn):
可靠性:有持久化、傳輸確認(rèn)以及發(fā)布確認(rèn)等機(jī)制保證可靠性
靈活的路由:在消息進(jìn)入隊(duì)列之前肴敛,通過(guò)交換器來(lái)路由消息般贼。典型的路由有一些內(nèi)置交換器實(shí)現(xiàn)本昏,復(fù)制的路由可能將多個(gè)交換器綁定在一起,也可以通過(guò)插件機(jī)制來(lái)實(shí)現(xiàn)自己的交換器。
擴(kuò)展性:多個(gè)RabbitMQ節(jié)點(diǎn)可以組成一個(gè)集群被去,也可以根據(jù)實(shí)際業(yè)務(wù)情況動(dòng)態(tài)擴(kuò)展集群節(jié)點(diǎn)
高可用:隊(duì)列可以在集群中的機(jī)器上設(shè)置鏡像,部分節(jié)點(diǎn)出現(xiàn)問題時(shí)隊(duì)列仍然可用
多種協(xié)議:除了支持AMQP奖唯,還支持STOMP(Simple (or Streaming) Text Oriented Messaging Protocol惨缆,簡(jiǎn)單(流)文本面向消息協(xié)議),MQTT(Message Queue Telemetry Transport 丰捷,IBM開發(fā)的即時(shí)通信協(xié)議)等多種消息中間件協(xié)議坯墨。
多語(yǔ)言客戶端:支持Java、Python病往、Ruby捣染、PHP等
管理界面:提供了一個(gè)易用的用戶界面,可以監(jiān)控和管理消息停巷、集群中的節(jié)點(diǎn)等耍攘。
插件機(jī)制:提供了許多插件,實(shí)現(xiàn)多方面擴(kuò)展
RabbitMQ概念
生產(chǎn)者(Producer)創(chuàng)建消息發(fā)布到RabbitMQ畔勤,消息一般包含兩個(gè)部分:消息體(payload)和標(biāo)簽(Label)蕾各。消息的標(biāo)簽用來(lái)表述這條消息,比如一個(gè)交換器名稱和一個(gè)路由鍵庆揪。生產(chǎn)者把消息交由RabbitMQ之后會(huì)根據(jù)標(biāo)簽把消息發(fā)送給感興趣的消費(fèi)者(Consumer)式曲。
消費(fèi)者(Consumer)連接到RabbitMQ服務(wù)器并訂閱隊(duì)列。消費(fèi)消息的消息體(payload)嚷硫。在消息路由過(guò)程中检访,消息的標(biāo)簽會(huì)丟棄始鱼,存入到隊(duì)列中的消息只有消息體仔掸。
Broker:消息中間件的服務(wù)節(jié)點(diǎn)。
對(duì)于RabbitMQ來(lái)說(shuō)医清,一個(gè)RabbitMQ Broker可以簡(jiǎn)單看作一個(gè)RabbitMQ服務(wù)節(jié)點(diǎn)或者RabbitMQ服務(wù)實(shí)例起暮。
生產(chǎn)者將業(yè)務(wù)數(shù)據(jù)包裝成消息,發(fā)送(AMQP協(xié)議中這個(gè)動(dòng)作對(duì)應(yīng)命令為Basic.Publish)到Broker中会烙。消費(fèi)者訂閱并接收消息(AMQP協(xié)議中這個(gè)動(dòng)作對(duì)應(yīng)的命令為Basic.Consume 或Basic.Get)负懦,經(jīng)過(guò)可能的解包處理得到原始的數(shù)據(jù)再進(jìn)行業(yè)務(wù)處理邏輯。業(yè)務(wù)處理邏輯可以使用Java的BlockingQueue進(jìn)一步解耦提高處理效率柏腻。
隊(duì)列(Queue):RabbitMQ內(nèi)部對(duì)象用于存儲(chǔ)消息纸厉。RabbitMQ中消息都只能存儲(chǔ)在隊(duì)列中,這一點(diǎn)和Kafka相反五嫂,Kafka將消息存儲(chǔ)在topic(主題)這個(gè)邏輯層面颗品,而相對(duì)應(yīng)的隊(duì)列邏輯只是topic實(shí)際存儲(chǔ)文件中的位移標(biāo)識(shí)肯尺。多個(gè)消費(fèi)者可以訂閱同一個(gè)隊(duì)列,消息會(huì)被平均分?jǐn)偅≧ound-Robin)躯枢。RabbitMQ不支持隊(duì)列層面的廣播消費(fèi)则吟。
交換器(Exchange):生產(chǎn)者將消息發(fā)送到Exchange,由交換器將消息路由到一個(gè)或者多個(gè)隊(duì)列中锄蹂,如果路由不到或許返回給生產(chǎn)者氓仲,或許直接丟棄。RabbitMQ的交換器有四種類型得糜,不同類型有不同的路由策略敬扛。
路由鍵(RoutingKey):生產(chǎn)者將消息發(fā)給交換器的時(shí)候,會(huì)指定一個(gè)RoutingKey朝抖,用來(lái)指定這個(gè)消息的路由規(guī)則舔哪,這個(gè)RoutingKey需要與交換器類型和綁定鍵(BindingKey)聯(lián)合使用才能最終生效。
綁定(Binding):RabbitMQ中通過(guò)綁定講交換器與隊(duì)列關(guān)聯(lián)起來(lái)槽棍,綁定時(shí)一般會(huì)指定給一個(gè)綁定鍵(BindingKey)捉蚤,這樣RabbitMQ就知道如何正確地將消息路由到隊(duì)列。生產(chǎn)者將消息發(fā)送給交換器炼七,需要一個(gè)RoutingKey缆巧,當(dāng)BindingKey和RoutingKey相匹配時(shí),消息會(huì)被路由到對(duì)應(yīng)隊(duì)列豌拙。
交換器類型
RabbitMQ常用的交換器由fanout陕悬、direct、topic按傅、headers這四種捉超。AMQP協(xié)議里還提到另外兩種類型:System和自定義。
headers:不依賴于路由鍵的匹配規(guī)則來(lái)路由消息唯绍,而是根據(jù)發(fā)送消息內(nèi)容中的headers屬性進(jìn)行匹配拼岳。
fanout:會(huì)把所有發(fā)送到該交換器的消息路由到所有與該交換器綁定的隊(duì)列中。
direct:會(huì)把消息路由到哪些BindingKey和RoutingKey完全匹配的隊(duì)列中况芒。
topic:與direct相似惜纸,是將消息路由到BindingKey和RoutingKey相匹配的隊(duì)列中,但是這里匹配規(guī)則有些不同:
RountingKey為一個(gè)點(diǎn)號(hào) “.” 分隔的字符串绝骚,如“com.rabbitmq.client”
BindingKey 和 RoutingKey 一樣也是點(diǎn)號(hào)“.”分隔的字符串
BindingKey中可以存在兩種特殊字符“”和“#”耐版,用于模糊匹配。用于匹配一個(gè)單詞压汪,#用于匹配多個(gè)單詞(可以是零個(gè))
運(yùn)轉(zhuǎn)流程
生產(chǎn)者發(fā)送消息:
1. 生產(chǎn)者連接到RabbitMQ Broker粪牲,建立一個(gè)連接,開啟一個(gè)信道(Channel)
2. 生產(chǎn)者聲明一個(gè)交換器止剖,設(shè)置相關(guān)屬性腺阳,比如交換機(jī)類型湿滓、是否持久化等
3. 生產(chǎn)者聲明一個(gè)隊(duì)列并設(shè)置相關(guān)屬性,比如是否排他舌狗,是否持久化叽奥,是否自動(dòng)刪除等
4. 生產(chǎn)者通過(guò)路由鍵將交換器和隊(duì)列綁定起來(lái)
5. 生產(chǎn)者發(fā)送消息至RabbitMQ Broker,其中包含路由鍵痛侍、交換器等信息
6. 相應(yīng)的交換器根據(jù)收到的路由鍵查找相匹配的隊(duì)列
7. 如果找到朝氓,則將從生產(chǎn)者發(fā)送過(guò)來(lái)的消息存入相應(yīng)的隊(duì)列中。
8. 如果沒找到主届,根據(jù)生產(chǎn)者配置的屬性選擇丟棄還是回退給生產(chǎn)者
9. 關(guān)閉信道
10. 關(guān)閉連接
消費(fèi)者接受消息:
1. 消費(fèi)者連接到RabbitMQ Broker赵哲,建立一個(gè)連接(Connection),開啟一個(gè)信道(Channel)
2. 消費(fèi)者向RabbitMQ Broker請(qǐng)求消費(fèi)相應(yīng)隊(duì)列中的消息君丁,可能會(huì)設(shè)置相應(yīng)的回調(diào)函數(shù)枫夺,以及做一些準(zhǔn)備工作
3. 等待RabbitMQ Broker回應(yīng)并投遞相應(yīng)隊(duì)列中的消息,消費(fèi)者接收消息
4. 消費(fèi)者確認(rèn)(ack)接收到的消息
5. RabbitMQ從隊(duì)列中刪除相應(yīng)已經(jīng)被確認(rèn)的消息绘闷。
6. 關(guān)閉信道
7. 關(guān)閉連接
生產(chǎn)者和消費(fèi)者都需要和RabbitMQ Broker建立連接橡庞,這個(gè)連接就是一條TCP連接,也就是Connection印蔗。建立之后可以創(chuàng)建一個(gè)AMQP信道(Channel)扒最,每個(gè)信道都會(huì)被指派一個(gè)唯一的ID,信道時(shí)建立在Connection之上的虛擬連接华嘹,RabbitMQ處理的每條AMQP指令都是通過(guò)信道完成的吧趣。RabbitMQ采用了類似NIO的做法,TCP連接復(fù)用減少開銷耙厚。
AMQP協(xié)議
本身包含三層:
Module Layer:位于協(xié)議最高層强挫,主要定義了一些供客戶端調(diào)用的命令,客戶端可以利用這些命令實(shí)現(xiàn)自己的業(yè)務(wù)邏輯薛躬。例如客戶端可以使用Queue.Declare命令聲明一個(gè)隊(duì)列或者使用Basic.Consume訂閱消費(fèi)一個(gè)隊(duì)列中的消息俯渤。
Session Layer:位于中間層,主要負(fù)責(zé)將客戶端命令發(fā)送給服務(wù)器泛豪,再將服務(wù)器的應(yīng)答返回給客戶端稠诲,主要為客戶端與服務(wù)器之間的通信提供可靠性同步機(jī)制和錯(cuò)誤處理侦鹏。
Transport Layer:位于最底層诡曙,主要傳輸二進(jìn)制數(shù)據(jù)流,提供幀的處理略水、信道復(fù)用价卤、錯(cuò)誤檢測(cè)和數(shù)據(jù)表示等。
AMQP說(shuō)到底還是一個(gè)通信協(xié)議渊涝,通信協(xié)議都會(huì)涉及報(bào)文交互慎璧,從low-level來(lái)說(shuō)床嫌,AMQP是應(yīng)用層協(xié)議,其填充于TCP協(xié)議層的數(shù)據(jù)部分胸私。從high-level來(lái)說(shuō)厌处,AMQP是通過(guò)協(xié)議命令進(jìn)行交互的。AMQP協(xié)議可以看作一系列結(jié)構(gòu)化命令的集合岁疼,這里的命令代表一種操作阔涉。
生產(chǎn)消息
ConnectionFactory創(chuàng)建Connection
Connection創(chuàng)建Channel,Channel聲明交換器(channel.exchangeDeclare)和隊(duì)列(channel.queueDeclare)
exchangeDeclare方法
參數(shù)說(shuō)明:
exchange:交換器名稱
type:交換器類型捷绒,fanout瑰排、direct、topic
durable:設(shè)置是否持久化暖侨,true時(shí)持久化
autoDelete:設(shè)置是否自動(dòng)刪除椭住。與這個(gè)交換器綁定的隊(duì)列或者交換器都與此解綁。
internal:設(shè)置是否內(nèi)置交換器字逗,true是內(nèi)置交換器客戶端程序無(wú)法直接發(fā)送消息到這個(gè)交換器京郑,只能通過(guò)交換器路由到交換器這種方式
argument:其他一些結(jié)構(gòu)化參數(shù),如atlernate-exchange
queueDeclare方法
不帶參數(shù)的queueDeclare方法默認(rèn)創(chuàng)建一個(gè)由RabbitMQ命名的(類似amq.gen-Lhfjakjhdfawef2ij的匿名隊(duì)列)葫掉、排他的傻挂、自動(dòng)刪除的、非持久化的隊(duì)列挖息。
參數(shù)說(shuō)明:
queue:隊(duì)列名稱
durable:設(shè)置是否持久化
exclusive:設(shè)置是否排他金拒。true為排他,則該隊(duì)列僅對(duì)首次聲明它的連接可見套腹,并在斷開連接時(shí)自動(dòng)刪除绪抛。注意三點(diǎn):排他隊(duì)列基于連接,不同信道是可以同時(shí)訪問的电禀。首次是指連接若已經(jīng)聲明排他隊(duì)列其他連接不允許創(chuàng)建同名排他隊(duì)列幢码。即使該隊(duì)列持久化,一旦連接關(guān)閉或者客戶端退出都會(huì)自動(dòng)刪除尖飞。
autoDelete:自動(dòng)刪除
argument:設(shè)置隊(duì)列其他參數(shù)症副,如:x-message-ttl、x-expires
queueBind方法
將隊(duì)列和交換器綁定的方法
參數(shù)說(shuō)明:
queue:隊(duì)列名稱
exchange:交換器名稱
routingKey:用來(lái)綁定隊(duì)列和交換器的路由鍵
argument:頂一個(gè)綁定的一些參數(shù)
exchangeBind方法
將交換器和隊(duì)列綁定的方法
發(fā)送消息 basicPublish 方法
channel.basicPublish(
exchangeName,
routingKey,
new AMQP.BasicProperties.Builder()
.contentType("text/plain")
.deliveryMode(2)
.priority(1)
.userId("hidden")
.header(new HashMap<String, Object>())
.expiration("60000")
.build() ,
messageBodyBytes
);
消費(fèi)消息
RabbitMQ的消費(fèi)模式分為兩種政基,推(Push)和拉(Pull)贞铣。推模式采用Basic.Consume,拉模式調(diào)用Basic.Get進(jìn)行消費(fèi)
推模式
推模式接收消息一般通過(guò)實(shí)現(xiàn)Consumer接口或者繼承DefaultConsumer類來(lái)實(shí)現(xiàn)沮明。當(dāng)調(diào)用與Consumer相關(guān)API方法時(shí)辕坝,不同的訂閱采用不同的消費(fèi)者標(biāo)簽(consumerTag)來(lái)區(qū)分彼此,在同一個(gè)Channel中的消費(fèi)者也需要通過(guò)唯一的消費(fèi)者標(biāo)簽以作區(qū)分荐健。
basicConsume方法參數(shù)如下:
queue:隊(duì)列名稱
autoAck:設(shè)置是否自動(dòng)確認(rèn)酱畅,建議false
consumerTag: 消費(fèi)者標(biāo)簽琳袄,區(qū)分多個(gè)消費(fèi)者
noLocal:設(shè)置true表示不能將同一個(gè)Connection中生產(chǎn)者發(fā)送的消息發(fā)送給這個(gè)Connection中的消費(fèi)者
exclusive:是否排他
arguments:消費(fèi)者其他參數(shù)
callback:消費(fèi)者的回調(diào)函數(shù),用來(lái)處理RabbitMQ推送過(guò)來(lái)的消息纺酸。比如DefaultConsumer窖逗,使用時(shí)需要客戶端重寫(override)其中的方法。
拉模式
通過(guò)channel.basicGet方法可以單條獲取消息餐蔬,其返回值時(shí)GetReponse滑负。
GetResponse response = channel.basicGet(QUEUE_NAME, false);
System.out.println(new String(reponse.getBody()));
channel.basicAck(reponse.getEnvelop().getDeliveryTag(),false);
為了保證消息可靠到達(dá)消費(fèi)者,RabbitMQ提供了消息確認(rèn)機(jī)制(message acknowledge)用含。消費(fèi)者在訂閱隊(duì)列時(shí)可以指定autoAck參數(shù)矮慕,表示是否需要顯示應(yīng)答才會(huì)刪除消息。未回復(fù)確認(rèn)時(shí)啄骇,RabbitMQ會(huì)一直等待痴鳄,除非消費(fèi)該消息的消費(fèi)者連接已經(jīng)斷開。消費(fèi)者頁(yè)可以調(diào)用channel.basicReject方法拒絕單個(gè)消息缸夹。使用channel.basicNack方法批量拒絕消息痪寻。
RabbitMQ進(jìn)階
mandatory 和 immediate 是 channel.basicPublish 方法中的兩個(gè)參數(shù),它們都有當(dāng)消息傳遞過(guò)程中不可達(dá)目的地時(shí)將消息返回給生產(chǎn)者的功能虽惭。
mandatory參數(shù)為true橡类,交換機(jī)無(wú)法根據(jù)自身類型和路由鍵找到一個(gè)符合條件的隊(duì)列會(huì)返回給生產(chǎn)者,如果為false芽唇,則消息被丟棄顾画。
immediate參數(shù)為true,如果交換器將消息路由到隊(duì)列時(shí)發(fā)現(xiàn)隊(duì)列上不存在消費(fèi)者匆笤,則這條消息不會(huì)存入隊(duì)列中研侣。所有匹配的隊(duì)列都沒有消費(fèi)者時(shí),該消息返回生產(chǎn)者炮捧。3.0去除
備份交換器(alternate exchange)庶诡,生產(chǎn)者在發(fā)送消息的時(shí)候如果不設(shè)置mandatory參數(shù),那么消息在未被路由的情況下會(huì)丟失咆课,如果設(shè)置了mandatory末誓,需要添加ReturnListener邏輯。但是可以使用備份交換器將未被路由的消息存儲(chǔ)在RabbitMQ中书蚪,需要時(shí)再去處理喇澡。
Map<String,Object> args = new HashMap<String,Object>();
args.put("alternate-exchange","myAe");
args.put("x-message-ttl",6000); // 設(shè)置過(guò)期時(shí)間
channel.exchangeDeclare("normalExchange","direct",true,false,args);
channel.exchangeDeclare("myAe","fanout",true,false,null);
channel.queueDeclare("normalQueue",true,false,false,null);
channel.queueBind("normalQueue","normalExchange","normalKey");
channel.queueDeclare("unroutedQueue",true,false,false,null);
channel.queueBind("unroutedQueue","myAe","");
RabbitMQ可以對(duì)消息和隊(duì)列設(shè)置TTL(Time To Live)過(guò)期時(shí)間。
目前有兩種方法設(shè)置消息的TTL善炫,第一種方法通過(guò)隊(duì)列屬性設(shè)置撩幽,隊(duì)列中所有的消息都有相同的過(guò)期時(shí)間。第二種方法時(shí)對(duì)消息本身進(jìn)行單獨(dú)設(shè)置箩艺,每條消息的TTL可以不同窜醉。如果兩種方法一起使用,則消息的TTL以兩者較小的那個(gè)數(shù)值為準(zhǔn)艺谆。消息在隊(duì)列中生存時(shí)間一旦超過(guò)設(shè)置的TTL值榨惰,就會(huì)變成死信(Dead Message)。
對(duì)于設(shè)置隊(duì)列TTL屬性的方法静汤,一旦消息過(guò)期琅催,就會(huì)從隊(duì)列中抹去,而在第二種方法中虫给,即使消息過(guò)期藤抡,也不會(huì)馬上從隊(duì)列中抹去,因?yàn)槊織l消息是否過(guò)期時(shí)在即將投遞到消費(fèi)者之前判定的抹估。
第一種方法中缠黍,隊(duì)列中已經(jīng)過(guò)期的消息肯定在隊(duì)列的頭部,RabbitMQ只要定期從隊(duì)頭開始掃描是否有過(guò)期的消息即可药蜻。第二種方法里瓷式,每條消息的過(guò)期時(shí)間不同,如果要?jiǎng)h除所有過(guò)期消息必須要掃描整個(gè)隊(duì)列语泽,所以等到消息被消費(fèi)的時(shí)候再判定是否過(guò)期在進(jìn)行刪除贸典。
死信隊(duì)列(DLX),全稱是Dead-Letter-Exchange踱卵。
消息變成死信有下面幾個(gè)原因:
消息被拒絕(Basic.Reject/Basic.Nack)廊驼,并設(shè)置requeue參數(shù)為false;
消息過(guò)期
隊(duì)列達(dá)到最大長(zhǎng)度
channel.exchangeDeclare("dlx_exchange","direct");
Map<String,Object> args = new HashMap<String,Object>();
args.put("x-dead-letter-exchange","dlx_exchange");
// 可以為DLX指定路由鍵惋砂,如果沒有特殊指定蔬充,則使用原隊(duì)列的路由鍵
args.put("x-dead-letter-routing-key","dlx-routing-key");
channel.queueDeclare("myqueue",false,false,false,args);
通過(guò)設(shè)定TTL和DLX模擬出延遲隊(duì)列。消費(fèi)者訂閱的是死信隊(duì)列而不是正常隊(duì)列班利。
可以通過(guò)設(shè)置隊(duì)列的x-max-priority參數(shù)來(lái)實(shí)現(xiàn)優(yōu)先級(jí)隊(duì)列饥漫,優(yōu)先級(jí)高的消息具備優(yōu)先被消費(fèi)的特權(quán)。
持久化
持久化可以提高RabbitMQ的可靠性罗标,以防在異常情況(重啟庸队,關(guān)閉,宕機(jī)等)下的數(shù)據(jù)丟失闯割。持久化分為三個(gè)部分:交換器的持久化彻消、隊(duì)列的持久化、消息的持久化宙拉”錾校可以引入鏡像隊(duì)列機(jī)制。
生產(chǎn)者確認(rèn)
消息生產(chǎn)者消息發(fā)送之后,默認(rèn)時(shí)不會(huì)返回任何信息給生產(chǎn)者煌贴。為了解決這個(gè)問題御板,提供了兩種解決方式:
通過(guò)事務(wù)機(jī)制實(shí)現(xiàn)
通過(guò)發(fā)送方確認(rèn)(publisher confirm)機(jī)制實(shí)現(xiàn)
RabbitMQ客戶端中與事務(wù)機(jī)制相關(guān)的方法有三個(gè):channel.txSelect(設(shè)置為事務(wù)模式)、channel.txCommit(提交事務(wù))和channel.txRollback(回滾事務(wù))牛郑。事務(wù)會(huì)很大影響RabbitMQ的消息吞吐量怠肋。
輕量級(jí)的方式:發(fā)送方確認(rèn)機(jī)制。生產(chǎn)者將信道設(shè)置成confirm(確認(rèn))模式淹朋,一旦信道進(jìn)入confirm模式笙各,所有該信道上面發(fā)布的消息都會(huì)被指派一個(gè)唯一的ID(從1開始),一旦消息被投遞到所有匹配隊(duì)列之后础芍,RabbitMQ就發(fā)送一個(gè)確認(rèn)(Basic.Ack)給生產(chǎn)者(包含消息的唯一ID)杈抢,這就使得生產(chǎn)者知曉消息已經(jīng)正確的到達(dá)了目的地。如果消息和隊(duì)列是可持久化的仑性,那么確認(rèn)消息就會(huì)在消息寫入磁盤后發(fā)出惶楼。RabbitMQ回傳給生產(chǎn)者的確認(rèn)消息中的deliveryTag包含了待確認(rèn)消息的序號(hào),此外RabbitMQ也可以設(shè)置channel.basicAck方法中的multiple參數(shù)虏缸,表示這個(gè)序號(hào)之前的所有消息都已經(jīng)得到了處理鲫懒。
事務(wù)機(jī)制是同步的,會(huì)阻塞發(fā)送端刽辙。發(fā)送方確認(rèn)機(jī)制時(shí)異步的窥岩,可以通過(guò)回調(diào)方法來(lái)處理該確認(rèn)消息。建議使用異步confirm模式宰缤,在Channel接口中提供的addConfirmListener方法可以添加ConfirmListener這個(gè)回調(diào)接口颂翼,包含兩個(gè)方法:handleAck和handleNack。我們要為每個(gè)信道維護(hù)一個(gè)“unconfirm”的消息序號(hào)集合慨灭,每發(fā)送一條朦乏,集合中元素加1,回調(diào)時(shí)如果multiple為false就一條氧骤,為true時(shí)多條呻疹。
消費(fèi)端要點(diǎn)
消費(fèi)端有幾點(diǎn)要注意:
消息分發(fā)
消息順序性
啟用QueueingConsumer
消息分發(fā)默認(rèn)時(shí)輪詢(round-robin),可以加入流量控制筹陵,使用channel.basicQos(int prefetchCount)刽锤,允許限制信道上的消費(fèi)者所能保持的最大未確認(rèn)消息數(shù)量。Basic.Qos的使用對(duì)于拉模式的消費(fèi)方式無(wú)效朦佩。
消息順序性是指消費(fèi)者消費(fèi)到的消息順序和生產(chǎn)者發(fā)布的順序是一致的并思。沒有高級(jí)特性的情況下,默認(rèn)能夠保持順序性语稠。
棄用QueueingConsumer宋彼,建議使用繼承DefaultConsumer的方式。
消息傳輸保障
消息中間件的消息傳輸保障分為三個(gè)層級(jí):
At most once:最多一次。消息可能會(huì)丟失输涕,但絕不會(huì)重復(fù)傳輸(RabbitMQ支持)
At least once:最少一次音婶,消息絕不會(huì)丟失,但可能會(huì)重復(fù)傳輸(RabbitMQ支持)
Exactly once:恰好一次占贫,消息肯定會(huì)被傳輸一次且僅傳輸一次
RabbitMQ運(yùn)維
集群搭建
RabbitMQ集群中的所有節(jié)點(diǎn)都會(huì)備份所有的元數(shù)據(jù)信息桃熄,包括:
隊(duì)列元數(shù)據(jù):隊(duì)列的名稱以及屬性
交換器:交換器的名稱以及屬性
綁定關(guān)系元數(shù)據(jù):交換器與隊(duì)列或者交換器與交換器之間的綁定關(guān)系
vhost元數(shù)據(jù):為vhost內(nèi)的隊(duì)列先口、交換器和綁定命名空間及安全屬性
在RabbitMQ集群中創(chuàng)建隊(duì)列型奥,集群只會(huì)在單個(gè)節(jié)點(diǎn)而不是在所有節(jié)點(diǎn)上創(chuàng)建隊(duì)列的進(jìn)程并包含完整的隊(duì)列(元數(shù)據(jù)、狀態(tài)碉京、內(nèi)容)厢汹。這樣只有隊(duì)列的宿主節(jié)點(diǎn)(所有者)節(jié)點(diǎn)知道隊(duì)列的所有信息,所有其他非所有者只知道隊(duì)列的元數(shù)據(jù)和指向該隊(duì)列存在的那個(gè)節(jié)點(diǎn)的指針谐宙。節(jié)點(diǎn)崩潰時(shí)烫葬,該節(jié)點(diǎn)的隊(duì)列進(jìn)程和關(guān)聯(lián)的綁定都會(huì)消失,附加在那些隊(duì)列上的消費(fèi)者也會(huì)丟失其所訂閱的信息凡蜻,并且任何匹配該隊(duì)列綁定信息的新消息也會(huì)丟失搭综。
不同于隊(duì)列那樣有自己的進(jìn)程,交換器實(shí)際上只是一個(gè)名稱和綁定列表划栓。當(dāng)消息發(fā)布到交換器時(shí)兑巾,實(shí)際上是由所連接的信道將消息上的路由鍵同交換器的綁定列表進(jìn)行比較,然后再路由消息忠荞。當(dāng)創(chuàng)建一個(gè)新的交換器時(shí)蒋歌,RabbitMQ所要做的就是將綁定列表添加到集群中的所有節(jié)點(diǎn)上。這樣每個(gè)節(jié)點(diǎn)上的每個(gè)信道都可以訪問到新的交換器委煤。
多機(jī)多節(jié)點(diǎn)是指每臺(tái)物理機(jī)器都安裝了RabbitMQ堂油,應(yīng)當(dāng)只在局域網(wǎng)內(nèi)使用,廣域網(wǎng)應(yīng)當(dāng)使用Federation或者Shovel碧绞。
命令行主要使用 rabbitmqctl join_cluster {nodename} 加入集群節(jié)點(diǎn)
rabbitmqctl forget_cluester_node {nodename}
RabbitMQ要求集群中至少有一個(gè)磁盤節(jié)點(diǎn)府框,其他節(jié)點(diǎn)可以是內(nèi)存節(jié)點(diǎn)。當(dāng)節(jié)點(diǎn)加入或者離開集群的時(shí)候讥邻,它們必須將變更通知到至少一個(gè)磁盤節(jié)點(diǎn)迫靖。如果唯一一個(gè)磁盤節(jié)點(diǎn)崩潰,集群可以繼續(xù)收發(fā)消息计维,但是不能執(zhí)行創(chuàng)建隊(duì)列袜香、交換器、綁定關(guān)系鲫惶、用戶蜈首,以及更改權(quán)限、添加和刪除集群節(jié)點(diǎn)的操作。所以集群應(yīng)該保障有兩個(gè)或者多個(gè)磁盤節(jié)點(diǎn)的存在欢策。
/usr/lib64/erlang/erts-8.0.3/bin/beam.smp -W w -A 64 -P 1048576 -t 5000000 -stbt db -zdbbl 32000 -K true -B i -- -root /usr/lib64/erlang -progname erl -- -home /root -- -pa /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.6/ebin -noshell -noinput -s rabbit boot -sname rabbit@localhost -boot start_sasl -kernel inet_default_connect_options [{nodelay,true}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit error_logger {file,"/var/log/rabbitmq/rabbit@localhost.log"} -rabbit sasl_error_logger {file,"/var/log/rabbitmq/rabbit@localhost-sasl.log"} -rabbit enabled_plugins_file "/etc/rabbitmq/enabled_plugins" -rabbit plugins_dir "/usr/lib/rabbitmq/lib/rabbitmq_server-3.6.6/plugins" -rabbit plugins_expand_dir "/var/lib/rabbitmq/mnesia/rabbit@localhost-plugins-expand" -os_mon start_cpu_sup false -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/var/lib/rabbitmq/mnesia/rabbit@localhost" -kernel inet_dist_listen_min 25672 -kernel inet_dist_listen_max 25672 status
RabbitMQ的日志默認(rèn)存放在 $RABBITMQ_HOME/var/log/rabbitmq文件夾內(nèi)吆寨。一般會(huì)創(chuàng)建兩個(gè)日志文件:RABBITMQ_NODENAME-sasl.log 和 RABBITMQ_NODENAME.log兩個(gè)日志文件。SASL(System Application Support Libraries踩寇,系統(tǒng)應(yīng)用程序支持庫(kù))是庫(kù)的集合啄清,RabbitMQ在記錄Erlang相關(guān)信息會(huì)寫入這個(gè)文件,例如可以找到Erlang的崩潰報(bào)告俺孙。后者就會(huì)有RabbitMQ的應(yīng)用服務(wù)的日志辣卒。
集群遷移
集群故障例如IDC整體停電、網(wǎng)線被挖斷等睛榄,這時(shí)候需要通過(guò)集群遷移重新建立一個(gè)新的集群荣茫。
RabbitMQ集群遷移包括元數(shù)據(jù)重建、數(shù)據(jù)遷移场靴、以及與客戶端連接的切換啡莉。
元數(shù)據(jù)重建是指新的集群中創(chuàng)建原集群的隊(duì)列、交換器旨剥、綁定關(guān)系咧欣、vhost、用戶轨帜、權(quán)限和Parameter等數(shù)據(jù)信息魄咕。元數(shù)據(jù)重建之后才可以將原集群中的消息以及客戶端連接遷移過(guò)來(lái)。
可以在原集群管理界面上點(diǎn)擊 “Download broker definitions” 下載集群元數(shù)據(jù)信息文件
集群監(jiān)控
RabbitMQ Management插件提供了管理界面阵谚,也提供了HTTP API接口來(lái)調(diào)用提供監(jiān)控?cái)?shù)據(jù)蚕礼。
跨越集群限制
Federation(聯(lián)邦交換器)
Federation插件可以讓多個(gè)交換器或者多個(gè)隊(duì)列進(jìn)行聯(lián)邦,一個(gè)聯(lián)邦交換器(federated exchange)或者一個(gè)聯(lián)邦隊(duì)列(federated queue)接收上游(upstream)的消息梢什,這里的上游時(shí)指位于其他Broker上的交換器或者隊(duì)列聯(lián)邦交換器能夠?qū)⒃景l(fā)送給上游交換器(upstream exchange)的消息路由到本地的某個(gè)隊(duì)列中奠蹬;聯(lián)邦隊(duì)列則允許一個(gè)本地消費(fèi)者接收到來(lái)自上游隊(duì)列(upstream queue)的消息。
Shovel
與Federation具備的數(shù)據(jù)轉(zhuǎn)發(fā)功能類似嗡午,Shovel能夠可靠囤躁、持續(xù)的從一個(gè)Broker的隊(duì)列拉取數(shù)據(jù)并轉(zhuǎn)發(fā)只另一個(gè)Broker的交換器。實(shí)際上是基于AMQP協(xié)議的轉(zhuǎn)發(fā)器荔睹。
Shovel可以部署在源端也可以部署在目的端狸演。有兩種方式可以部署Shovel:靜態(tài)方式(static)和動(dòng)態(tài)方式(dynamic)。靜態(tài)方式是指在RabbitMQ.config配置文件中設(shè)置僻他,動(dòng)態(tài)方式只指通過(guò)Runtime Parameter設(shè)置宵距。
當(dāng)集群消息堆積嚴(yán)重時(shí),可以通過(guò)Shovel將隊(duì)列中的消息移交給另一個(gè)集群吨拗,這是一備一的情況满哪。如果需要一備多婿斥,可以采用鏡像隊(duì)列或者引入Federation。
Shovel工作在Federation的更低一層哨鸭。監(jiān)獄Federation從一個(gè)交換器中轉(zhuǎn)發(fā)消息到另一個(gè)交換器(如果有必要可以確認(rèn)消息是否被轉(zhuǎn)發(fā))民宿,Shovel只是簡(jiǎn)單地從某個(gè)Broker上的隊(duì)列消費(fèi)消息,然后轉(zhuǎn)發(fā)消息到另一個(gè)Broker上的交換器而已像鸡。Shovel也可以再一臺(tái)單獨(dú)的服務(wù)器上去轉(zhuǎn)發(fā)消息活鹰,例如將一個(gè)隊(duì)列中的數(shù)據(jù)移動(dòng)到另一個(gè)隊(duì)列中。
RabbitMQ高階
存儲(chǔ)機(jī)制
持久化的消息在到達(dá)消息隊(duì)列時(shí)就被寫入到磁盤只估,如果可以志群,在內(nèi)存中也會(huì)保留一份備份。非持久化消息在內(nèi)存中仅乓,內(nèi)存緊張是會(huì)被換入磁盤赖舟。這些都是依靠持久層完成蓬戚。
持久層時(shí)一個(gè)邏輯上的概念夸楣,包含兩部分:隊(duì)列索引(rabbit_queue_index)和消息存儲(chǔ)(rabbit_msg_store)。前者負(fù)責(zé)維護(hù)隊(duì)列中落盤消息的信息子漩,包括消息的存儲(chǔ)地點(diǎn)豫喧,是否已經(jīng)被交付給消費(fèi)者,是否已經(jīng)被消費(fèi)者ack等幢泼。每個(gè)隊(duì)列都有這個(gè)信息紧显。后者則以鍵值對(duì)的形式存儲(chǔ)消息,它被所有隊(duì)列共享缕棵,在每個(gè)節(jié)點(diǎn)中有且只有一個(gè)孵班。技術(shù)層面上來(lái)說(shuō),rabbit_msg_store具體還分為msg_store_persistent(負(fù)責(zé)持久化消息招驴,重啟后消息不丟失)和msg_store_transient(負(fù)責(zé)非持久化消息篙程,重啟后消息丟失)。默認(rèn)在 /var/lib/mnesia/rabbit@hostname 路徑下包含 queues别厘、msg_store_persistent虱饿、msg_store_transient三個(gè)文件夾下,建議較小的消息存儲(chǔ)在rabbit_queue_index中触趴,而較大的消息存儲(chǔ)在rabbit_msg_store中氮发。消息大小界定可以通過(guò)queue_index_embed_msgs_below來(lái)配置,默認(rèn)大小為4096單位B冗懦。
通常隊(duì)列由rabbit_amqqueue_process和backing_queue兩部分組成爽冕,前者負(fù)責(zé)協(xié)議相關(guān)的消息處理,即接收生產(chǎn)者發(fā)布的消息披蕉、向消費(fèi)者交付消息颈畸、處理消息的確認(rèn)(包括生產(chǎn)端的confirm和消費(fèi)端的ack)等前塔。后者時(shí)消息存儲(chǔ)的具體形式和引擎,并向rabbit_amqqueue_process提供相關(guān)的接口以供調(diào)用承冰。
如果消息投遞的目的隊(duì)列是空的华弓,并且有消費(fèi)者訂閱了這個(gè)隊(duì)列,那么消息不會(huì)經(jīng)過(guò)隊(duì)列直接發(fā)送給消費(fèi)者困乒。如果無(wú)法直接投遞暫存入隊(duì)列寂屏。消息入隊(duì)后會(huì)隨著系統(tǒng)負(fù)載在隊(duì)列中不斷流動(dòng),狀態(tài)也不斷變化娜搂,可能處于4種狀態(tài):
alpha:消息內(nèi)容(消息體迁霎、屬性和headers)和消息索引都存儲(chǔ)在內(nèi)存中
beta:消息內(nèi)容保存在磁盤中,消息索引保存在內(nèi)存中
gamma:消息內(nèi)容保存在磁盤中百宇,消息索引保存在磁盤和內(nèi)存中
delta:消息內(nèi)容和索引都在磁盤上
普通的沒有設(shè)置優(yōu)先級(jí)和鏡像的隊(duì)列考廉,backing_queue的默認(rèn)實(shí)現(xiàn)時(shí)rabbit_variable_queue,其內(nèi)部通過(guò)5個(gè)子隊(duì)列Q1携御、Q2昌粤、Delta、Q3啄刹、Q4來(lái)體現(xiàn)消息的各個(gè)狀態(tài)涮坐。Q1,Q4只包含alpha狀態(tài)的消息誓军,Q2袱讹,Q3包含beta和gamma狀態(tài)的消息,Delta只包含delta狀態(tài)的消息昵时。一般情況下捷雕,消息按照Q1→Q2→Delta→Q3→Q4這樣順序步驟進(jìn)行流動(dòng)。
消費(fèi)者消息首先會(huì)對(duì)Q4獲取消息壹甥,如果Q4為空嘗試從Q3獲取救巷,如果Q3為空說(shuō)明隊(duì)列為空。
RabbitMQ從3.6.0開始引入惰性隊(duì)列(Lazy Queue)盹廷。惰性隊(duì)列盡可能地將消息存入磁盤中征绸,在消費(fèi)者消費(fèi)相應(yīng)消息會(huì)被加載到內(nèi)存,這是為了支持更長(zhǎng)的隊(duì)列俄占。default為默認(rèn)內(nèi)存模式管怠,lazy為惰性隊(duì)列模式:
args.put("x-queue-mode","lazy");
流控
RabbitMQ可以對(duì)內(nèi)存和磁盤使用量設(shè)置閾值,到達(dá)閾值時(shí)生產(chǎn)者會(huì)被阻塞直到對(duì)應(yīng)項(xiàng)恢復(fù)正常缸榄。2.8.0還引入了流控(Flow Control)機(jī)制確保穩(wěn)定性渤弛,為了避免消息發(fā)送速率過(guò)快而導(dǎo)致服務(wù)器難以支撐的情形。
一個(gè)連接(Connection)觸發(fā)流控時(shí)會(huì)處于“flow”的狀態(tài)甚带,也就意味著這個(gè)Connection的狀態(tài)每秒在blocked和unblocked之間來(lái)回切換數(shù)次她肯,將消息發(fā)送的速率控制在服務(wù)器能夠支持的范圍之內(nèi)佳头。
鏡像隊(duì)列
引入鏡像隊(duì)列(Mirror Queue)的機(jī)制,可以將隊(duì)列鏡像到集群中的其他Broker節(jié)點(diǎn)之上晴氨,如果集群中的一個(gè)節(jié)點(diǎn)失效了康嘉,隊(duì)列能自動(dòng)地切換到鏡像的另一個(gè)節(jié)點(diǎn)上以保證服務(wù)的可用性。每一個(gè)配置鏡像的隊(duì)列都包含一個(gè)主節(jié)點(diǎn)(master)和若干個(gè)從節(jié)點(diǎn)(slave)籽前,如果master失效亭珍,slave加入時(shí)間最長(zhǎng)的會(huì)提升為master。發(fā)送到鏡像隊(duì)列的所有消息會(huì)被同時(shí)發(fā)往master和其他所有的slave枝哄。除了發(fā)送消息(Basic.Publish)外所有動(dòng)作都只會(huì)想master發(fā)送肄梨,然后由master將命令執(zhí)行的結(jié)果廣播給各個(gè)slave。
消費(fèi)者與slave建立連接消費(fèi)時(shí)實(shí)質(zhì)上都是從master上獲取消息挠锥,只不過(guò)看似從slave上消費(fèi)而已众羡。例如消費(fèi)者與slave建立了TCP連接后執(zhí)行Basic.Get操作,由slave轉(zhuǎn)發(fā)給master蓖租,再由master準(zhǔn)備好數(shù)據(jù)返回給slave粱侣,投遞給消費(fèi)者。這里的master和slave針對(duì)隊(duì)列而言菜秦,隊(duì)列可以均勻地散落在集群的各個(gè)Broker節(jié)點(diǎn)中以達(dá)到負(fù)載均衡地目的甜害,真正的負(fù)載還是針對(duì)實(shí)際的物理機(jī)器而言,而不是內(nèi)存中駐留的隊(duì)列進(jìn)程球昨。
網(wǎng)絡(luò)分區(qū)
網(wǎng)絡(luò)分區(qū)的恢復(fù)
首先選一個(gè)最信任的partition,Mnesia使用該partition中的狀態(tài)眨攘,其他partitions中發(fā)生的變化都將丟失主慰。
停止其他partitions中的所有nodes,之后重啟這些nodes鲫售。當(dāng)這些nodes重新加入cluster后將從信任的partition恢復(fù)狀態(tài)共螺。
最后還需重啟信任的partition中的所有nodes以清除network partition的警告信息
Rabbitmq自動(dòng)處理網(wǎng)絡(luò)分區(qū)的3種模式
RabbitMQ提供了3種自動(dòng)處理network partitions的方式:默認(rèn)為ignore模式,也即需要手工處理
pause-minority mode:暫停少數(shù)模式情竹;
pause-if-all-down mode:暫停-如果全部停止模式
autoheal mode:自動(dòng)愈合模式
pause-minority mode:暫停少數(shù)模式
在pause-minority模式下藐不,察覺其他nodes down掉后,RabbitMQ將自動(dòng)暫停認(rèn)為自己是少數(shù)派的 nodes(例如小于或等于總nodes數(shù)的一半)秦效,network partition一旦發(fā)生雏蛮,“少數(shù)派”的nodes將立刻暫停,直至partition結(jié)束后重新恢復(fù)阱州。這可以保證在network partition發(fā)生時(shí)挑秉,至多只有一個(gè)partition中的nodes繼續(xù)運(yùn)行。(犧牲可用性保證一致性)
若所有分區(qū)的nodes個(gè)數(shù)都小于總nodes個(gè)數(shù)一半苔货,則意味著所有分區(qū)的nodes都會(huì)認(rèn)為自己是少數(shù)派犀概,即所有nodes都將暫停
pause-if-all-down mode:暫停-如果全部停止模式
http://www.rabbitmq.com/partitions.html
autoheal模式
在autoheal模式下一旦發(fā)生了partition立哑,RabbitMQ將自動(dòng)確定一個(gè)優(yōu)勝partition,然后重啟所有不在優(yōu)勝partition中的nodes姻灶。
獲勝的partition為擁有最多客戶端連接的partition(若連接相同則為節(jié)點(diǎn)最多的partition)铛绰。
關(guān)于自動(dòng)處理partitions的設(shè)置在配置文件的cluster_partition_handling參數(shù)中進(jìn)行。
各自的適用場(chǎng)景
network partitions自動(dòng)處理并不能保證cluster不出任何問題产喉。
一般來(lái)說(shuō)可作如下選擇:
ignore:若網(wǎng)絡(luò)非吵窍梗可靠。所有nodes在同一機(jī)架运吓,通過(guò)交換機(jī)連接团秽,該交換機(jī)也是通往外部網(wǎng)絡(luò)的出口。在cluster的某一部分故障時(shí)不希望其余部分受影響晦譬“唐唬或者cluster只有兩個(gè)node。
pause_minority:網(wǎng)絡(luò)較不可靠敛腌。cluster處于EC2的3個(gè)AZ中卧土,假定每次至多只有其中一個(gè)AZ故障,想要剩余的AZ繼續(xù)提供服務(wù)而故障的AZ中的nodes在AZ恢復(fù)后重新自動(dòng)加入到cluster像樊。
autoheal:網(wǎng)絡(luò)很不可靠尤莺。與數(shù)據(jù)完整性相比更關(guān)注服務(wù)的持續(xù)性。cluster只有兩個(gè)node生棍。
RabbitMQ擴(kuò)展
消息追蹤
RabbitMQ可以使用Firehose來(lái)實(shí)現(xiàn)消息追蹤颤霎,F(xiàn)irehose的原理是將生產(chǎn)者投遞給RabbitMQ的消息或者RabbitMQ投遞給消費(fèi)者的消息按照指定的格式發(fā)送到默認(rèn)的交換器上,這個(gè)默認(rèn)的交換器名稱為:amp.rabbitmq.trace涂滴,它是一個(gè)topic類型的交換器友酱。發(fā)送到這個(gè)交換器上的消息的路由鍵為publish.{exchangename}和deliver.{queuename},其中exchange和queuename為交換器和隊(duì)列的名稱柔纵,分別對(duì)應(yīng)生產(chǎn)者投遞到交換器的消息和消費(fèi)者從隊(duì)列中獲取的消息缔杉。
使用rabbitmqctl trace_on [-p vhost]開啟Firehose命令
rabbitmq_tracing插件相當(dāng)于Firehose的GUI版本,會(huì)對(duì)流入流出的消息進(jìn)行封裝搁料,然后將封裝后的消息日志存入相應(yīng)的trace文件中或详。
使用rabbitmq-plugins enable rabbitmq_tracing命令來(lái)啟動(dòng)插件。
負(fù)載均衡
除了應(yīng)用內(nèi)部實(shí)現(xiàn)負(fù)載均衡外郭计,還可以使用HAProxy霸琴、Keepalived、LVS拣宏。
HAProxy提供高可用沈贝、負(fù)載均衡以及基于TCP和HTTP應(yīng)用的代理,支持虛擬主機(jī)勋乾。HAProxy實(shí)現(xiàn)來(lái)一種事件驅(qū)動(dòng)宋下、單一進(jìn)程模型嗡善,支持非常大的并發(fā)連接數(shù)。
Keepalived通過(guò)自身健康檢查学歧、資源接管功能做高可用(雙機(jī)熱備)罩引,實(shí)現(xiàn)故障轉(zhuǎn)移。
Keepalived采用VRRP(Virtual Router Redundancy Protocol枝笨,虛擬路由冗余協(xié)議)袁铐,以軟件形式實(shí)現(xiàn)服務(wù)的熱備功能。通常情況下是將兩臺(tái)Linux服務(wù)器組成一個(gè)熱備組(Master和Backup)横浑,同一時(shí)間內(nèi)熱備組只有一臺(tái)主服務(wù)器Master提供服務(wù)剔桨,同時(shí)Master會(huì)虛擬出一個(gè)公用的虛擬IP地址,簡(jiǎn)稱VIP徙融。這個(gè)VIP只存在于Master上并對(duì)外提供服務(wù)洒缀。如果Keepalived檢測(cè)到Master宕機(jī)或者服務(wù)故障,備份服務(wù)器Backup會(huì)自動(dòng)接管VIP并成為Master欺冀,Keepalived將原Master從熱備組中移除树绩。當(dāng)原Master恢復(fù)后,會(huì)自動(dòng)加入到熱備組隐轩,默認(rèn)再搶占成為Master啟到故障轉(zhuǎn)移的功能饺饭。
LVS是Linux Virtual Server的簡(jiǎn)稱,是4層負(fù)載均衡职车,建立在OSI模型的傳輸層上瘫俊。支持TCP/UDP的負(fù)載均衡非常高效。
LVS主要由3部分組成
負(fù)載調(diào)度器(Load Balancer/Director):它是整個(gè)集群對(duì)外面的前端機(jī)提鸟,負(fù)責(zé)將客戶的請(qǐng)求發(fā)送到一組服務(wù)器上執(zhí)行军援,而客戶認(rèn)為服務(wù)是來(lái)自一個(gè)IP地址(VIP)上的
服務(wù)器池(Server Pool/RealServer):一組真正執(zhí)行客戶端請(qǐng)求的服務(wù)器
共享存儲(chǔ)(Shared Storage):它為服務(wù)器提供來(lái)一個(gè)共享的存儲(chǔ)區(qū),這樣很容易使服務(wù)器池?fù)碛邢嗤膬?nèi)容称勋,提供相同的服務(wù)。
目前LVS的負(fù)載均衡地方式也分為三種涯竟。
VS/NAT:Virtual Server via Network Address Translation的簡(jiǎn)稱赡鲜。是一種最簡(jiǎn)單的方式,所有的RealServer只需要將自己的網(wǎng)關(guān)指向Director即可庐船。但是一個(gè)Director可以帶動(dòng)的RealServer比較有限
VS/TUN:Virtual Server via IP Tunneling的簡(jiǎn)稱银酬。IP隧道是將一個(gè)IP報(bào)文封裝在另一個(gè)IP報(bào)文的技術(shù)。這可以是目標(biāo)為一個(gè)IP地址的數(shù)據(jù)報(bào)文能夠被封裝和轉(zhuǎn)發(fā)到另一個(gè)IP地址筐钟,也稱之為IP封裝技術(shù)(IP encapsulation)
VS/DR:Virtual Server via Direct Routing的簡(jiǎn)稱揩瞪。這是通過(guò)改寫報(bào)文中的MAC地址部分來(lái)實(shí)現(xiàn),Director和RealServer必須在物理上由一個(gè)網(wǎng)卡通過(guò)不間斷的局域網(wǎng)相連篓冲。RealServer上綁定的VIP配置在各自的Non-ARP的網(wǎng)絡(luò)設(shè)備上(如lo或tunl)李破,Director的VIP地址對(duì)外空間宠哄,而RealServer的VIP對(duì)外不可見。RealServer的地址既可以是內(nèi)部地址嗤攻,也可以是真實(shí)地址