rabbitmq 官网教程 http://www.rabbitmq.com/getstarted.html
rabbitmq是什么,按照官网的说法
With more than 35,000 production deployments of RabbitMQ world-wide at small startups and large enterprises, RabbitMQ is the most popular open source message broker.
RabbitMQ is lightweight and easy to deploy on premises and in the cloud. It supports multiple messaging protocols. RabbitMQ can be deployed in distributed and federated configurations to meet high-scale, high-availability requirements.
RabbitMQ是最广泛部署的开源消息代理。
随着RabbitMQ在全球范围内在小型初创企业和大型企业中的35000多个生产部署,RabbitMQ是最受欢迎的开源消息代理。
RabbitMQ是轻量级的,易于部署在本地和云上。它支持多个消息传递协议。RabbitMQ可以部署在分布式和联邦配置中,以满足高规模、高可用性需求。
关于rabbitmq的安装,我们在上一篇的文章中已经介绍了,本篇我们来写一个以下rabbitmq的入门案例。
rabbitmq中最简单的消息收发模型就是:一方发送一方直接接收(exchange为"",收发双方根据相同的queue名称关联),如图:
发送方代码 Sender.java:
package com.tingcream.rabbitmq.helloworld;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
* (AMQP DEFAULT)
* @author jelly
*
*/
public class Sender {
private final static String QUEUE_NAME = "helloWorld";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
//主机 端口 vhost 用户名 密码
factory.setHost("192.168.9.102");
factory.setUsername("rabbitmq");
factory.setPassword("rabbitmq123");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
/*queueDeclare
* 第一个参数 queue: 队列名称
* 第二个参数 durable: 是否持久, true则当rabbitmq broker重启后队列仍在
* 第三个参数 exclusive: 是否是独占队列(创建者可以使用的私有队列,断开后自动删除)
* 第四个参数 autoDelete ,当所有消费者连接断开时,是否自动删除队列 ,true是
* 第五个参数 arguments ,可选参数map
*/
//channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments)
channel.queueDeclare(QUEUE_NAME, false, false,false, null);
String message = "Hello rabbitmq";
//exchagne名称默认为 (AMQP DEFAULT) direct
//channel.basicPublish(exchange, routingKey, props, body);
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
//关闭连接
channel.close();
connection.close();
}
}
接收方代码
package com.tingcream.rabbitmq.helloworld;
import java.io.IOException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
public class Receiver {
private final static String QUEUE_NAME = "helloWorld";
public static void main(String[] argv)
throws Exception {
ConnectionFactory factory = new ConnectionFactory();
//主机 端口 vhost 用户名 密码
factory.setHost("192.168.9.102");
factory.setUsername("rabbitmq");
factory.setPassword("rabbitmq123");
factory.setPort(AMQP.PROTOCOL.PORT);
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// channel.queueDeclare(queue, durable, exclusive, autoDelete, arguments)
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 + "'");
}
};
//收取消息 自动ack autoAck为true
//channel.basicConsume(queue, autoAck, callback)
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
注意:
1、在我们这个案例中,没有使用到交换机exchange,实际上exchange的名称为空字符"",交换机类型为direct,收发双方是通过一个相同的queue名称——helloworld来产生关联的。
2、 channel.queueDeclare(QUEUE_NAME, false, false,false, null); 这句声明queue的代码很重要,并且这句代码在收发双方中必须保持一致。若收发双方声明queue的特性不同,不仅无法正确地收发消息,而且在收、发程序启动时会抛出异常,因为rabbitmq服务器上不允许队列(名称、特性)的重复声明。
3 收、发双方代码中都有个channel.queueDeclare(QUEUE_NAME, false, false,false, null)这句代码很重要,里面每个参数(最后一个参数除外)都具有着重要的作用,不同参数值的组合所声明的队列的特性也不一样:
第一个参数 queue: 队列名称
第二个参数 durable: 是否持久, true则当rabbitmq broker重启后队列仍在
第三个参数 exclusive: 是否是独占队列(创建者可以使用的私有队列,断开后自动删除)
第四个参数 autoDelete ,当所有消费者连接断开时,是否自动删除队列 ,true是
第五个参数 arguments ,可选参数map,附加参数
4 、在接收方代码中有一句 channel.basicConsume(QUEUE_NAME, true, consumer) ,这句代码很重要,其中第二个参数true表示是否自动确认(autoAck)为true (这是示例程序,我们为了简便起见就自动ack了)。然而在大多数情况下一般应该设置为false,让我们的程序业务处理完毕后,再手动确认,告知rabbitmq服务器这条消息我们已确认处理(消费)完毕了。
最后我们启动rabbitmq服务器,运行发送方和接收方程序:
./rabbitmq-server -detached #后台进程启动服务
http://192.168.9.102:15672/ #访问管理后台