Rabbit MQ - tutorial 1:hello rabbit mq

Rabbit MQ

RabbitMQ是一個消息代理:它接受和轉發消息。 你可以把它想象成一個郵局,RabbitMQ是郵箱,郵局和郵遞員。

幾個重要概念

  • 生產者(Producer):消息發送者即爲生產者
  • 消息隊列(Queue):本質上是一個消息緩衝區,可以理解成郵箱,容量受限於主機內存和磁盤;多個生產者可以往同一個消息隊列發消息,多個消費者可以從同一個消息隊列接收消息
  • 消費者(Consumer):消息接收者即爲消費者
  • 代理(Broker):中間人,它接受消息,轉發消息

通常情況下,Producer,Consumer,Broker它們都不在同一臺主機上。

Tutorial 1 - Hello Rabbit MQ

本例使用:rabbitmq_server-3.7.4, Intellij Idea; 並且Producer,Broker,Consumer都在統一電腦上。
(1)Broker:直接使用本機,Rabbit MQ Server安裝(見下面安裝部分)完成後,直接從開始菜單“RabbitMQ Service - start”啓動服務。(2)實現Publisher,通過一個線程,每隔5s發送一條消息到Broker。(3)實現Consumer,從Broker接收消息。

Rabbit MQ安裝

下載並安裝Erlang

  • 添加環境變量:ERLANG_HOME=D:\Program Files\erl9.3

  • path添加:%ERLANG_HOME%\bin

下載安裝Rabbit MQ

  • 確保Erlang cookie一致:

To ensure Erlang cookie files contain the same string, copy the .erlang.cookie file from the Windows service directory [%USERPROFILE%.erlang.cookie (usually C:\WINDOWS\system32\config\systemprofile)] to replace the user .erlang.cookie[%HOMEDRIVE%%HOMEPATH%.erlang.cookie (usually C:\Users\%USERNAME%.erlang.cookie for user %USERNAME%)].
注意它們倆之間的版本對應關係。

Rabbit MQ Service運行

安裝完成之後,在開始菜單上有常用命令的快捷方式:
RabbitMQ Service - start
RabbitMQ Service - stop
RabbitMQ Command Prompt(sbin dir)
這裏寫圖片描述
通過RabbitMQ Command Prompt(sbin dir)開啓management plugin:rabbitmq-plugins enable rabbitmq_management
這裏寫圖片描述
PS: 裝該plugin遇到過:
問題1 - “Failed to create cookie file ‘h:/.erlang.cookie’: enoent”這樣的問題,解決方案,設置cookie所在的目錄,如下:

//我這裏是:C:\Users\%USERNAME%
set HOMEDRIVE=[location of ".erlang.cookie"]
rabbitmq-plugins.bat enable rabbitmq_management

問題2 - 運行rabbitmqctl status命令,報錯:*empd reports: node ‘rabbit’ not running at all no other nodes on XXX.
解決方案步驟如下:
1)停止rabbitmq服務
2)清空c:\user\%USERNAME%\AppData\Roaming\RabbitMQ\log
3)重啓rabbitmq服務

這樣就可以通過http://localhost:15672使用RabbitMQ management
使用默認的user=guest,password=guest登錄
這裏寫圖片描述

想要了解RabbitMQ使用的相關端口,參見http://www.rabbitmq.com/install-windows.html頁面。

通過 RabbitMQ Service - start啓動服務,這就相當於把代理(broker)運行起來了,Producer就可以往它發送message,而Consumer也可以從它接收message。

實現Publisher(Publisher往Broker發送消息)

  • 運行Intellij Idea 創建一個maven的quickstart類型的項目
POM.xml依賴如下

<!-- 
    rabbit mq client depend on SLF4J API and SLF4J Simple
    Please note SLF4J Simple is enough for these tutorials
    but you should use a full-blown logging library 
    like Logback in production.
-->
<dependencies>
    <dependency>
      <groupId>com.rabbitmq</groupId>
      <artifactId>amqp-client</artifactId>
      <version>5.2.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-log4j12</artifactId>
      <version>1.7.25</version>
    </dependency>
  </dependencies>
  • 新加一個Send類和一個線程實現類用於發送消息
    代碼實現如下,詳細步驟見代碼註釋
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

//Publisher發送完消息就結束
//The publisher(MySendTask) will connect to RabbitMQ, 
// send message per 5 seconds, 
// until the thread stopped and then exit.
public class MySendTask implements Runnable {
    //define name of the queue
    private final static String QUEUE_NAME = "hello";
    //connection to the server(broker)
    private Connection rbtMqConn;
    //
    private Channel rbtMqChnl;

    private boolean isStop = false;

    public void setIsStop(boolean stop){
        this.isStop = stop;
    }

    @Override
    public void run() {
        try{
            //1.create a connection to the server
            //The connection abstracts the socket connection,
            //and takes care of protocol version negotiation 
            //and authentication and so on for us.
            ConnectionFactory factory = new ConnectionFactory();
            //Here we connect to a broker on the 
            //local machine - hence the localhost.
            //consumer也從這個broker接收消息,也可以使用其它主機,比如172.16.21.10
            factory.setHost("localhost");
            rbtMqConn = factory.newConnection();

            //2.we create a channel, which is where most of the 
            //API for getting things done resides.
            rbtMqChnl = rbtMqConn.createChannel();

            //3.To send, we must declare a queue for us to send to; 
            // then we can publish a message to the queue
            //Consumer也需要指定使用該名字的channel
            rbtMqChnl.queueDeclare(QUEUE_NAME, false, false, false, null);

            //message to send
            String message = "Hello Rabbit MQ!";

            //send message per 5s
            while (!isStop){
                rbtMqChnl.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
                System.out.println(" [x] Sent '" + message + "'");
                Thread.sleep(5000);
            }

            //4.Lastly, we close the channel and the connection;
            rbtMqChnl.close();
            rbtMqConn.close();
        }catch(Exception ex){
            System.out.println(ex.getMessage());
        }
        System.out.println(" Send task stop");
    }
}

//message publisher
public class Send {
    public static void main(String[] argv) throws Exception {
        MySendTask sendTask = new MySendTask();
        Thread thread = new Thread(sendTask);
        thread.start();
        //let the thread run 60 seconds
        Thread.sleep(60000);
        sendTask.setIsStop(true);
    }
}

實現Consumer(Consumer從Broker接收消息)

和Publisher類似,Consumer也要打開鏈接和通道(channel),並且要和Publisher匹配。步驟見如下代碼。

import com.rabbitmq.client.*;
import java.io.IOException;

//consumer和publisher不一樣,它一直運行,監聽接收消息
//Our consumer is pushed messages from RabbitMQ, 
// so unlike the publisher which publishes some messages and stop, 
// we'll keep it running to listen for messages and print them out.
public class Recv {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        //we open a connection and a channel,
        // and declare the queue from which we're going to consume.
        // Note this matches up with the queue that send publishes to.
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        //Note that we declare the queue here, as well.
        // Because we might start the consumer before the publisher,
        // we want to make sure the queue exists before we try to consume messages from it.
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        //Since it will push us messages asynchronously,
        // we provide a callback in the form of an object
        // that will buffer the messages until we're ready to use them.
        // That is what a DefaultConsumer subclass does.
        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.basicConsume(QUEUE_NAME, true, consumer);
    }
}

運行結果截圖

這裏寫圖片描述

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