RabbitMQ中,所有生產者提交的消息都由Exchange來接受,然后Exchange按照特定的策略轉發到Queue進行存儲
RabbitMQ提供了四種Exchange:fanout,direct,topic,header
header模式在實際使用中較少,本文只對前三種模式進行比較。
性能排序:fanout > direct >> topic。比例大約為11:10:6
一.Direct Exchange
Direct Exchange - 處理路由鍵。需要將一個隊列綁定到交換機上,要求該消息與一個特定的路由鍵完全匹配。這是一個完整的匹配。如果一個隊列綁定到該交換機上要求路由鍵 “dog”,則只有被標記為“dog”的消息才被轉發,不會轉發dog.puppy,也不會轉發dog.guard,只會轉發dog。
任何發送到Direct Exchange的消息都會被轉發到RouteKey中指定的Queue。
1.一般情況可以使用rabbitMQ自帶的Exchange:”"(該Exchange的名字為空字符串,下文稱其為default Exchange)。
2.這種模式下不需要將Exchange進行任何綁定(binding)操作
3.消息傳遞時需要一個“RouteKey”,可以簡單的理解為要發送到的隊列名字。
4.如果vhost中不存在RouteKey中指定的隊列名,則該消息會被拋棄。
Channel channel = connection.createChannel(); channel.exchangeDeclare("exchangeName", "direct"); //direct fanout topic channel.queueDeclare("queueName"); channel.queueBind("queueName", "exchangeName", "routingKey"); byte[] messageBodyBytes = "hello world".getBytes(); //需要綁定路由鍵 channel.basicPublish("exchangeName", "routingKey", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);
二.Fanout Exchange
Fanout Exchange – 不處理路由鍵。你只需要簡單的將隊列綁定到交換機上。一個發送到交換機的消息都會被轉發到與該交換機綁定的所有隊列上。很像子網廣播,每台子網內的主機都獲得了一份復制的消息。Fanout交換機轉發消息是最快的。
任何發送到Fanout Exchange的消息都會被轉發到與該Exchange綁定(Binding)的所有Queue上。
1.可以理解為路由表的模式
2.這種模式不需要RouteKey
3.這種模式需要提前將Exchange與Queue進行綁定,一個Exchange可以綁定多個Queue,一個Queue可以同多個Exchange進行綁定。
4.如果接受到消息的Exchange沒有與任何Queue綁定,則消息會被拋棄。
Channel channel = connection.createChannel(); channel.exchangeDeclare("exchangeName", "fanout"); //direct fanout topic channel.queueDeclare("queueName"); channel.queueBind("queueName", "exchangeName", "routingKey"); channel.queueDeclare("queueName1"); channel.queueBind("queueName1", "exchangeName", "routingKey1"); byte[] messageBodyBytes = "hello world".getBytes(); //路由鍵需要設置為空 channel.basicPublish("exchangeName", "", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);
三.Topic Exchange
Topic Exchange – 將路由鍵和某模式進行匹配。此時隊列需要綁定要一個模式上。符號“#”匹配一個或多個詞,符號“*”匹配不多不少一個詞。因此“audit.#”能夠匹配到“audit.irs.corporate”,但是“audit.*” 只會匹配到“audit.irs”
任何發送到Topic Exchange的消息都會被轉發到所有關心RouteKey中指定話題的Queue上
1.這種模式較為復雜,簡單來說,就是每個隊列都有其關心的主題,所有的消息都帶有一個“標題”(RouteKey),Exchange會將消息轉發到所有關注主題能與
RouteKey模糊匹配的隊列。
2.這種模式需要RouteKey,也許要提前綁定Exchange與Queue。
3.在進行綁定時,要提供一個該隊列關心的主題,如“#.log.#”表示該隊列關心所有涉及log的消息(一個RouteKey為”MQ.log.error”的消息會被轉發到該隊列)。
4.“#”表示0個或若干個關鍵字,“*”表示一個關鍵字。如“log.*”能與“log.warn”匹配,無法與“log.warn.timeout”匹配;但是“log.#”能與上述兩者匹配。
5.同樣,如果Exchange沒有發現能夠與RouteKey匹配的Queue,則會拋棄此消息。
Channel channel = connection.createChannel(); channel.exchangeDeclare("exchangeName", "topic"); //direct fanout topic channel.queueDeclare("queueName"); channel.queueBind("queueName", "exchangeName", "routingKey.*"); byte[] messageBodyBytes = "hello world".getBytes(); channel.basicPublish("exchangeName", "routingKey.one", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);