0.备注
CSDN也好,博客园也好,SegmentFloat也好,很多教程都有问题,或者没有自己测试过。经过将近两天的踩坑,结合部分已有文档总结了本教程,写完之后又按照步骤装了一台,亲测可用。
本文主要讲的是如何安装以及入门使用,深度进阶请参考其他大神的文章。
1.系统环境
CentOS 6.9 /64bit
默认路径为/usr/local,如果没有特殊需求,在进行下列操作前请先 cd /usr/local
2.获取Erlang和RabbitMQ源文件
2.1 Erlang
在http://erlang.org/download/下查找最新的源文件,我选择的是版本17,具体为【otp_src_17.0.tar.gz】。执行以下命令直接在Linux下获取源码:
wget http://erlang.org/download/otp_src_17.0.tar.gz
2.2 RabbitMQ
在http://www.rabbitmq.com/releases/rabbitmq-server查找到最新的源码版本,我选择的是v3.6.0版本,具体为【rabbitmq-server-3.6.0-1.noarch.rpm】。执行以下命令直接在Linux下获取源码:
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el6.noarch.rpm
3.编译安装Erlang
3.1 解压otp_src_17.0.tar.gz
tar -zxvf otp_src_17.0.tar.gz
可能会出现【gzip: stdin: not in gzip format】等错误,去掉z即可,即tar -xvf。
3.2 安装erlang编译环境
yum -y install make ncurses-devel gcc gcc-c++ unixODBC unixODBC-devel openssl openssl-devel
3.3 编译安装Erlang
①设置
#下面的是一整行代码,复制执行
cd otp_src_17.0
./configure \
--prefix=/usr/local/erlang \
--enable-smp-support \
--enable-threads \
--enable-sctp \
--enable-kernel-poll \
--enable-hipe \
--with-ssl
执行完后可能会出现错误:
忽略即可。
参数说明:
–prefix 指定安装目录
–enable-smp-support启用对称多处理支持
–enable-threads启用异步线程支持
–enable-sctp启用流控制协议支持(Stream Control Transmission Protocol,流控制传输协议)
–enable-kernel-poll启用Linux内核poll
–enable-hipe启用高性能Erlang(High Performance Erlang)
–with-ssl使用SSL包
②编译安装
make && make install
3.4 设置环境变量
环境变量为追加,首先打开profile
vi /etc/profile
然后在末尾追加下列语句
ERL_HOME=/usr/local/erlang PATH=$ERL_HOME/bin:$PATH export ERL_HOME PATH
保存后,重新激活环境变量
source /etc/profile
验证是否追加成功
[root@localhost otp_src_21.0]# echo $ERL_HOME
/usr/local/erlang
[root@localhost otp_src_21.0]# echo $PATH
/usr/local/erlang/bin:/usr/local/node/bin:/usr/local/java/jdk1.8.0_111/bin:/usr/local/java/jdk1.8.0_111/jre/bin:/usr/local/node/bin:/in
3.5 安装RabbitMQ
[root@localhost local]# rpm -i rabbitmq-server-3.6.0-1.noarch.rpm
warning: rabbitmq-server-3.6.11-1.el6.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 6026dfca: NOKEY
error: Failed dependencies:
erlang >= R16B-03 is needed by rabbitmq-server-3.6.11-1.el6.noarch
socat is needed by rabbitmq-server-3.6.11-1.el6.noarch
最后一行信息为缺少socat,一般不会出现,如果出现解决方法为:
yum -y install epel-release
yum -y install socat
再次尝试 rpm -i rabbitmq-server-3.6.0-1.noarch.rpm
倒数第二行的错误为依赖关系所导致,解决方法:
使用命令rpm -i --nodeps rabbitmq-server-3.6.0-1.noarch.rpm
忽略依赖。
3.6 启停RabbitMQ
[root@localhost local]#service rabbitmq-server start
启动服务
[root@localhost local]#service rabbitmq-server etc
查看哪些命令可以使用
[root@localhost local]#service rabbitmq-server stop
停止服务
[root@localhost local]#service rabbitmq-server status
查看服务状态
启动时可能会出现下列错误
运行命令: [root@localhost local]# ln -s /usr/local/erlang/bin/erl /usr/bin/erl
后再次执行即可。
如果出现其他错误也可以尝试运行此命令
3.7 添加rabbitmq到启动项
[root@localhost local]# chkconfig rabbitmq-server on
4 RabbitMQ管理
4和5模块参考博客园一大神,但是找不到出处地址了十分抱歉
4.1 RabbitMQ配置文件
从官网来看,RabbitMQ有两个配置文件,使用RPM方式安装:
RabbitMQ的根目录:/var/lib/rabbitmq
RabbitMQ的配置文件目录:/etc/rabbitmq/
RabbitMQ的日志文件目录:/var/log/rabbitmq
两个配置文件分别是:
rabbitmq.config
rabbitmq-env.conf
RabbitMQ环境变量配置文件,变量名称及内容可参考:http://www.rabbitmq.com/configure.html#define-environment-variables
配置在文件中的变量使用参考中的标准变量,但是需要将变量前缀RABBITMQ_去掉
官网中提到的关于变量的默认内容及含义可参考:http://www.rabbitmq.com/relocate.html
配置文件相关资料:http://www.rabbitmq.com/configure.html#configuration-file
4.2 web管理界面
RabbitMQ有一个web管理的界面,可通过ip:15672进行访问,但是安装好之后默认的用户guess和密码guest是不能用来做远程登录的,这对用户名和密码只能在本地访问,说是为了安全,因此就必须创建一个用户管理员权限的新用户,记得在防火墙设置中添加15672端口。
管理插件启动: rabbitmq-plugins enable rabbitmq_management
添加用户: rabbitmqctl add_user admin admin
添加权限: rabbitmqctl set_permissions -p "/" admin "." "." "."
修改用户标签: rabbitmqctl set_user_tags admin administrator
通过上面三步即新建了一个拥有管理员权限的用户admin,密码admin,此时就可以在浏览器中输入ip:15672,然后用admin进行登录。
至此,RabbitMQ全部安装完成
5 卸载
未经实践,仅供参考
5.1 卸载rabbitmq
命令:rpm -qa|grep rabbitmq
结果:rabbitmq-server-3.6.1-1.noarch
命令:rpm -e --nodeps rabbitmq-server-3.6.1-1.noarch
5.2 卸载erlang
命令:rpm -qa|grep erlang
结果:esl-erlang-18.3-1.x86_64
命令:rpm -e --nodeps esl-erlang-18.3-1.x86_64
或:yum remove erlang
6 SpringBoot中的使用
6.1 添加所需依赖
在pom.xml中添加RabbitMQ所需依赖及SpringBoot对AMPQ(Advanced Message Queuing Protocol,高级消息队列协议)的支持。
<!-- RabbitMQ依赖 -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.9.0</version>
</dependency>
<!-- 添加springboot对amqp的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>${springboot.version}</version>
</dependency>
6.2 添加配置类
@Configuration
public class RabbitConfig {
@Value("${rabbitmq.host}")
private String host;
@Value("${rabbitmq.username}")
private String username;
@Value("${rabbitmq.password}")
private String password;
@Value("${rabbitmq.virtualhost}")
private String virtualhost;
@Value("${rabbitmq.port}")
private int port;
@Value("${rabbitmq.queue}")
private String queue;
@Bean
public Queue createQueue() {
return new Queue(queue,true, false, false);
}
@Bean
public ConnectionFactory connectionFactory(){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses(host);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualhost);
connectionFactory.setPort(port);
connectionFactory.setPublisherConfirms(true);
return connectionFactory;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
return new RabbitAdmin(connectionFactory);
}
}
6.3 添加监听类
利用@RabbitListener注解,配置好queues即可自动配置exchange。
@Component
@RabbitListener(queues = "${rabbitmq.queue}")//自动识别exchange
public class Consumer {
private static Logger LOGGER = Logger.getLogger(Consumer.class);
@Autowired
private CtripRemoteService ctripremoteservice;
/**
* 监听器 消费者
* @param body
*/
@RabbitHandler
public void process(byte[] body) {//接收类型根据发送类型调整
LOGGER.info("ReceiverA : " + body);
}
@RabbitHandler
public void process(String body) {//接收类型根据发送类型调整
LOGGER.info("ReceiverB : " + body);
}
}
6.4 添加发送类
@RestController
@RequestMapping("/rabbit")
public class SendController {
public final static String QUEUE_NAME="queueName";
@Autowired
private AmqpTemplate rabbitTemplate;
@RequestMapping("/sendMessage")
public void SendMessage() {
String sendMsg = "hello -------------------------------- " + new Date();
rabbitTemplate.convertAndSend(QUEUE_NAME, sendMsg);
}
}
6.5 启动项目即可根据配置开始监听或发送
7 附录,两个测试类
7.1 接收测试类
public class RecvTest {
public final static String QUEUE_NAME="hello";
public static void main(String[] args) throws IOException, TimeoutException {
// 创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置RabbitMQ地址
factory.setHost("localhost");
factory.setVirtualHost("/");
factory.setUsername("guest");
factory.setPassword("guest");
factory.setPort(5672);
//创建一个新的连接
Connection connection = factory.newConnection();
//创建一个通道
Channel channel = connection.createChannel();
//声明要关注的队列
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
System.out.println("Customer Waiting Received messages");
//DefaultConsumer类实现了Consumer接口,通过传入一个频道,告诉服务器我们需要那个频道的消息,
//如果频道中有消息,就会执行回调函数handleDelivery
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("Customer Received '" + message + "'");
}
};
//自动回复队列应答 -- RabbitMQ中的消息确认机制
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
7.2 发送测试类
public class SendTest {
public final static String QUEUE_NAME="queue";
public final static String ROUTING_KEY="hello";
public final static String EXCHANGE_NAME="exchange";
public static void main(String[] args) throws Exception {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置RabbitMQ相关信息
factory.setHost("localhost");
factory.setUsername("guest");
factory.setPassword("guest");
factory.setPort(5672);
//创建一个新的连接
Connection connection = factory.newConnection();
//创建一个通道
Channel channel = connection.createChannel();
String message = "啦啦啦";
// 声明一个队列 允许注释
//channel.queueDeclare("wei",false,false,false,null);
// 声明一个交换机 允许注释
//channel.exchangeDeclare(EXCHANGE_NAME, "direct");
//绑定队列、交换机、RoutingKey 允许注释
//channel.queueBind(QUEUE_NAME, "lalal", ROUTING_KEY);
//发送消息到队列中 不允许注释
channel.basicPublish("", ROUTING_KEY, null, message.getBytes("UTF-8"));
System.out.println("Producer Send +'" + message + "'");
//关闭通道和连接
channel.close();
connection.close();
}
}