RabbitMQ實(shí)戰(zhàn)

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)者步驟
消費(fèi)者步驟

生產(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í)地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末毛嫉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子妇菱,更是在濱河造成了極大的恐慌承粤,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闯团,死亡現(xiàn)場(chǎng)離奇詭異辛臊,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)房交,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門彻舰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人涌萤,你說(shuō)我怎么就攤上這事淹遵。” “怎么了负溪?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵透揣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我川抡,道長(zhǎng)辐真,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任崖堤,我火速辦了婚禮侍咱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘密幔。我一直安慰自己楔脯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布胯甩。 她就那樣靜靜地躺著昧廷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪偎箫。 梳的紋絲不亂的頭發(fā)上木柬,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音淹办,去河邊找鬼眉枕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的速挑。 我是一名探鬼主播谤牡,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梗摇!你這毒婦竟也來(lái)了拓哟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤伶授,失蹤者是張志新(化名)和其女友劉穎断序,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糜烹,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡违诗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疮蹦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诸迟。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖愕乎,靈堂內(nèi)的尸體忽然破棺而出阵苇,到底是詐尸還是另有隱情,我是刑警寧澤感论,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布绅项,位于F島的核電站,受9級(jí)特大地震影響比肄,放射性物質(zhì)發(fā)生泄漏快耿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一芳绩、第九天 我趴在偏房一處隱蔽的房頂上張望掀亥。 院中可真熱鬧,春花似錦妥色、人聲如沸搪花。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鳍侣。三九已至,卻和暖如春吼拥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背线衫。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工凿可, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓枯跑,卻偏偏與公主長(zhǎng)得像惨驶,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子敛助,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353