RabbitMQ實踐--安裝、JAVA客戶端操作

RabbitMQ是一種消息中間件,用於處理來自客戶端的異步消息。服務端將要發送的消息放入到隊列池中。接收端可以根據RabbitMQ配置的轉發機制接收服務端發來的消息。RabbitMQ依據指定的轉發規則進行消息的轉發、緩衝和持久化操作,主要用在多服務器間或單服務器的子系統間進行通信,是分佈式系統標準的配置。

建議先看我的另一篇博文,對RabbitMQ有個整體的認識再來操作,將會事半功倍
RabbitMQ–整體簡介:http://blog.csdn.net/qq_34039315/article/details/77378641
也可以考慮先對消息隊列有個整體的認識:
消息隊列綜述:http://blog.csdn.net/qq_34039315/article/details/77338178

RabbitMQ服務端安裝

Rabbitmq基於erlang語言開發,所有需要安裝erlang虛擬機,各平臺參考官網安裝即可。Mac、linux的安裝方法在頁面的相對後面一點,也很簡單。
鏈接地址:http://www.erlang.org/downloads
同理,參考rabbitMQ官網來安裝RabbitMQ:
鏈接地址:http://www.rabbitmq.com/download.html

開啓管理插件

使用Rabbit MQ 管理插件,可以更好的可視化方式查看Rabbit MQ 服務器實例的狀態
請在windows在RabbitMQ的安裝目錄 執行如下命令

# sbin\rabbitmq-plugins.bat enable rabbitmq_management
# net stop RabbitMQ && net start RabbitMQ

各平臺插件管理命令:

開啓某個插件:rabbitmq-plugins enable xxx
關閉某個插件:rabbitmq-plugins disable xxx

注意:重啓服務器後生效
然後打開連接http://localhost:15672,以guest/guest登錄就可以看到服務器當前的運行狀態

文檔地址

文檔頁: 文檔分爲 服務器及關鍵插件、客戶端及特性、插件、開發、協議 部分,可以參考對應的文檔繼續深入瞭解。
http://next.rabbitmq.com/documentation.html

java客戶端操作實踐

本操作系列根據官網的指引文檔http://next.rabbitmq.com/getstarted.html操作結果,由於純英文展示,本文做了部分翻譯和加工操作

“Hello World”

本小節創建一個很簡單的隊列,一個生產者,一個消費者。
一個生產者,一個消費者
添加maven依賴,此處對slf4j的實現是簡單的slf4j-simple實現,在真正的生產環境中建議使用log4j、logback等。

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.25</version>
</dependency>

代碼如下:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class Send {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) throws IOException, TimeoutException {
        //創建一個連接,並且從連接處獲取一個channel,爲什麼用channel參考"RabbitMQ--整體綜述"
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //將消息發送到某個Queue上面去
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        String message = "Hello World!";
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        System.out.println(" [x] Sent '" + message + "'");
        //如同數據庫連接一樣,依次關閉連接
        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class Recv {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) throws IOException, TimeoutException {
        //創建一個連接,並且從連接處獲取一個channel,爲什麼用channel參考"RabbitMQ--整體綜述"
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //聲明接收某個隊列的消息
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //創建一個默認消費者,並在handleDelivery中回調處理消息內容
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body)
                            throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            }
        };
        //channel綁定隊列、消費者,autoAck爲true表示一旦收到消息則自動回覆確認消息
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}

運行:
發送端運行兩次
Send1
接收端會一直接收
Recv1

Work Queues

分發消息隊列,多個消費者
多個消費者
代碼如下:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class Send {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) throws IOException, TimeoutException {
        //創建一個連接,並且從連接處獲取一個channel,爲什麼用channel參考"RabbitMQ--整體綜述"
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //將消息發送到某個Queue上面去
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        for (int i = 0; i < 10; i++) {//改爲發送十次消息
            String message = "Hello World " + (i+1);
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
        }
        //如同數據庫連接一樣,依次關閉連接
        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class Recv1 {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) throws IOException, TimeoutException {
        //創建一個連接,並且從連接處獲取一個channel,爲什麼用channel參考"RabbitMQ--整體綜述"
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //聲明接收某個隊列的消息
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        //創建一個默認消費者,並在handleDelivery中回調處理消息內容
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body)
                            throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
                //增加處理時間
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        //channel綁定隊列、消費者,autoAck爲true表示一旦收到消息自動回覆確認消息
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}

此處Recv1與Recv2代碼一致,不再贅述

運行
send發送如下

[x] Sent ‘Hello World 1’
[x] Sent ‘Hello World 2’
[x] Sent ‘Hello World 3’
[x] Sent ‘Hello World 4’
[x] Sent ‘Hello World 5’
[x] Sent ‘Hello World 6’
[x] Sent ‘Hello World 7’
[x] Sent ‘Hello World 8’
[x] Sent ‘Hello World 9’
[x] Sent ‘Hello World 10’

Recv1接收如下

[*] Waiting for messages. To exit press CTRL+C
[x] Received ‘Hello World 1’
[x] Received ‘Hello World 3’
[x] Received ‘Hello World 5’
[x] Received ‘Hello World 7’
[x] Received ‘Hello World 9’

Recv2接收如下

[*] Waiting for messages. To exit press CTRL+C
[x] Received ‘Hello World 2’
[x] Received ‘Hello World 4’
[x] Received ‘Hello World 6’
[x] Received ‘Hello World 8’
[x] Received ‘Hello World 10’

探索1:將Rev1的Thread.sleep(50)修改爲50,意思是Rev1的處理能力比Rev2的處理能力強20倍,會發生什麼事情呢?

結果還是和原來一樣,每個Recv處理5個間隔一個的消息,爲什麼這樣呢?默認情況下,RabbitMQ採用輪詢的方式發送message,所以只能一個輪一個地發送。這個在機器處理能力不均勻的場景是不合適的,當然RabbitMQ是提供了配置方法的。

探索2:在Recv2處理到收到第二條消息的時候,我們強制kill掉Recv2會發生什麼事情呢?剩餘的消息會不會轉發到Recv1上呢?

不會的,當前的模式下,RabbitMQ發送完消息後就把緩存的消息刪除了,不關心消息是否真正的處理是否完成,所以如果宕機等會發生消息丟失的情況。這個時候就需要消息確認機制了,Recv真正的收到消息,處理完消息後,RabbitMQ才刪除消息。
修改方法如下:
Recv增加消息確認反饋機制

@Override
public void handleDelivery(String consumerTag, Envelope envelope,
                AMQP.BasicProperties properties, byte[] body)
                throws IOException {
    String message = new String(body, "UTF-8");
    System.out.println(" [x] Received '" + message + "'");
    //增加處理時間
    try {
        Thread.sleep(50);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println(" [x] Done");
        //此處增加消息確認確認機制,envelope.getDeliveryTag()獲取消息的唯一標識,false表示僅ack當前消息
        channel.basicAck(envelope.getDeliveryTag(), false);
    }

//channel綁定隊列、消費者,autoAck爲true表示一旦收到消息自動回覆確認消息
channel.basicConsume(QUEUE_NAME, false, consumer);

探索3:消息確認機制可以大體上保證消費端不丟失消息,那麼Broker怎麼保證呢?

開啓持久化即可,當然達不到100%,畢竟持久化也是需要少量的時間,但這個時間可能造成微量損失。
代碼改動如下:

//統一修改隊列名稱
private final static String QUEUE_NAME = "task_queue";
//聲明隊列的時候說明屬性
boolean durable = true;
channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
//發送消息的時候說明保存方式
channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

爲什麼要改隊列名字呢?因爲RabbitMQ只會遵循首次創建隊列時候的屬性!後面聲明同一個名字的隊列的時候,如果沒有這個隊列則創建,有則忽略創建任務。當然,你也可以先刪除以前的隊列,然後再創建,就不用改隊列名了。

探索4:修正探索1的缺點

改成根據處理能力來分發消息,代碼修改如下:
Recv增加設置

int prefetchCount = 1;
channel.basicQos(prefetchCount);

最終整體代碼如下:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class Send {
    private final static String QUEUE_NAME = "task_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        //創建一個連接,並且從連接處獲取一個channel,爲什麼用channel參考"RabbitMQ--整體綜述"
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //將消息發送到某個Queue上面去
        boolean durable = true;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
        for (int i = 0; i < 10; i++) {//改爲發送十次消息
            String message = "Hello World " + (i+1);
            channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
        }
        //如同數據庫連接一樣,依次關閉連接
        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class Recv1 {
    private final static String QUEUE_NAME = "task_queue";

    public static void main(String[] args) throws IOException, TimeoutException {
        //創建一個連接,並且從連接處獲取一個channel,爲什麼用channel參考"RabbitMQ--整體綜述"
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        final Channel channel = connection.createChannel();
        //聲明接收某個隊列的消息
        boolean durable = true;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
        int prefetchCount = 1;
        channel.basicQos(prefetchCount);
        //創建一個默認消費者,並在handleDelivery中回調處理消息內容
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body)
                            throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
                //增加處理時間
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(" [x] Done");
                    //此處增加消息確認確認機制,envelope.getDeliveryTag()獲取消息的唯一標識,false表示僅ack當前消息
                    channel.basicAck(envelope.getDeliveryTag(), false);
                }
            }
        };
        //channel綁定隊列、消費者,autoAck爲true表示一旦收到消息自動回覆確認消息
        channel.basicConsume(QUEUE_NAME, false, consumer);
    }
}

Publish/Subscribe

fanout類型
創建一個日誌系統,一個Send,兩個Recv。
重點是增加Exchange,通過fanout類型將消息廣播給所有的的Recv。

這裏我們創建臨時隊列,從RabbitMQ中獲取隊列名,然後在不需要使用的時候刪除它。
代碼如下:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class EmitLog {

    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] argv) throws java.io.IOException, TimeoutException {
        //建立連接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //聲明exchange,並用fanout類型
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        for (int i = 0; i < 10; i++) {//改爲發送十次消息
            String message = "Hello World " + (i + 1);
            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
        }
        //關閉連接
        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class ReceiveLogs {
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] argv) throws Exception {
        //簡歷連接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //聲明Exchange類型
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        //獲取隨機隊列名稱
        String queueName = channel.queueDeclare().getQueue();
        //Exchange與queue綁定
        channel.queueBind(queueName, EXCHANGE_NAME, "");

        System.out.println(" [*] " + queueName + "Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }
}

運行兩次ReceiveLogs,再運行EmitLog,就會發現ReceiveLogs都接受到了相同的消息

Routing

direct類型
重點是Exchange的direct類型。如果某些消費者只關注部分消息怎麼辦?這個direct類型解決這類問題,也叫routing模式

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.util.*;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class EmitLogDirect {
    private static final String EXCHANGE_NAME = "direct_logs";
    private static final List<String> SEVERITIES = new ArrayList<>();
    static {
        SEVERITIES.add("info");
        SEVERITIES.add("error");
        SEVERITIES.add("warning");
    }

    public static void main(String[] argv) throws java.io.IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "direct");

        for (int i = 0; i < 10; i++) {
            String severity = SEVERITIES.get(new Random().nextInt(3));//隨機產生一個routingKey
            String message = "some logs " + i;
            channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
            System.out.println(" [x] Sent '" + severity + "':'" + message + "'");
        }

        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class ReceiveLogsDirect1 {
    private static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] argv) throws Exception {
        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();

        //綁定固定類型的routingKey
        channel.queueBind(queueName, EXCHANGE_NAME, "info");
        channel.queueBind(queueName, EXCHANGE_NAME, "error");
        channel.queueBind(queueName, EXCHANGE_NAME, "warning");

        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class ReceiveLogsDirect2 {
    private static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] argv) throws Exception {
        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();

        //綁定固定類型的routingKey,只關心error
        channel.queueBind(queueName, EXCHANGE_NAME, "error");

        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }
}

運行即可發現ReceiveLogsDirect2只收到了error的相關信息,而ReceiveLogsDirect1接收到了所有消息

Topics

topic類型
Exchange的topic類型,用通配符的方式來匹配相應的接收信息
符號“#”匹配一個或多個詞,符號“*”匹配不多不少一個詞
代碼如下:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeoutException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class EmitLogDirect {
    private static final String EXCHANGE_NAME = "topic_logs";
    private static final List<String> SEVERITIES = new ArrayList<>();
    static {
        // 符號“#”匹配一個或多個詞,符號“*”匹配不多不少一個詞
        SEVERITIES.add("*.*.rabbit");
        SEVERITIES.add("a.b.rabbit");
        SEVERITIES.add("c.rabbit");//丟失,因爲不匹配
        SEVERITIES.add("lazy.#");
        SEVERITIES.add("lazy.a.b");
        SEVERITIES.add("lazy.c");
        SEVERITIES.add("*.orange.*");
        SEVERITIES.add("a.orange.b");
        SEVERITIES.add("c.orange");//丟失,因爲不匹配
    }

    public static void main(String[] argv) throws java.io.IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "topic");

        for (int i = 0; i < 30; i++) {
            String severity = SEVERITIES.get(new Random().nextInt(SEVERITIES.size()));//隨機產生一個routingKey
            String message = "some logs " + i;
            channel.basicPublish(EXCHANGE_NAME, severity, null, message.getBytes());
            System.out.println(" [x] Sent '" + severity + "':'" + message + "'");
        }

        channel.close();
        connection.close();
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class ReceiveLogsDirect1 {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "topic");
        String queueName = channel.queueDeclare().getQueue();

        //綁定固定類型的topic
        channel.queueBind(queueName, EXCHANGE_NAME, "*.*.rabbit");
        channel.queueBind(queueName, EXCHANGE_NAME, "lazy.#");

        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }
}
import com.rabbitmq.client.*;

import java.io.IOException;

/**
 *
 * @author xuexiaolei
 * @version 2017年08月20日
 */
public class ReceiveLogsDirect2 {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, "topic");
        String queueName = channel.queueDeclare().getQueue();

        //綁定固定類型的topic
        channel.queueBind(queueName, EXCHANGE_NAME, "*.orange.*");

        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                            AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queueName, true, consumer);
    }
}

Remote procedure call (RPC)

RPC畢竟不是MQ擅長的事情,建議使用擅長的工具做擅長的事,所以此處不再贅述
RPC方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章