引用百度百科:

MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。

消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。

排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。其中较为成熟的MQ产品有IBM WEBSPHERE MQ。

MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取或者订阅队列中的消息。MQ和JMS类似,但不同的是JMS是SUN JAVA消息中间件服务的一个标准和API定义,而MQ则是遵循了AMQP协议的具体实现和产品。

在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。

RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统。他遵循Mozilla Public License开源协议。


    现在公司项目需要,要安装RabbitMQ,在安装之前,要确定依赖的环境要有:erlang、python、simplejson,下面将我安装过程过记录如下。

一、安装erlang

    首先下载otp_src_R16B03.tar.gz

    依次执行如下命令:

tar -zxf otp_src_R16B.tar.gz    #具体版本
cd otp_src_R16B
./configure --prefix=/opt/
make
make install

    在安装Erlang过程中可能会出现如下问题:

checking for kstat_open in -lkstat... no
checking for tgetent in -lncurses... no
checking for tgetent in -lcurses... no
checking for tgetent in -ltermcap... no
checking for tgetent in -ltermlib... no
configure: error: No curses library functions found
configure: error: /bin/sh '/home/niewf/software/erlang_R13B01/erts/configure' failed for erts

    在网上找了一下,发现该问题在安装Mysql的时候也可能发生。

    具体原因为:缺少ncurses安装包。因此要先安装ncurses,安装过程如下:

    a)、如果你的系统是RedHat系列:

yum list|grep ncurses
yum -y install ncurses-devel
yum install ncurses-devel

    b)、如果你的系统是Ubuntu或Debian:

apt-cache search ncurses
apt-get install libncurses5-dev

    安装之后,验证是否安装成功,执行以下命令并显示结果:

[root@sckf otp_src_R16B]# erl
Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:24:24] [async-threads:10] [hipe] [kernel-poll:false]
 
Eshell V5.10.1  (abort with ^G)

    表示erlang已经安装成功。


二、安装python

    在操作系统安装时要选择上python安装,CRM5.7的OS是6.2,所以python不需升级。

    如果机器的python版本过低,编译simplejson时会出错,需安装python较新版本,我这里使用的是Python-3.4.1.tgz

tar -zxf Python-3.4.1.tgz 
cd Python-3.4.1
./configure
make
make  install
mv/usr/bin/python /usr/bin/python-old
ln -s /usr/local/bin/python /usr/bin/python

    安装完成后验证python版本

[root@sckf ~]# python -V
Python 3.4.1  
[root@sckf ~]# which python
/usr/bin/python
[root@sckf~]#


三、安装simplejson

    一般都未安装simplejson,如果机器未安装,在安装过程中会出现出现如下提示: 

You don't appear to have simplejson.py installed

    这时需先安装simplejson,这里安装最新的simplejson:simplejson-3.3.1.tar.gz。

    然后执行以下命令:

tar xvzf simplejson-2.6.1.tar.gz
cd simplejson-2.6.1
python setup.py install


四、安装rabbitmq

    在http://www.rabbitmq.com/download.html下载相应安装包,请使用当前最新的稳定版本。

    我这里使用的版本是:rabbitmq-server-generic-unix-3.2.2.tar.gz

    (注意:请不要在内核是pae版本的os上安装,因为rabbitmq的可用内存会因为pae而大大减小。

1.  直接使用generic版本(推荐的方式)

[root@localhost rabbitmq]# tar -zxfrabbitmq-server-generic-unix-3.2.2.tar.gz 
[root@localhost rabbitmq]# ll
总计 3804
drwxr-xr-x 8 root root    4096 11-07 18:54 rabbitmq_server-3.2.2
-rw-r--r-- 1 root root 3886276 11-20 11:23rabbitmq-server-generic-unix-3.2.2.tar.gz
[root@localhost rabbitmq]# cd rabbitmq
-bash: cd: rabbitmq: 没有那个文件或目录
[root@localhostrabbitmq]# cd rabbitmq_server-3.2.2/

2.  启动rabbitmqserver

./rabbitmq-server  -detached

(可能会因为没有日志文件夹而启用失败,只需要创建相应文件夹后重新运行该命令即可)

    执行一下命令:

make TARGET_DIR=/opt/rabbitmq_server-3.2.2 SBIN_DIR=/opt/rabbitmq_server-3.2.2l/sbin MAN_DIR=/opt/rabbitmq_server-3.2.2/man make install

3.  启用web管理界面

$rabbimq_home$/sbin/  ./rabbitmq-plugins enable rabbitmq_management

    启用web管理插件时会由于在/etc下无rabbitmq目录而失败,请建立/etc/rabbitmq目录;

    之后我们就可以通过http://localhsot:15672/来访问web管理界面了

    交易日志中间件需要启用stomp插件(看应用是否需要再启用)

$rabbimq_home$/sbin/  ./rabbitmq-plugins enable rabbitmq_stomp


五、集群配置(单节点部署不需要这部分)

    假设有两个节点10.109.1.149,10.109.1.158

    (1)修改机器的hostname,例:

10.109.1.149 : export  HOSTNAME=”server149”
10.109.1.158 : export  HOSTNAME=”server158”

     注意:

        这里只是会话级修改,所以必须修改/etc/sysconfig/network文件才行。

    (2)修改/etc/hosts文件,使得DNS可解析HOSTNAME,例:

10.109.1.149 server149
10.109.1.158 server158

    (3)保证两台机器的.erlang.cookie文件相同,以便他们之间能互相通信

     将141的文件(/root/.erlang.cookie)scp至143,然后执行如下命令:

cat erlang.cookie.141 >>.erlang.cookie

    再将.erlang.cookie拷贝至其他机器即可,其目的是要将集群里的所有节点的.erlang.cookie文件cat到一个中,然后再拷贝至其他所有的节点,这样所有节点的.erlang.cookie文件一致,他们才能够互信。

    (4)假设158作为磁盘节点,149作为内存节点

    启动158的rabbitmqserver

$rabbimq_home$/sbin/ ./rabbitmq-server -detached

    (5)启动149的rabbitmqserver并以内存节点的形式加入集群

$rabbimq_home$/sbin/  ./rabbitmq-server -detached
$rabbimq_home$/sbin/  ./rabbitmqctl stop_app
$rabbimq_home$/sbin/  ./rabbitmqctl reset
$rabbimq_home$/sbin/  ./rabbitmqctl join_cluster --ram rabbit@server158
$rabbimq_home$/sbin/  ./rabbitmqctl start_app

    至此集群环境搭建成功,可以使用rabbitmqctl cluster_status来查看集群状态。

六、测试实例

ReceiveTest:

package com.asiainfo.mq.rabbitmq.rabbitmqtest;

import java.util.Date;

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

public class ReceiveTest {
	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("10.5.1.11");
		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");
		
		QueueingConsumer consumer = new QueueingConsumer(channel);
	    channel.basicConsume(QUEUE_NAME, true, consumer);

	    Date nowTime = new Date();
	    
	    while (true) {
	      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
	      String message = new String(delivery.getBody());
	      System.out.println("RecieveTime: " + nowTime);
	      System.out.println(" [x] Received '" + message + "'");
	    }

	}
}


SendTest:

package com.asiainfo.mq.rabbitmq.rabbitmqtest;

import java.util.Date;

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

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

	public static void main(String[] argv) throws java.io.IOException {
		try {
			ConnectionFactory factory = new ConnectionFactory();
		    factory.setHost("10.5.1.11");
		    Connection connection = factory.newConnection();
		    Channel channel = connection.createChannel();
		    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
		    
		    Date nowTime = new Date();
		    String message = "Hello World!	I'm RabbitMQ!!" + "  SendTime: " + nowTime;
		    channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
		    System.out.println(" [x] Sent '" + message + "'");
		    
		    channel.close();
		    connection.close();
		    System.out.println("Over Send.");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}