RabbitMQ入门(RabbitMQ的安装 + 解决RabbitMQ安装过程中的版本等问题 + 解决启动RabbitMQ服务失败等问题 + Java客户端使用)
1. 前言——参考官网
1.1 官网地址
1.2 注意版本对照
- 注意Linux版本支持的RabbitMQ版本
- 注意Linux支持的 Erlang 版本
- 注意RabbitMQ 支持的Erlang版本
- 更多的版本对应关系,看下面的链接
https://www.rabbitmq.com/which-erlang.html.
- 更多的版本对应关系,看下面的链接
2. 下载、安装
2.1 下载 并 安装erlang
2.1.1 查看 Linux 版本
- 我这边是centos,命令如下:
cat /etc/centos-release
2.1.2 查看当前系统支持的erlang版本
- 命令如下:
uname -a
2.1.3 下载 erlang
- 下载地址:
https://github.com/rabbitmq/erlang-rpm. - 根据 Linux 版本 和 系统支持的erlang 版本,下载对应的erlang,如下:
- 所以,我这里下载的是
Erlang 23.3.4.18
(注意:如果是自己学习,建议换CenOS8,也最好直接换其他发行版,比如 Ubuntu 等),如下:
2.1.4 安装 erlang
- 安装命令,如下:
rpm -ivh erlang-23.3.4.18-1.el7.x86_64.rpm
2.1.5 遇到的问题
- 说明:这个问题是安装
erlang-23.3.4.18-1.el8.x86_64.rpm
(el8
)出的问题,但是安装erlang-23.3.4.18-1.el7.x86_64.rpm
(el7
)没有问题,上面查的我的Linux系统支持的是el7
,所以不知道是不是版本的问题! - 如下:
error: Failed dependencies: libtinfo.so.6()(64bit) is needed by erlang-23.3.4.18-1.el8.x86_64 libz.so.1(ZLIB_1.2.7.1)(64bit) is needed by erlang-23.3.4.18-1.el8.x86_64
- 解决问题:
加上--nodeps --force
,该命令的作用: 不再分析包之间的依赖关系而直接安装rpm -ivh erlang-23.3.4.18-1.el8.x86_64.rpm --nodeps --force
2.2 安装 socat
- 安装命令如下:
yum install socat -y
2.3 下载、安装rabbitmq-server
2.3.1 下载rabbitmq-server
- 下载 RabbitMQ 时,注意上面下载的Erlang的版本(
Erlang 23.3.4.18
),然后再找对应的RabbitMQ版本- 下载地址1:找新版本好找,找老版本费劲,如下:
https://github.com/rabbitmq/rabbitmq-server/releases. - 下载地址2:rpm 仓库
https://packagecloud.io/rabbitmq.
- 下载地址1:找新版本好找,找老版本费劲,如下:
- 根据Linux系统 以及 Erlang版本,找到对应的rabbitmq版本如下:
2.3.2 安装rabbitmq-server
- 安装命令如下:
rpm -ivh rabbitmq-server-3.9.13-1.el7.noarch.rpm
3. 启动服务
3.1 启动服务
- 最好使用下面的命令启动:
service rabbitmq-server start
- 当然也可以去安装目录启动,安装之后,找安装目录:
whereis rabbitmq
- 进入安装的
sbin
目录:
- 启动服务:
./rabbitmq-server start
- 查看服务是否启动:
ps -ef | grep rabbitmq
3.2 启动服务失败问题
3.2.1 版本问题
- 如果启动失败,检查erlang是否安装,或者erlang版本是否正确,检查命令如下:
rpm -qa|grep erlang
- 如果
erlang
版本安装错了,可以卸载重装(卸载前先卸载rabbitmq,因为rabbitmq 依赖 erlang),卸载命令如下:# 1. 卸载rabbitmq-server rpm -e rabbitmq-server rm -rf /usr/lib/rabbitmq # 2. 卸载erlang rpm -e erlang rm -rf /usr/lib64/erlang
- 然后重新安装正确版本即可。
4. 访问管理界面
4.1 开启图形化管理界面
- 如果rabbitmq正在启动,先停止服务,然后再安装web界面插件,命令如下:
rabbitmq-plugins enable rabbitmq_management
4.2 查看占用的端口
-
如下:
ps -ef | grep rabbit lsof -i | grep pid
4.3 开放 15672 端口
- 参考下面的文章:
linux下查看防火墙状态、关闭防火墙、开放关闭端口等.
4.4 访问管理界面
- 访问地址:
http://服务器IP:15672/
4.5 登录问题
4.5.1 问题
- 登录,用户名 和 密码 都是:guest,登录之后,提示如下
4.5.2 解决问题——创建新用户
- 进入安装目录,查看用户和角色:
cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.9.13/sbin ./rabbitmqctl list_users
- 创建新用户
- 第 1 步:添加 mqAdmin 用户并设置密码123456
rabbitmqctl add_user mqAdmin 123456
- 第 2 步:设置用户角色(设置 mqAdmin 用户为administrator角色)
rabbitmqctl set_user_tags mqAdmin administrator
- 第 3 步:设置用户权限(指定允许访问的vhost以及write/read)
rabbitmqctl set_permissions -p "/" mqAdmin ".*" ".*" ".*"
- 第 4 步,查看:
- 第 1 步:添加 mqAdmin 用户并设置密码123456
4.6 登录——使用新用户
- 使用上面新创建的
mqAdmin
用户登录进去,如下:
5. 启动、停止服务等相关命令
5.1 启动命令
5.1.1 启动方式
- 方式1:就是上面使用的,进入安装目录的sbin目录下启动:
cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.9.13/sbin/ ./rabbitmq-server start
- 方式2:设置开机启动,如下:
chkconfig rabbitmq-server on
- 方式3:service命令启动(任意目录下可执行)
service rabbitmq-server start
5.1.2 启动问题——Job for rabbitmq-server.service failed……
5.1.2.1 问题
- 使用
service rabbitmq-server start
命令启动的报错问题,问题描述,如下:Job for rabbitmq-server.service failed because the control process exited with error code. See "systemctl status rabbitmq-server.service" and "journalctl -xe" for details.
5.1.2.2 解决问题
5.1.2.2.1 尝试1:
- 执行
journalctl -xe
命令,查看详细问题:
- 解决问题(修改 /var/log/rabbitmq/ 目录下的两个日志文件的所属组和所属者,改为rabbitmq):
cd /var/log/rabbitmq/ chown -R rabbitmq:rabbitmq rabbit@hello_TQ1*
5.1.2.2.2 尝试2:
- 上面问题解决之后,再启动还报错的话,再执行
journalctl -xe
命令,查看详细问题,如下:
- 这个解决方式同上,如下:
再次执行service rabbitmq-server start
命令,不再报错,如下:
5.2 总结常用命令
- 检查服务状态
service rabbitmq-server status
rabbitmqctl status
- 启动服务
service rabbitmq-server start
- 停止服务
service rabbitmq-server stop
- 重启服务
service rabbitmq-server restart
6. 总结安装过程(7步)
-
第一步:安装 erlang(安装自己需要的版本)
rpm -ivh erlang-23.3.4.18-1.el7.x86_64.rpm
-
第二步:安装socat
yum install socat -y
-
第三步:安装rabbitmq-server(安装自己需要的版本)
rpm -ivh rabbitmq-server-3.9.13-1.el7.noarch.rpm
-
第四步:安装插件rabbitmq_management,开启图形化界面管理
rabbitmq-plugins enable rabbitmq_management
-
第五步:启动服务
service rabbitmq-server start
-
第六步:创建新用户、并设置角色权限等
- 进入安装目录,创建用户
cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.9.13/sbin/ rabbitmqctl add_user mqAdmin 123456
- 设置用户角色、设置用户权限
rabbitmqctl set_user_tags mqAdmin administrator rabbitmqctl set_permissions -p "/" mqAdmin ".*" ".*" ".*"
- 查看用户:
rabbitmqctl list_users
- 进入安装目录,创建用户
-
第七步,访问界面
- 如果是云服务器,开放端口5672、15672,防火墙处理等
linux下查看防火墙状态、关闭防火墙、开放关闭端口等. - 然后,访问界面
http://服务IP:15672/
- 如果是云服务器,开放端口5672、15672,防火墙处理等
7. 快速入门
7.1 控制台上模拟发送消息
-
创建交换机,当然可以用默认的交换机,我这里省事,就使用默认的一个了,amq.fanout。
-
创建队列
-
交换机绑定队列,如下:
-
发消息
-
查看
7.2 Java客户端——基础代码
7.2.1 pom文件
- 如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.liu.susu</groupId> <artifactId>rabbitmq-demo1</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>rabbitmq-demo1</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- rabbitmq依赖客户端--> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> </project>
7.2.2 生产者
- 测试:
- 查看效果
- 附代码
package com.liu.susu.example; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; /** * @Description 生产者 * @Author susu */ public class Producer { // 队列名称 public static final String QUEUE_NAME = "queue-hello"; public static void main(String[] args) throws Exception{ //1. 创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); //2. 工厂IP连接rabbitmq的队列 factory.setHost("服务IP地址"); //3. 连接用户名和密码 factory.setUsername("mqAdmin"); factory.setPassword("123456"); //4. 创建连接 Connection connection = factory.newConnection(); //5. 获取信道 Channel channel = connection.createChannel(); /** * 6. 创建一个队列 */ channel.queueDeclare(QUEUE_NAME,false,false,false,null); //7. 定义发送消息的内容 String msg = "hello world!!!,我来之于Java程序"; /** * 8. 发送消息 * 1. 参数1:交换机(发送到哪个交换机上) * 2. 参数2:路由key的值(本次发送用的队列名称) * 3. 参数3:其他参数信息 (本次没有,直接null) * 4. 参数4:发送消息的消息体 */ channel.basicPublish("",QUEUE_NAME,null,msg.getBytes()); System.out.println("=====消息发送成功====="); } }
7.2.3 消费者
-
消费之前,先看队列里的消息
-
测试消费者消费消息
-
消费之后,再看队列里的消息
-
附代码:
package com.liu.susu.example; import com.rabbitmq.client.*; /** * @Description 消费者 接收消息 * @Author susu */ public class Consumer { // 队列名称 public static final String QUEUE_NAME = "queue-hello"; public static void main(String[] args) throws Exception{ //1. 创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); //1.1. 工厂IP连接rabbitmq的队列 factory.setHost("服务IP地址"); //1.2. 连接用户名和密码 factory.setUsername("mqAdmin"); factory.setPassword("123456"); //2. 创建连接 Connection connection = factory.newConnection(); //3. 获取信道 Channel channel = connection.createChannel(); // 接收消息后的回调 DeliverCallback deliverCallback = (consumerTag,msg)->{ byte[] msgBody = msg.getBody(); System.out.println("消费的消息是:" + new String(msgBody)); }; // 取消消息时的回调 CancelCallback cancelCallback = (consumerTag)->{ System.out.println("===消息消费被取消===="); }; /** * 4. 消费者消费消息 * 1. 参数1:消费哪个队列 * 2. 参数2:消费成功之后是否要自定应答 * true——自动应答 * false——手动应答 * 3. 参数3:消费者接收消息后的回调方法 * 4. 参数4:消费者取消消费的回调(正常接收不调用) */ channel.basicConsume(QUEUE_NAME,true,deliverCallback,cancelCallback); } }
7.2.4 遇到的问题
7.2.4.1 问题1——Connection timed out
- 问题描述:Operation timed out (Connection timed out)
- 解决问题
云服务的话,安全组开放端口5672
,即可解决问题。
7.2.4.2 问题2——Connection refused
- 问题如下:
Connection refused (Connection refused)
- 解决问题
如果防火墙没有关闭,防火墙开放5672
端口即可。sudo firewall-cmd --add-port=5672/tcp --permanent firewall-cmd --reload
7.3 Java客户端——Spring AMQP
7.3.1 简介
- AMQP(Advanced Message Queuing Protocol)是用于在应用程序之间传递业务消息的开放标准。该协议与语言平台无关,更符合微服务中独立性的要求。
- Spring AMQP 是基于AMQP协议的一套API规范,提供了模版来发送和接收消息。
- Spring AMQP包含
spring-amqp
和spring-rabbit
两部分,其中spring-amqp是基础抽象,spring-rabbit是底层的默认实现。 - 参考官网:
https://spring.io/projects/spring-amqp.
- Spring AMQP包含
7.3.2 项目结构
-
目录结构
-
父pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.liu.susu</groupId> <artifactId>rabbitmq-demo2</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>rabbitmq-demo2</name> <url>http://maven.apache.org</url> <modules> <module>producer</module> <module>consumer</module> </modules> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>3.8.1</junit.version> <lombok.version>1.16.8</lombok.version> <spring-boot.version>2.7.16</spring-boot.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- AMQP依赖,包含RabbitMQ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> <version>2.7.14</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!-- <dependency>--> <!-- <groupId>junit</groupId>--> <!-- <artifactId>junit</artifactId>--> <!-- <version>${junit.version}</version>--> <!-- <scope>test</scope>--> <!-- </dependency>--> </dependencies> </dependencyManagement> </project>
7.3.3 生产者服务
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.liu.susu</groupId> <artifactId>rabbitmq-demo2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>producer</artifactId> <packaging>jar</packaging> <name>producer</name> <description>producer</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- AMQP依赖,包含RabbitMQ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <!--单元测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <testFailureIgnore>true</testFailureIgnore> </configuration> </plugin> </plugins> </build> </project>
-
application.yml
spring: rabbitmq: host: 服务IP地址 # 服务IP port: 5672 # 端口(发送消息的端口5672 rabbitmq管理界面的端口15672) # virtual-host: /mqAdmin # 虚拟主机 username: mqAdmin # 用户名 password: 123456 # 密码
-
发送消息的测试类
package com.liu.susu.producer; import org.junit.jupiter.api.Test; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; /** * @Description * @Author susu */ @SpringBootTest public class ProducerTest { @Autowired private RabbitTemplate rabbitTemplate; @Test public void publishMsg(){ System.out.println("---------------------"); String queueName = "queue-hello"; String msg = "hello,I am from amqp!!!"; //发送消息 rabbitTemplate.convertAndSend(queueName,msg); System.out.println("amqp——消息发送成功!!!"); } }
-
测试看效果
7.3.4 消费者服务
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.liu.susu</groupId> <artifactId>rabbitmq-demo2</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>consumer</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <name>consumer</name> <description>consumer</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- AMQP依赖,包含RabbitMQ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
application.yml
logging: pattern: dateformat: HH:mm:ss:SSSS spring: rabbitmq: host: 服务IP地址 # 服务IP port: 5672 # 端口(发送消息的端口5672 rabbitmq管理界面的端口15672) # virtual-host: /mqAdmin # 虚拟主机 username: mqAdmin # 用户名 password: 123456 # 密码
-
接收消息的组件
package com.liu.susu.consumer.listeners; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * @Description * @Author susu */ @Component public class MqListener { @RabbitListener(queues = "queue-hello") //监听的队列 public void listenQueues(String msg){ System.out.println("消费者收到消息===>"+msg); } }
-
启动服务,测试看效果