【RabbitMQ】HelloWorld

初识RabbitMQ

RabbitMQ是一个消息代理人。它的主要目的很简单:接受并推送消息。我们可以将它理解为一个邮局:当你邮寄一封邮件到邮箱里,可以非常确定邮递员会将它送到收件人手中。打这种比方来将RabbitMQ看做一个邮局,邮箱,邮递员。

RabbitMQ和邮局的主要区别在于它不需要纸,它所接收的,存贮的以及推送的是二进制数据----消息。

下面介绍一些术语:

生产(Producing)就是发送数据,一个发送消息的程序被称为生产者(Producer)

 

 

队列(queue)代表着邮箱。它依附在RabbitMQ内部。尽管消息在RabbitMQ和你的应用程序之间传输,它们也只能被保存在队列中。一个队列没有被绑定任何限制,它可以存放任意多的消息----它本质上就是一个无限大小的缓冲区。多个生产者可以发送消息到同一个队列中,多个消费者也可以从同一个队列中消费消息。

 

 

 

消费(Consuming)即接收。一个等待接收消息的程序被称为消费者(Consumer)。 

 

 

注意:生产者,消费者,代理人不需要在同一台机器上。

"HelloWorld"

这部分我们将使用Java写两个小程序:一个生产者发送一条消息,一个消费者接收并打印该条消息(先决条件:要在本地启动RabbitMQ服务器http://www.rabbitmq.com/install-debian.html)。流程如下图所示:

 

 

导入maven依赖:

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

Sending

我们将会调用Send和接收端Recv。发送端将会连接到RabbitMQ服务,发送一条消息后退出。

在Send.java,导入下列包:

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

初始化类和队列名:

public class Send {
  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv)
      throws java.io.IOException {
      ...
  }
}

然后创建到RabbitMQ服务的连接:

 ConnectionFactory factory = new ConnectionFactory();
 factory.setHost("localhost");
 Connection connection = factory.newConnection();
 Channel channel = connection.createChannel();

这个connection抽象了socket连接,并且为我们管理好了协议版本和安全认证等。这里我们连接的是在本机的代理人----因为127.0.0.1.如果你想连接到其它的机器上,只需要更改IP地址就可以。

下面创建一个channel,大多数API在它里面驻留来获取数据。

我们必须声明一个队列来向其中发送消息:

    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和connection:

    channel.close();
    connection.close();

Receiving

接收方负责推送从RabbitMQ得到的消息,不像发送方只发送单条消息,我们需要让接收方保持运行状态,不断监听消息并打印。

 

 

 

 

导入的包与发送时基本相同:

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

额外的DefaultConsumer是Consumer接口的实现类,我们将用它来缓冲服务器推送给我们的消息。

初始化和sender一样,打开一个connection和一个channel,声明我们要消费消息的队列。注意它需要与发送消息的队列相匹配。

public class Recv {
  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv)
      throws java.io.IOException,
             java.lang.InterruptedException {

    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");
    ...
    }
}

注意我们在这里也声明了队列,这是因为可能receiever运行在sender之前,我们要确保在监听消息时这个队列是存在的。

现在我们要告诉服务器准备从队列中发送消息。由于服务器是异步的推送给我们消息,我们以对象的形式提供一个回调,它将缓冲消息,直到我们准备好使用它。这就是DefaultConsumer的作用。

    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);

最后运行Recv.java,他会开始监听消息,此时我们运行一次Send.java,就会发送一条消息,同时Recv会接收一条消息。

 

 
posted @ 2017-01-05 10:03  大地的谎言  阅读(362)  评论(0编辑  收藏  举报