- 更新記錄:
-
2017.07.18 增加 MAC 安裝方式豫喧。
[toc]
簡(jiǎn)書不支持 toc 目錄模式,截圖一張孵班。
image.png
image.png
-
簡(jiǎn)介
MQ為Message Queue别厘,消息隊(duì)列是應(yīng)用程和應(yīng)用程序之間的通信方法氮发。
RabbitMQ是一個(gè)開源的爽冕,在AMQP基礎(chǔ)上完整的乌奇,可復(fù)用的企業(yè)消息系統(tǒng)。
支持主流的操作系統(tǒng)寂屏,Linux、Windows、MacOX等昌粤。
多種開發(fā)語言支持,Java、Python捷雕、Ruby、.NET棒假、PHP、C/C++祝拯、node.js等
AMQP
AMQP是消息隊(duì)列的一個(gè)協(xié)議。
AMQP,即Advanced Message Queuing Protocol,一個(gè)提供統(tǒng)一消息服務(wù)的應(yīng)用層標(biāo)準(zhǔn)高級(jí)消息隊(duì)列協(xié)議,是應(yīng)用層協(xié)議的一個(gè)開放標(biāo)準(zhǔn),為面向消息的中間件設(shè)計(jì)。基于此協(xié)議的客戶端與消息中間件可傳遞消息众羡,并不受客戶端/中間件不同產(chǎn)品蓖宦,不同的開發(fā)語言等條件的限制。Erlang中的實(shí)現(xiàn)有 RabbitMQ等嚣州。
RabbitMQ官網(wǎng)地址http://www.rabbitmq.com/
Linux安裝RabbitMQ
安裝Erlang
添加yum支持
在線安裝:
cd /usr/local/src/
mkdir rabbitmq
cd rabbitmq
wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
rpm --import http://packages.erlang-solutions.com/rpm/erlang_solutions.asc
sudo yum install erlang
離線安裝:
centos相關(guān)資源:
http://omj2w5bt7.bkt.clouddn.com/rabbitmq-server-3.4.1-1.noarch.rpm
http://omj2w5bt7.bkt.clouddn.com/esl-erlang-compat-R14B-1.el6.noarch.rpm
http://omj2w5bt7.bkt.clouddn.com/esl-erlang_17.3-1centos6_amd64.rpm
http://omj2w5bt7.bkt.clouddn.com/esl-erlang-17.3-1.x86_64.rpm
windows相關(guān)資源:
http://omj2w5bt7.bkt.clouddn.com/rabbitmq-server-3.4.1.exe
http://omj2w5bt7.bkt.clouddn.com/otp_win32_17.4.exe
http://omj2w5bt7.bkt.clouddn.com/otp_win64_17.3.exe
上傳esl-erlang_17.3-1~centos~6_amd64.rpm
執(zhí)行 yum install esl-erlang_17.3-1~centos~6_amd64.rpm
上傳:esl-erlang-compat-R14B-1.el6.noarch.rpm
yum install esl-erlang-compat-R14B-1.el6.noarch.rpm
安裝RabbitMQ
上傳rabbitmq-server-3.4.1-1.noarch.rpm文件到/usr/local/src/rabbitmq/
安裝:
rpm -ivh rabbitmq-server-3.4.1-1.noarch.rpm
啟動(dòng)藐不、停止
service rabbitmq-server start
service rabbitmq-server stop
service rabbitmq-server restart
設(shè)置開機(jī)啟動(dòng)
chkconfig rabbitmq-server on
設(shè)置配置文件
cd /etc/rabbitmq
cp /usr/share/doc/rabbitmq-server-3.4.1/rabbitmq.config.example /etc/rabbitmq/
mv rabbitmq.config.example rabbitmq.config
開啟用戶遠(yuǎn)程訪問
vi /etc/rabbitmq/rabbitmq.config
開啟web界面管理工具
rabbitmq-plugins enable rabbitmq_management
service rabbitmq-server restart
防火墻開放15672端口
/sbin/iptables -I INPUT -p tcp --dport 15672 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 5672 -j ACCEPT
/etc/rc.d/init.d/iptables save
MAC安裝RabbitMQ
安裝:brew install rabbitmq
配置環(huán)境變量:
RabbitMQ Config
需要在 bash 或者 zsh 的環(huán)境變量中添加:
export PATH=$PATH:/usr/local/sbin
不然下面的指令,就必須到/usr/local/sbin
目錄下,才能直接執(zhí)行。
啟動(dòng):rabbitmq-server
停止:rabbitmqctl stop
狀態(tài):rabbitmqctl status
訪問:http://localhost:15672/
默認(rèn)的用戶名和密碼是 guest
和 guest
基本使用
訪問界面管理:
使用 guest/guest 進(jìn)行登錄产喉。
添加用戶
界面介紹:
創(chuàng)建虛擬主機(jī)
用戶授權(quán)虛擬主機(jī)


交換機(jī)和隊(duì)列綁定
首先創(chuàng)建好交換機(jī)和隊(duì)列
通過交換機(jī)綁定隊(duì)列或者通過隊(duì)列綁定交換機(jī)都可以塞俱。
隊(duì)列
簡(jiǎn)單隊(duì)列
P:消息的生產(chǎn)者
C:消息的消費(fèi)者
紅色:隊(duì)列
生產(chǎn)者將消息發(fā)送到隊(duì)列,消費(fèi)者從隊(duì)列中獲取消息颤霎。
代碼測(cè)試:
導(dǎo)入下面測(cè)試代碼柔纵,運(yùn)行完 Send.java 消息隊(duì)列中就有"Hello World! -- 1"字符串系羞,在運(yùn)行Recv.java梧乘,就會(huì)取出字符串学歧。
啟動(dòng)接收者Recv.java
,就可以在 rabbitMQ 管理平臺(tái)看到如下的一些信息:
啟動(dòng)接收者Send.java
洒缀,就可以在 rabbitMQ 看到隊(duì)列中的信息:
Recv.java
public class Recv {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 定義隊(duì)列的消費(fèi)者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監(jiān)聽隊(duì)列
channel.basicConsume(QUEUE_NAME, true, consumer);
// 獲取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
}
Send.java
public class Send {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
// 從連接中創(chuàng)建通道
Channel channel = connection.createChannel();
// 聲明(創(chuàng)建)隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 消息內(nèi)容
String message = "Hello World! -- 1";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
//關(guān)閉通道和連接
channel.close();
connection.close();
}
}
ConnectionUtil.java
public class ConnectionUtil {
public static Connection getConnection() throws Exception {
//定義連接工廠
ConnectionFactory factory = new ConnectionFactory();
//設(shè)置服務(wù)地址
factory.setHost("192.168.18.130");
//端口
factory.setPort(5672);
//設(shè)置賬號(hào)信息,用戶名、密碼、vhost
factory.setVirtualHost("/inke-test");
factory.setUsername("inke");
factory.setPassword("inke");
// 通過工程獲取連接
Connection connection = factory.newConnection();
return connection;
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>rabbitmq-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>rabbitmq-demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
</dependencies>
</project>
Work模式
一個(gè)生產(chǎn)者揩瞪、2個(gè)消費(fèi)者。
一個(gè)消息只能被一個(gè)消費(fèi)者獲取。
Send.java
public class Send {
private final static String QUEUE_NAME = "test_queue_work";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
for (int i = 0; i < 50; i++) {
// 消息內(nèi)容
String message = "" + i;
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
Thread.sleep(i * 10);
}
channel.close();
connection.close();
}
}
Recv.java
public class Recv {
private final static String QUEUE_NAME = "test_queue_work";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 同一時(shí)刻服務(wù)器只會(huì)發(fā)一條消息給消費(fèi)者
// channel.basicQos(1);
// 定義隊(duì)列的消費(fèi)者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監(jiān)聽隊(duì)列辛臊,手動(dòng)返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
//休眠
Thread.sleep(10);
// 返回確認(rèn)狀態(tài)
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
Recv2.java
public class Recv2 {
private final static String QUEUE_NAME = "test_queue_work";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 同一時(shí)刻服務(wù)器只會(huì)發(fā)一條消息給消費(fèi)者
// channel.basicQos(1);
// 定義隊(duì)列的消費(fèi)者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監(jiān)聽隊(duì)列,手動(dòng)返回完成狀態(tài)
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
// 休眠1秒
Thread.sleep(1000);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
測(cè)試結(jié)果:
1川抡、消費(fèi)者1和消費(fèi)者2獲取到的消息內(nèi)容是不同的密幔,同一個(gè)消息只能被一個(gè)消費(fèi)者獲取。
2、消費(fèi)者1和消費(fèi)者2獲取到的消息的數(shù)量是相同的速挑,一個(gè)是奇數(shù)一個(gè)是偶數(shù)腊满。
其實(shí)疮蹦,這樣是不合理的绅项,應(yīng)該是消費(fèi)者1要比消費(fèi)者2獲取到的消息多才對(duì)掀亥。
Work模式的“能者多勞”
消費(fèi)者需要打開這個(gè)開關(guān)
測(cè)試結(jié)果:
消費(fèi)者1比消費(fèi)者2獲取的消息更多。
消息的確認(rèn)模式
消費(fèi)者從隊(duì)列中獲取消息惑折,服務(wù)端如何知道消息已經(jīng)被消費(fèi)呢?
模式1:自動(dòng)確認(rèn)
只要消息從隊(duì)列中獲取,無論消費(fèi)者獲取到消息后是否成功消費(fèi)纱昧,都認(rèn)為是消息已經(jīng)成功消費(fèi)。模式2:手動(dòng)確認(rèn)
消費(fèi)者從隊(duì)列中獲取消息后艘包,服務(wù)器會(huì)將該消息標(biāo)記為不可用狀態(tài)猫牡,等待消費(fèi)者的反饋瑰抵,如果消費(fèi)者一直沒有反饋渣磷,那么該消息將一直處于不可用狀態(tài)丘侠。
手動(dòng)模式:
手動(dòng)模式:

訂閱模式:
解讀:
1始花、1個(gè)生產(chǎn)者亥贸,多個(gè)消費(fèi)者
2、每一個(gè)消費(fèi)者都有自己的一個(gè)隊(duì)列
3浇垦、生產(chǎn)者沒有將消息直接發(fā)送到隊(duì)列炕置,而是發(fā)送到了交換機(jī)
4、每個(gè)隊(duì)列都要綁定到交換機(jī)
5、生產(chǎn)者發(fā)送的消息朴摊,經(jīng)過交換機(jī)默垄,到達(dá)隊(duì)列,實(shí)現(xiàn)甚纲,一個(gè)消息被多個(gè)消費(fèi)者獲取的目的
代碼演示:
需求是:一個(gè)后臺(tái)服務(wù)提供給前臺(tái)和搜索展示數(shù)據(jù)口锭,如何保證數(shù)據(jù)的統(tǒng)一性。
向交換機(jī)中發(fā)送消息介杆。
注意:消息發(fā)送到?jīng)]有隊(duì)列綁定的交換機(jī)時(shí)鹃操,消息將丟失,因?yàn)榇荷冢粨Q機(jī)沒有存儲(chǔ)消息的能力荆隘,消息只能存在在隊(duì)列中。
消費(fèi)者1(看作是前臺(tái)系統(tǒng))
消費(fèi)者2(看作是搜索系統(tǒng))
測(cè)試結(jié)果:
同一個(gè)消息被多個(gè)消費(fèi)者獲取悲靴。
在管理工具中查看隊(duì)列和交換機(jī)的綁定關(guān)系:
使用訂閱模式能否實(shí)現(xiàn)商品數(shù)據(jù)的同步臭胜?
答案:可以的。
后臺(tái)系統(tǒng)就是消息的生產(chǎn)者癞尚。
前臺(tái)系統(tǒng)和搜索系統(tǒng)是消息的消費(fèi)者。
后臺(tái)系統(tǒng)將消息發(fā)送到交換機(jī)中乱陡,前臺(tái)系統(tǒng)和搜索系統(tǒng)都創(chuàng)建自己的隊(duì)列浇揩,然后將隊(duì)列綁定到交換機(jī),即可實(shí)現(xiàn)憨颠。
消息胳徽,新增商品、修改商品爽彤、刪除商品养盗。
前臺(tái)系統(tǒng):修改商品、刪除商品适篙。
搜索系統(tǒng):新增商品往核、修改商品、刪除商品嚷节。
所以使用訂閱模式實(shí)現(xiàn)商品數(shù)據(jù)的同步并不合理聂儒。
路由模式
如圖所示:c1 隊(duì)列綁定了 error ,c2 隊(duì)列綁定了 info硫痰、error衩婚、warning。
如果發(fā)送 error 的消息效斑,那么 c1 和 c2 都可以收到非春,發(fā)送 info、warning 只有c2可以收到,可以隨意組合奇昙,更加自由护侮。
例如:前臺(tái)系統(tǒng)只需要收取“更新“”刪除”的消息,而搜索系統(tǒng)還需要收取“新增”的消息敬矩。
測(cè)試結(jié)果:
當(dāng)發(fā)送的key是 insert 的時(shí)候概行,只有Recv2隊(duì)列的test_queue_direct_2才能接收到消息,
當(dāng)發(fā)送的key是 delete弧岳、update的時(shí)候凳忙,Recv1和Recv2都能接收到消息。
通配符模式
將路由鍵和某模式進(jìn)行匹配禽炬。此時(shí)隊(duì)列需要綁定要一個(gè)模式上涧卵。
符號(hào)“#”匹配一個(gè)或多個(gè)詞,符號(hào)“”匹配不多不少一個(gè)詞腹尖。*
因此“audit.#”能夠匹配到“audit.irs.corporate”柳恐,但是“audit.*” 只會(huì)匹配到“audit.irs”。
topic交換機(jī)是如何工作的:
生產(chǎn)者(后臺(tái)系統(tǒng))Send.java
public class Send {
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明exchange
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
// 消息內(nèi)容
String message = "商品刪除热幔,id=1003";
channel.basicPublish(EXCHANGE_NAME, "item.delete", null, message.getBytes());
System.out.println(" 后臺(tái)系統(tǒng): '" + message + "'");
channel.close();
connection.close();
}
}
消費(fèi)者1(前臺(tái)系統(tǒng))Recv.java
public class Recv {
private final static String QUEUE_NAME = "test_queue_topic_1";
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 綁定隊(duì)列到交換機(jī)
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.update");
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.delete");
// 同一時(shí)刻服務(wù)器只會(huì)發(fā)一條消息給消費(fèi)者
channel.basicQos(1);
// 定義隊(duì)列的消費(fèi)者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監(jiān)聽隊(duì)列乐设,手動(dòng)返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 前臺(tái)系統(tǒng): '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}
消費(fèi)者2(搜索系統(tǒng))Recv2.java
public class Recv2 {
private final static String QUEUE_NAME = "test_queue_topic_2";
private final static String EXCHANGE_NAME = "test_exchange_topic";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 聲明隊(duì)列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 綁定隊(duì)列到交換機(jī)
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "item.#");
// 同一時(shí)刻服務(wù)器只會(huì)發(fā)一條消息給消費(fèi)者
channel.basicQos(1);
// 定義隊(duì)列的消費(fèi)者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 監(jiān)聽隊(duì)列,手動(dòng)返回完成
channel.basicConsume(QUEUE_NAME, false, consumer);
// 獲取消息
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 搜索系統(tǒng): '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
}
}

測(cè)試結(jié)果:item.# 匹配所有前綴是 item 的消息绎巨。
Spring-Rabbit
Spring項(xiàng)目
http://spring.io/projects
The project consists of two parts; spring-amqp is the base abstraction, and spring-rabbit is the RabbitMQ implementation.
該項(xiàng)目由兩部分組成: spring-amqp是基礎(chǔ)抽象近尚,spring-rabbit是RabbitMQ實(shí)現(xiàn)。
代碼演示:
public class SpringMain {
public static void main(final String... args) throws Exception {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:spring/rabbitmq-context.xml");
//RabbitMQ模板
RabbitTemplate template = ctx.getBean(RabbitTemplate.class);
//發(fā)送消息
template.convertAndSend("Hello, world!");
Thread.sleep(1000);// 休眠1秒
ctx.destroy(); //容器銷毀
}
}
/**
* 消費(fèi)者
*/
public class Foo {
//具體執(zhí)行業(yè)務(wù)的方法
public void listen(String foo) {
System.out.println("消費(fèi)者: " + foo);
}
}
rabbitmq-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- 定義RabbitMQ的連接工廠 -->
<rabbit:connection-factory id="connectionFactory"
host="192.168.18.130" port="5672" username="inke" password="inke" virtual-host="/inke-test" />
<!-- 定義Rabbit模板场勤,指定連接工廠以及定義exchange -->
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" exchange="fanoutExchange" />
<!-- <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
exchange="fanoutExchange" routing-key="foo.bar" /> -->
<!-- MQ的管理戈锻,包括隊(duì)列、交換器等 -->
<rabbit:admin connection-factory="connectionFactory" />
<!-- 定義隊(duì)列和媳,自動(dòng)聲明 -->
<rabbit:queue name="myQueue" auto-declare="true" durable="false"/>
<!-- 定義交換器格遭,自動(dòng)聲明 -->
<rabbit:fanout-exchange name="fanoutExchange" auto-declare="true" durable="false">
<rabbit:bindings>
<rabbit:binding queue="myQueue"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
<!-- <rabbit:topic-exchange name="myExchange">
<rabbit:bindings>
<rabbit:binding queue="myQueue" pattern="foo.*" />
</rabbit:bindings>
</rabbit:topic-exchange> -->
<!-- 隊(duì)列監(jiān)聽 -->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="foo" method="listen" queue-names="myQueue" />
</rabbit:listener-container>
<bean id="foo" class="com.example.rabbitmq.spring.Foo" />
</beans>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" exchange="fanoutExchange" />
這里可以直接選擇發(fā)送到哪個(gè)隊(duì)列,而不是交換機(jī)留瞳。
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" queue="myQueue"/>
持久化交換機(jī)和隊(duì)列
持久化:將交換機(jī)或隊(duì)列的數(shù)據(jù)保存到磁盤拒迅,服務(wù)器宕機(jī)或重啟之后依然存在。
非持久化:將交換機(jī)或隊(duì)列的數(shù)據(jù)保存到內(nèi)存撼港,服務(wù)器宕機(jī)或重啟之后將不存在坪它。
非持久化的性能高于持久化。
如何選擇持久化帝牡?非持久化往毡?-- 看需求。

參考自:
某培訓(xùn)機(jī)構(gòu)
CSDN
spring 官網(wǎng)