RabbitMQ课程翻译(第一课)

来源:互联网 发布:数据统计分析公司 编辑:程序博客网 时间:2024/06/05 04:08

说明:此文是对RabbitMQ官网上的Tutorials标题下Java版的翻译,可能存在不对之处,还望大神指正,官网地址如下:http://www.rabbitmq.com/tutorials/tutorial-one-java.html


简介


RabbitMQ是消息代理。在本质上,它接受来自生产者的消息,然后把它传送给消费者。在这个过程中,它可以根据你给它制定的规则对这些消息进行缓冲和保留。

一般来说,我们在使用RabbitMQ的时候需要使用到一些术语。


生产者


生产,或者说是发送。一段发送消息的程序我们成为“生产者”,可以使用“P”表示,如下图展现



队列


一个类似于信箱的队列。它存在RabbitMQ的内部。尽管消息流在RabbitMQ和你的应用中传递流动,但它们却是被存储在队列里面的。队列并不受任何约束,它本质上是一段无限的缓冲区,它可以存储任何你希望存储的消息。生产者向队列发送消息--消费者则从队列接收消息。我们可以使用下面的图形来描述它:



消费者


消费者意味着需要接收消息。消费者就是一段等待接收消息的程序。它可以使用“C”表示,其图形如下:



请留意,生产者,消费者和代理不一定非要安装在同一台机器上,实际上大多数应用都不是安装在同一台机器上的。


“Hello World”

(使用java客户端)

在课程的这一部分,我们会写两段Java代码;一段生产者发送单一消息的代码和一段消费者接受消息并打印展现的代码。我们会尽力避免谈到一些java API中的细节,以求能使得你的大部分注意力集中在如何实现这些功能。我们可以从最简单的“Hello World”说起。


在下图中,“P”是生产者,“C”是消费者,而中间的红色区域,则是RabbitMQ中的消息队列--用于保存消息的缓冲区。




java客户端库

RabbitMQ支持多种协议。这章课程中,我们使用AMQP 0-9-1协议,它是一个开放、通用的消息协议。RabbitMQ的客户端有多个语言的版本,此处我们使用java版的。

下载客户端库,查看他的签名。将其解压到你所希望的目录并取出jar文件


linux系统下解压命令

$ unzip rabbitmq-java-client-bin-*.zip
$ cp rabbitmq-java-client-bin-*/*.jar ./


(此处不会翻译)


现在我们有了它所依赖的java客户端,下面就要进行编程了。


发送消息




我们将我们发送消息的生产者代码块命名为Send,接收消息的消费者代码块命名为Recv。生产者需要先连接到RabbitMQ,发送一个单独的消息,然后退出。


在Send.java文件中,我们需要带入如下class文件


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 {      ...  }}



然后我们需要创建连接的服务


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



该连接是从socket连接中抽取出来的,它能够很好的支持各个版本协议的规则。我们将本地的机器作为代理并连接,故而此处的连接地址为“loaclhost”。如果我们想使用其他机器作为代理,需要提供其他机器的ip或机器名。


下面我们需要创建一个通道。

为了能够发送消息,我们需要声明一个能发动消息的队列,这样我们就能将消息放入其中:


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.close();connection.close();



完整的Send.java代码如下

import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;public class Send {  private final static String QUEUE_NAME = "hello";  public static void main(String[] argv) throws Exception {    ConnectionFactory factory = new ConnectionFactory();    factory.setHost("localhost");    Connection connection = factory.newConnection();    Channel channel = connection.createChannel();    channel.queueDeclare(QUEUE_NAME, false, false, false, null);    String message = "Hello World!";    channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));    System.out.println(" [x] Sent '" + message + "'");    channel.close();    connection.close();  }}



发送但却没有正确执行

如果你是第一次使用RabbitMQ,当你运行完生产者程序的时候却没有任何结果,不必怀疑,一定是哪里出了问题。查看代理机器是不是有足够的磁盘空间(默认至少需要1GB的磁盘空间)或者是它拒绝接收消息。当你需要的时候,也可以到查看代理机器的日志文件来更改磁盘空间限制大小。你可以在配置文件中修改disk_free_limit这个字段


接收消息


也就是我们的消费者。消费者从消息队列中取得消息,但却不像生产者生产完消息后自动退出,而是一直运行并监听这些消息以便将它们打印输出。


在Recv.java文件中我们依然需要引入class


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;



(此处翻译不好)


类似于生产者,我们先建立一个Recv类,然后是开启通道连接,声明一个用作消费的通道。注意,该通道必须是之前我们通道生产者所发布的。


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



请留意,我们在此处也声明了一个消息通道。那是因为,在正常的执行环境下,我们不能够确保我们在创建消费者之前就一定存在可供传递消息的通道。

我们还要告诉服务器从队列中提供我们需要的消息。消费者接收到的消息可能是错乱的(因为是异步接收),因此我们还需要在使用之前提供一个回调程序以确保我们所获得到的消息是正确的。这是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代码如下:


import com.rabbitmq.client.*;import java.io.IOException;public class Recv {  private final static String QUEUE_NAME = "hello";  public static void main(String[] argv) throws Exception {    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");    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);  }}


以下为Linux上的运行命令,此处不作翻译


/**

*20160322修改

**/

之前还以为没有人对RabbitMQ的教程文档进行翻译,所以才尝试着去做这样一件事,但,当我发现有其他人已经做了(翻译)而且比我翻译的还好,so,果断不去重复制造轮子,现贴上路径,需要的可以去看看http://blog.csdn.net/lmj623565791/article/details/37607165

0 0
原创粉丝点击