RabbitMQ (三)Hello World

RabbitMQ官網中文版教程:

http://rabbitmq.mr-ping.com/tutorials_with_python/[1]Hello_World.html

上述教程示例為pathon版,Java版及相應解釋如下:

生產者代碼

package com.xc.rabbitmq.helloworld;

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

/**
 * 消息生產者
 *
 * Created by xc.
 */
public class Producer {

    private final static String QUEUE_NAME = "Hello";

    public static void main(String[] args) throws Exception {
        // 創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        // 設置 RabbitMQ 地址
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("xc");
        factory.setPassword("xc");
        // 創建一個新的連接
        Connection connection = factory.newConnection();
        // 創建一個新的頻道
        Channel channel = connection.createChannel();
        // 聲明一個隊列 -- 在 RabbitMQ 中, 隊列的聲明是冪等性的
        // 一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同
        // 也就是說, 如果不存在, 就創建, 如果存在, 不會對已經存在的隊列產生任何影響
        // 如果并不知道是生產者還是消費者程序中的哪個先運行,在程序中重復將隊列重復聲明一下是種值得推薦的做法
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        String message = "hello world";
        // 發送到消息隊列中
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
        System.out.println("P [x] Sent '" + message + "'");
        // 關閉頻道和連接
        channel.close();
        connection.close();
    }

}

程序執行結果如下圖(rabbitmq Web管理界面):

RabbitMQ中收到了一條消息。

消費者代碼

package com.xc.rabbitmq.helloworld;

import com.rabbitmq.client.*;

import java.io.IOException;


/**
 * 消費者
 *
 * Created by xc.
 */
public class Consumer {

    private static final String QUEUE_NAME = "Hello";

    public static void main(String[] args) throws Exception {
        // 創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        // 設置 RabbitMQ 地址
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setUsername("rabbit");
        factory.setPassword("carrot");
        // 創建一個新的連接
        Connection connection = factory.newConnection();
        // 創建一個頻道
        Channel channel = connection.createChannel();
        // 聲明要關注的隊列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

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

        // DefaultConsumer類 實現了 Consumer 接口, 通過傳入一個頻道, 告訴服務器我們需要哪個頻道的消息
        // 如果頻道中有消息, 就會執行回調函數 handleDelivery
        com.rabbitmq.client.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("C [x] Received '" + message + "'");
            }
        };

        // 自動回復隊列應答 -- RabbitMQ 中的消息確認機制, 后面章節會詳細介紹
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}

程序執行結果如下圖(rabbitmq Web管理界面):

如圖,Hello隊列中的消息被消費掉了。

程序的maven依賴:

        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>3.6.0</version>
        </dependency>

API參數解釋:

1) Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) throws IOException;

@param queue : the name of the queue 隊列名

@param durable :true if we are declaring a durable queue (the queue will survive a server restart) 隊列是否持久化

@param exclusive : true if we are declaring an exclusive queue (restricted to this connection) 是否為當前連接的專用隊列,在連接斷開后,會自動刪除該隊列

@param autoDelete : true if we are declaring an autodelete queue (server will delete it when no longer in use) 當沒有任何消費者使用時,自動刪除該隊列

@param arguments : other properties (construction arguments) for the queue 其他隊列配置

2)void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;

@param exchange the exchange to publish the message to 消息發送到哪個交換器(之后章節會講到)。填空字符串表示指定默認交換器,MQ會根據routingKey生成一個默認的direct類型的交換器。

@param routingKey :the routing key 路由鍵,#匹配0個或多個單詞,*匹配一個單詞,在topic exchange做消息轉發用

@param mandatory :true if the 'mandatory' flag is to be set 如果exchange根據自身類型和消息routeKey無法找到一個符合條件的queue,那么會調用basic.return方法將消息返還給生產者。false:出現上述情形broker會直接將消息扔掉

@param immediate :true if the 'immediate' flag is to be set. Note that the RabbitMQ server does not support this flag. 如果exchange在將消息route到queue(s)時發現對應的queue上沒有消費者,那么這條消息不會放入隊列中。當與消息routeKey關聯的所有queue(一個或多個)都沒有消費者時,該消息會通過basic.return方法返還給生產者。

@param props other properties for the message - routing headers etc 需要注意的是BasicProperties.deliveryMode,0:不持久化 1:持久化 這里指的是消息的持久化,配合exchange(durable=true),queue(durable)可以實現,即使服務器宕機,消息仍然保留。

@param body the message body 具體消息

簡單來說:mandatory標志告訴服務器至少將該消息route到一個隊列中,否則將消息返還給生產者;immediate標志告訴服務器如果該消息關聯的queue上有消費者,則馬上將消息投遞給它,如果所有queue都沒有消費者,直接把消息返還給生產者,不用將消息入隊列等待消費者了。

  1. String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;

@param queue the name of the queue 隊列名

@param autoAck true if the server should consider messages acknowledged once delivered; false if the server should expect explicit acknowledgements 是否自動ACK。如果不自動ack,需要使用channel.ack、channel.nack、channel.basicReject 進行消息應答

@param callback an interface to the consumer object 消息消費的回調

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 來源 RabbitMQ是用Erlang實現的一個高并發高可靠AMQP消息隊列服務器。支持消息的持久化、事務、擁塞控...
    jiangmo閱讀 10,398評論 2 34
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • 什么叫消息隊列 消息(Message)是指在應用間傳送的數據。消息可以非常簡單,比如只包含文本字符串,也可以更復雜...
    lijun_m閱讀 1,364評論 0 1
  • 本文章翻譯自http://www.rabbitmq.com/api-guide.html,并沒有及時更新。 術語對...
    joyenlee閱讀 7,695評論 0 3
  • AMQP大致內容就是,將消息和隊列綁定起來,規定讓進入到交換機中的具有某個路由鍵的消息進入到指定隊列中去。 Rab...
    StevenMD閱讀 1,893評論 0 3