柯南君:看大資料時代下的IT架構(7)訊息佇列之RabbitMQ--案例(routing 起航)

來源:互聯網
上載者:User

標籤: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 起航)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.