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);
}
}
運行:
發送端運行兩次
接收端會一直接收
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
創建一個日誌系統,一個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
重點是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
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擅長的事情,建議使用擅長的工具做擅長的事,所以此處不再贅述