標籤:bindings rabbitmq exchange 大資料 架構
一、回顧
讓我們回顧一下,在上幾章裡都講了什嗎?總結如下:
- 《柯南君:看大資料時代下的IT架構(1)業界訊息佇列對比》
- 《柯南君:看大資料時代下的IT架構(2)訊息佇列之RabbitMQ-基礎概念詳細介紹》
- 《柯南君:看大資料時代下的IT架構(3)訊息佇列之RabbitMQ-安裝、配置與監控》
- 《柯南君:看大資料時代下的IT架構(4)訊息佇列之RabbitMQ--案例(Helloword起航)》
- 《柯南君:看大資料時代下的IT架構(5)訊息佇列之RabbitMQ--案例(Work Queues起航)》
- 《柯南君:看大資料時代下的IT架構(6)訊息佇列之RabbitMQ--案例(Publish/Subscribe起航)》
二、Routing(路由) (using the Java client)在前面的學習中,構建了一個簡單的日誌記錄系統,能夠廣播所有的日誌給多個接收者,在該部分學習中,將添加一個新的特點,就是可以只訂閱一個特定的訊息源,也就是說能夠直接把關鍵的錯誤記錄檔訊息發送到記錄檔儲存起來,不重要的日誌資訊檔不儲存在磁碟中,但是仍然能夠在控制台輸出,那麼這便是我們這部分要學習的訊息的路由分發機制。三、Bindings(綁定) 在前面的學習中已經建立了綁定(bindings),代碼如下:
channel.queueBind(queueName, EXCHANGE_NAME, "");
一個綁定就是一個關於exchange和queue的關係,它可以簡單的被理解為:隊列是從這個exchange中擷取訊息的。
綁定可以採取一個額外的routingKey的參數,為了避免與basicPublish參數衝突,稱之為一個綁定Key,這是如何建立一個帶routingKey的綁定的關鍵。
channel.queueBind(queueName, EXCHANGE_NAME, "black");
一個綁定Key依賴於exchange的類型,像之前使用fanout類型的exchange,完全忽略了該綁定key的值。 四、Direct exchange(直接交換器)
前面實現的日誌記錄系統中廣播所有的訊息給所有的消費者,現在對其進行擴充,允許根據資訊的嚴重程度來對訊息進行過濾,比如,希望一個程式寫入到磁碟的日誌訊息只接收錯誤的訊息,而不是浪費磁碟儲存所有的日誌訊息。
為了實現這個目標,使用一個fanout類型的exchange,顯然是不能夠滿足這樣的需求的,因為它只能廣播所有的訊息。
為此將使用一個direct exchange來代替fanout exchange,direct exchange使用簡單的路由演算法,將訊息通過綁定的Key匹配將要到達的隊列。
從上面的結構圖中可以看出direct exchange X綁定著兩個queue(Q1,Q2),第一個queue綁定的routingKey為orange,第二個有兩個routingKey被綁定,一個routingKey為black,另外一個routingKey為green.
說明:發送帶有routingKey為orange的訊息到X(exchange)中,X將該訊息路由到Q1中,發送帶有routingKey為black和green的訊息都將被路由到Q2中,其他所有訊息將會被丟棄。
五、Multiple bindings(多綁定) 多個隊資料行繫結相同的routingKey是允許的,在上述執行個體中,可以把X和Q1用routingKey:black綁定起來,這種情況下,direct exchange將像fanout類型的exchange一樣會將訊息廣播都到所有匹配的queues中,即一個routingKey為black的訊息將會被發送到Q1和Q2中。六、Emitting logs(發送的日誌)使用direct代替fanout類型的exchange,發送訊息到一個direct exchange中,將根據訊息的重要程度作為routingKey,這樣接收程式能夠選擇它想要接收的日誌資訊,首先必須先建立一個exchange.
channel.exchangeDeclare(EXCHANGE_NAME, "direct");
其次,發送一條資訊:
channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
為了簡化程式,將severity設定為info、warning、error三種類型中的一種。六、Subscribing(訂閱訊息) 接收者根據自己感興趣的severity來建立一個新到的綁定。
String queueName = channel.queueDeclare().getQueue();for(String severity : argv){ channel.queueBind(queueName, EXCHANGE_NAME, severity);}
七、Putting it all together(代碼實現)EmitLogDirect.java代碼清單如下:
public class EmitLogDirect { private static final String EXCHANGE_NAME = "direct_logs"; public static void main(String[] argv) throws java.io.IOException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, "direct"); String severity = getSeverity(argv); String message = getMessage(argv); channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes()); System.out.println(" [x] Sent '" + severity + "':'" + message + "'"); channel.close(); connection.close(); } //..}
ReceiveLogsDirect代碼清單如下:
public class ReceiveLogsDirect { private static final String EXCHANGE_NAME = "direct_logs"; public static void main(String[] argv) throws java.io.IOException, java.lang.InterruptedException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, "direct"); String queueName = channel.queueDeclare().getQueue(); if (argv.length < 1){ System.err.println("Usage: ReceiveLogsDirect [info] [warning] [error]"); System.exit(1); } for(String severity : argv){ channel.queueBind(queueName, EXCHANGE_NAME, severity); } System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); QueueingConsumer consumer = new QueueingConsumer(channel); channel.basicConsume(queueName, true, consumer); while (true) { QueueingConsumer.Delivery delivery = consumer.nextDelivery(); String message = new String(delivery.getBody()); String routingKey = delivery.getEnvelope().getRoutingKey(); System.out.println(" [x] Received '" + routingKey + "':'" + message + "'"); } }}
編譯和往常一樣(參見以往教程用於編譯和類路徑的建議)。現在,為了方便起見,我們將使用一個環境變數$CP(%CP%在Windows上)的運行時類路徑的例子。
如果你只想儲存 “警告”和“錯誤”(而不是“資訊”)日誌訊息到一個檔案,開啟一個控制台和type:
$ java -cp $CP ReceiveLogsDirect warning error > logs_from_rabbit.log
如果你想看到所有的日誌訊息在你的螢幕上,開啟一個新終端和do:
$ java -cp $CP ReceiveLogsDirect info warning error [*] Waiting for logs. To exit press CTRL+C
例如,發布一個錯誤記錄檔資訊
$ java -cp $CP EmitLogDirect error "Run. Run. Or it will explode." [x] Sent ‘error‘:‘Run. Run. Or it will explode.‘
柯南君:看大資料時代下的IT架構(7)訊息佇列之RabbitMQ--案例(routing 起航)