MQ之RabbitMQ

  • 更新記錄:
    • 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)的用戶名和密碼是 guestguest



基本使用

訪問界面管理:


使用 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)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末靶溜,一起剝皮案震驚了整個(gè)濱河市开瞭,隨后出現(xiàn)的幾起案子懒震,更是在濱河造成了極大的恐慌,老刑警劉巖嗤详,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件个扰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡葱色,警方通過查閱死者的電腦和手機(jī)递宅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苍狰,“玉大人办龄,你說我怎么就攤上這事×苷眩” “怎么了俐填?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)翔忽。 經(jīng)常有香客問我英融,道長(zhǎng),這世上最難降的妖魔是什么歇式? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任驶悟,我火速辦了婚禮,結(jié)果婚禮上材失,老公的妹妹穿的比我還像新娘撩银。我一直安慰自己,他們只是感情好豺憔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著够庙,像睡著了一般恭应。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耘眨,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天昼榛,我揣著相機(jī)與錄音,去河邊找鬼剔难。 笑死胆屿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的偶宫。 我是一名探鬼主播非迹,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼纯趋!你這毒婦竟也來了憎兽?” 一聲冷哼從身側(cè)響起冷离,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纯命,沒想到半個(gè)月后西剥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亿汞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年瞭空,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疗我。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咆畏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碍粥,到底是詐尸還是另有隱情鳖眼,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布嚼摩,位于F島的核電站钦讳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏枕面。R本人自食惡果不足惜愿卒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望潮秘。 院中可真熱鬧琼开,春花似錦、人聲如沸枕荞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躏精。三九已至渣刷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矗烛,已是汗流浹背辅柴。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞭吃,地道東北人碌嘀。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像歪架,于是被迫代替她去往敵國(guó)和親股冗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 來源 RabbitMQ是用Erlang實(shí)現(xiàn)的一個(gè)高并發(fā)高可靠AMQP消息隊(duì)列服務(wù)器牡拇。支持消息的持久化魁瞪、事務(wù)穆律、擁塞控...
    jiangmo閱讀 10,361評(píng)論 2 34
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)导俘,斷路器峦耘,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • RabbitMQ筆記 本文參考資料:http://blog.csdn.net/chwshuang/article/...
    wangxiaoda閱讀 2,821評(píng)論 0 11
  • 關(guān)于消息隊(duì)列,從前年開始斷斷續(xù)續(xù)看了些資料旅薄,想寫很久了辅髓,但一直沒騰出空,近來分別碰到幾個(gè)朋友聊這塊的技術(shù)選型少梁,是時(shí)...
    預(yù)流閱讀 584,775評(píng)論 51 786
  • RabbitMQ 簡(jiǎn)介 RabbitMQ是一個(gè)在AMQP(Advanced Message Queuing Pro...
    Doris_Lee閱讀 71,958評(píng)論 2 29