最简单的消息模型 “Hello World”
- P 生产者:发送消息的程序;
- 队列(红色部分):队列是 RabbitMQ 内部邮箱的名称。尽管消息通过 RabbitMQ 和应用程序传递,但它们只能存储在队列中。队列只受主机内存和磁盘限制的限制,它本质上是一个大的消息缓冲区。许多生产者可以将消息发送到一个队列,而许多消费者可以尝试从一个队列接收数据。
- C 消费者:消费者是一个程序,主要是等待接收消息。
我们要做什么?
接下来,我们需要分别创建一个生产者客户端和一个消费者客户端,生产者负责发布消息,消费者负责订阅(接收)消息。
在此之前,我们需提前在 RabbitMQ 中为客户端创建一个用户和虚拟主机,并把这些信息交给客户端使用。
创建用户和虚拟主机
RabbitMQ 默认只提供一个 guest
用户,我们可以通过 RabbitMQ 管理界面创建用户:
除此之外,也可以使用 rabbitmqctl add_user <username> <password>
命令创建用户。接下来,我们新建一个用户,用户名 mail
,密码 123
:
$ rabbitmqctl add_user mail 123
Adding user "mail" ...
不推荐使用这种方式创建用户,因为你输入的命令会被系统记录。通过查看历史,可以轻松地获取用户的密码,这可不是什么好事:
$ history
...
1050 rabbitmqctl add_user mail 123
1051 history
我们可以使用 rabbitmqctl delete_user <username>
删除 mail
用户:
$ rabbitmqctl delete_user mail
Deleting user "mail" ...
再执行 history -c
删除历史记录(如果需要的话)。
我们换另一种方式,使用 rabbitmqctl add_user <username>
命令创建用户,先输入用户名,稍后根据提示再输入密码:
$ rabbitmqctl add_user mail
Adding user "mail" ...
Password:
123
此时,再次查看历史,可以看到用户的密码并没有被记录:
$ history
53 rabbitmqctl add_user mail
54 history
使用 rabbitmqctl list_users
命令可以列出用户名称及其标签:
$ rabbitmqctl list_users
Listing users ...
user tags
mail []
guest [administrator]
我们也可以通过 RabbitMQ 控制界面查看用户列表:
接下来,我们需为 mail
用户分配一个可以访问的虚拟主机。
默认情况下,RabbitMQ 只有一个名为 /
的虚拟主机,可以通过 RabbitMQ 控制界面新建虚拟主机:
当然,也可以使用 rabbitmqctl add_vhost <vhost>
命令新建一个虚拟主机:
$ rabbitmqctl add_vhost /mail
Adding vhost "/mail" ...
接着,使用 rabbitmqctl list_vhosts
命令列出虚拟主机,第 4 行是我们刚刚创建的虚拟主机的名称:
$ rabbitmqctl list_vhosts
Listing vhosts ...
name
/mail
/
通过 RabbitMQ 控制界面查看虚拟主机列表,可以看到新建的虚拟主机 /mail
,此时没有任何用户可以访问该虚拟主机:
新建的用户是没有任何权限的,可以通过 rabbitmqctl list_user_permissions <username>
命令列出用户在所有虚拟主机中的权限:
$ rabbitmqctl list_user_permissions mail
Listing permissions for user "mail" ...
接下来,我们将为 mail
用户设置权限,使其可以访问 /mail
虚拟主机。
使用 rabbitmqctl set_permissions [--vhost <vhost>] <username> <conf> <write> <read>
命令为用户设置虚拟主机和权限:
$ rabbitmqctl set_permissions --vhost '/mail' 'mail' '.*' '.*' '.*'
Setting permissions for user "mail" in vhost "/mail" ...
- 第一个
.*
表示拥有在每个实体上的配置权限 - 第二个
.*
表示拥有在每个实体上的读权限 - 第三个
.*
表示拥有在每个实体上的写权限
此外,我们还可以使用 rabbitmqctl list_permissions [--vhost <vhost>]
命令列出指定虚拟主机中的用户的权限:
$ rabbitmqctl list_permissions --vhost /mail
Listing permissions for vhost "/mail" ...
user configure write read
mail .* .* .*
或者,在管理界面的用户列表中,点击用户名称查看:
注意:因为我们并没有为 mail
用户分配任何标签(或说管理权限),所以其不能登录 RabbitMQ 管理界面:
可以使用 rabbitmqctl set_user_tags <username> <tag>
命令为用户设置标签:
$ rabbitmqctl set_user_tags mail administrator
Setting tags for user "mail" to [administrator] ...
可用标签及其含义参考:Access and Permissions
随后,我们列出用户的名称及其标签,可以看到 mail
拥有管理员的权限:
$ rabbitmqctl list_users
isting users ...
user tags
mail [administrator]
guest [administrator]
现在,可以使用 mail
用户可以登录 RabbitMQ 管理界面:
不过,因为我们创建 mail
用户的目的是用于客户端连接 RabbitMQ 服务器,而不是用于管理 RabbitMQ 服务器,所以还是不要为其分配权限。
将 mail
用户的标签设为 (NONE),既没有任何管理权限:
$ rabbitmqctl set_user_tags mail ''
Setting tags for user "mail" to [] ...
确认一下:
$ rabbitmqctl list_users
Listing users ...
user tags
mail []
guest [administrator]
开放端口
我们需要开放 5672 端口,远程客户端才能访问 RabbitMQ 服务器:
$ firewall-cmd --get-active-zones
public
interfaces: ens33
$ firewall-cmd --zone=public --add-port=5672/tcp --permanent
success
$ firewall-cmd --reload
success
$ firewall-cmd --query-port=5672/tcp
yes
Java 客户端程序
创建 Maven Project,引入依赖:
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.2</version>
</dependency>
创建生产者(发布消息),并运行:
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.88.158");
factory.setPort(5672); //
factory.setVirtualHost("/mail");
factory.setUsername("mail");
factory.setPassword("123");
Connection connection = factory.newConnection(); // 创建连接
Channel channel = connection.createChannel(); // 创建通道
channel.queueDeclare("mail", false, false, false, null); // 声明队列
channel.basicPublish("", "mail", null, "你的验证码:1234".getBytes()); // 发布消息
channel.close();
connection.close();
}
}
成功发布消息之后,可以看到队列中有 1 条消息:
创建消费者(订阅消息),并运行:
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.AMQP.BasicProperties;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("192.168.88.158");
factory.setPort(5672);
factory.setVirtualHost("/mail");
factory.setUsername("mail");
factory.setPassword("123");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("mail", false, false, false, null);
channel.basicConsume("mail", true, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body)
throws IOException {
System.out.println(new String(body));
}
});
// channel.close();
// connection.close();
}
}
成功订阅消息之后,如果 RabbitMQ 的队列中有消息,消费者将接收对应队列中的消息,然后将其打印到控制台。
参考
https://www.bilibili.com/video/BV1dE411K7MG?p=5
https://www.bilibili.com/video/BV1dE411K7MG?p=6