官网:http://www.rabbitmq.com
在一台测试机上安装,系统为CentOS 5.7. 参考:http://www.rabbitmq.com/install-rpm.html
必须先安装Erlang。rabbitmq 官网说,对于RHEL及其衍生出来的系统,强烈建议用 packaged version of Erlang。
启用EPEL: (根据版本不同的。 centos5用 epel-release-5-4.noarch.rpm)
wget http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
rpm -ivh epel-release-5-4.noarch.rpm
yum repolist 命令检查下,应该看到EPEL就对了。
对于5版的系统,EPEL5包含的Erlang版本较低,虽然可以运行,但是性能不如新版本。为了安装新版本,指定新的repository。执行
wget -O /etc/yum.repos.d/epel-erlang.repo http://repos.fedorapeople.org/repos/peter/erlang/epel-erlang.repo
yum install erlang
安装的时候提示缺少so文件。 后来把mirrors.163.com的yum源添加上,解决了。 (添加办法可以访问mirrors.163.com,看使用帮助)。
安装 RabbitMQ:
wget http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.4/rabbitmq-server-2.8.4.tar.gz
tar zxvf rabbitmq-server-2.8.4.tar.gz
这里采用的是编译源代码的方式,想省事应该可以用yum安装。官网上写的是yum安装。
编译需要python和simplejson.py。
索性升级下python。
yum update python
yum install python-simplejson.x86_64
cd rabbitmq-server-2.8.4
make的时候注意要有参数指定3个目录: TARGET_DIR SBIN_DIR MAN_DIR
make TARGET_DIR=/data/software/rabbitmq SBIN_DIR=/data/software/rabbitmq/sbin MAN_DIR=/data/software/rabbitmq/man
make install
if make: *** [install_dirs] Error 1:
make TARGET_DIR=/data/software/rabbitmq SBIN_DIR=/data/software/rabbitmq/sbin MAN_DIR=/data/software/rabbitmq/man install
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CENTOS6 rpm安装:
系统环境为CentOS6, 64bit。
RabbitMQ使用erlang,安装文档:
http://www.rabbitmq.com/install-rpm.html
官方建立使用rpm的方式安装erlang:
首先启用EPEL。EPEL的全称是 Extra Packages for Enterprise Linux,是一个软件源。
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-7.noarch.rpm
如果是5版,则是rpm -Uvh http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
安装erlang:
yum install erlang
安装RabbitMQ:
wget http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.6/rabbitmq-server-2.8.6-1.noarch.rpm
rpm --import http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
yum install rabbitmq-server-2.8.6-1.noarch.rpm
安装完成后,可使用
service rabbitmq-server start|stop 启动和停止。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
官网的get started文章写的很好:http://www.rabbitmq.com/getstarted.html
其中最主要的是work quere模式和publish/subscribe模式。 work queue模式下,当有多个consumer时,每一条消息只会发给一个consumer。而在publicsh/subscribe模式下,所有的consumer将会收到每一条消息。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Java API:
建立连接:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
Producer:
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 + "'");
Consumer:
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(QUEUE_NAME, true, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
程序结束时应该
channel.close();
connection.close();
在上述的例子中,rabbitMQ默认使用round robin的方式,将消息从队列中轮流发送consumer。 当每条消息代表一个耗时的计算过程时,可以有多个consumer并行运算。
RabbitMQ支持消息确认机制。 在消息确认机制下,如果RabbitMQ没有接收到确认消息,它就认为这个消息没有被正确处理,而会把它转发给另外一个consumer,以确保消息不会丢失。 这种确认机制是没有timeout限制的,只有在consumer连接死掉的情况,RabbitMQ才会把消息重新发送给其他consumer。接收消息的代码:
channel.basicConsume(QUEUE_NAME, true, consumer);
方法中的第2个参数的含义是,是否自动确认消息。 当设置为true时,等同于关闭消息确认机制(consumer一旦接收到消息,立即自动确认,不能保证消息被正确处理完成)。
启用消息确认机制的java代码:
QueueingConsumer consumer = new QueueingConsumer(channel);
boolean autoAck = false;
channel.basicConsume("hello", autoAck, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
//...
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
注意,一旦设置确认机制,一定不能忘记发送消息确认。否则当consumer退出时,它所处理的消息会被重新发送。RabbitMQ无法释放内存。
持久化:
如果要使RabbitMQ服务崩溃时仍然不丢失消息,那么必须把queue和message都声明为durable的。
boolean durable = true;
channel.queueDeclare("hello", durable, false, false, null);
channel.basicPublish("", "task_queue",
MessageProperties.PERSISTENT_TEXT_PLAIN,
message.getBytes());
持久化也不能保证100%不丢失。 如果要确保,还需要在代码级实现。
====================================================
publicsh/subscribe模式:
这种模式下,所有的consumer都会收到相同的message。 RabbitMQ把每一条message发给每一个consumer,而不是轮流。
其中引入了exchange的概念。
Producer代码:
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String message = getMessage(argv);
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
exchange有4种类型:direct, topic, headers 和fanout, 暂时只关心fanout。
关于这个和RabbitMQ更高级的应用,参见它的tutorials:http://www.rabbitmq.com/tutorials/tutorial-three-java.html