一、什么叫做消息队列

消息(Message)指在应用间传输的数据。消息包含 数字、文本、更复杂的嵌入对象等等。

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传输。消息发布者只管把消息发送到 MQ 中而不管谁来取,消费者只管从 MQ 中拿消息而不管谁发送的消息。消息的发送和接收都不知道双方的存在。

二、消息队列出现的原因

消息队列是一种异步协作的机制。

比如说订单系统,一般订单涉及的业务操作包括:扣减库存、生成订单信息、发红包、发送短信提示等。业务量较少时这些操作可以放在一起同步执行,但随着业务量的增多,需要提升系统的服务性能,这时可以将一些不需要立即生效的操作单独抽取出来异步执行。比如说 发红包、发短信提示 这两个操作可以不用那么急,这种情况下使用 MQ,在下单的主流程(扣减库存、生成订单信息)完成后发送一条消息到 MQ 让主流程快速完结,而另外的由单独的线程拉取 MQ 的消息,当发现 MQ 中有对应的消息时进行执行。

常用场景包括: 最终一致性、广播、错峰流控等。

三、RabbitMQ 特点

RabbitMQ 是一款由 Erlang 语言开发的 AMQP 的开源实现。

AMQP: Advanced Message Queue,高级消息队列协议。它是应用层协议的一个标准。

RabbitMQ 主要特性如下:

  1. 可靠性(Reliability)RabbitMQ 使用一些机制来保证可靠性,比如持久化、传输确认、发布确认。
  2. 灵活的路由(Flexible Routing)在消息进入消息队列之前,通过 Exchange交换机来路由消息。对于典型的路由功能,已经有了一些内置的交换机来实现;但是对于更复杂的路由,可以将多个交换机绑定到一起来实现。
  3. 消息集群(Clustering)多个RabbitMQ 服务器可以组合成为一个集群。
  4. 高可用(High Available Queues)队列可以在集群中的服务器上进行镜像,使得部分结点在出现问题的情况下队列仍然可以使用。
  5. 多种协议(Multi-protocol)RabbitMQ 支持多种消息队列协议,如 STOMP、MQTT。
  6. 多语言客户端(Many Clients)RabbitMQ 支持多种常用的语言。
  7. 管理界面、跟踪机制、插件机制。

四、RabbitMQ 中的概念

4.1 消息模型

4.2 RabbitMQ 基本概念

  1. Message 消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
  2. Publisher 消息的生产者,也是一个向交换器发布消息的客户端应用程序。
  3. Exchange 交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
  4. Binding 绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
  5. Queue 消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
  6. Connection 网络连接,比如一个TCP连接。
  7. Channel 信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
  8. Consumer 消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
  9. Virtual Host 虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。
  10. Broker 表示消息队列服务器实体。

五、AMQP 中的消息路由

AMQP 中增加了 Exchange 交换机和 Binding 的角色。生产者把消息发送到交换机,由 Binging 和路由键共同决定消息应该发往哪个队列。

Exchange 根据分发消息时的类型有着不同的发送策略。总共四种类型:direct、fanout、topic、headers。

headers匹配的不是路由键而是消息的 header,但是用的很少。

5.1 Direct

如果消息头中的 路由键和 Binding 中的 binding key一致,交换器就将消息发送到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是完全匹配、单播的模式。

5.2 Fanout

每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout 交换器不处理路由键,只是简单的将队列绑定到交换器上,每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的。

5.3 Topic

topic 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“”。#匹配0个或多个单词,匹配不多不少一个单词。

六、RabbitMQ 的运行

找到 RabbitMQ 安装后的 sbin 目录,里面有一个 rabbitmq-server 可执行文件,执行即可。

6.1 启动 RabbitMQ

./sbin/rabbitmq-server:启动

./sbin/rabbitmq-server -detached:后台启动

6.2 查看 RabbitMQ 服务器状态信息

./sbin/rabbitmqctl status:查询 RabbitMQ 服务器的状态信息

6.3 关闭 RabbitMQ 结点

RabbitMQ 是使用 Erlang 语言写的,在 Erlang中有两个概念:结点和应用程序。结点就是 Erlang虚拟机的每个实例,而多个 Erlang 应用程序可以运行在同一个结点上。结点之间可以进行本地通信(不管它们是不是运行在同一台服务器上)。比如一个运行在结点A上的应用程序可以调用运行在B上的应用程序的方法。如果应用程序由于某些原因出现崩溃,Erlang 就会自动尝试重启。

关闭整个 RabbitMQ 结点:./sbin/rabbitmqctl stop

也可以关闭远程结点: ./sbin/rabbitmqctl -n rabbit@server.example.com stop

-n node 默认 node 名称是 rabbit@server ,如果你的主机名是 server.example.com ,那么 node 名称就是 rabbit@server.example.com

6.4 关闭 RabbitMQ 应用程序

如果只想关闭 RabbitMQ 应用程序同时保持 Erlang 结点的运行,可以使用 stop_app

./sbin/rabbitmqctl stop_app

6.5 启动 RabbitMQ 应用程序

./sbin/rabbitmqctl start_app

6.6 重置 RabbitMQ 结点

./sbin/rabbitmqctl reset 该命令会清除所有队列

6.7 查看已经声明的队列

./sbin/rabbitmqctl list_queues

6.8 查看交换器

./sbin/rabbitmqctl list_exchanges

该命令还可以附带参数,比如交换器的名称、类型、是否持久化是否自动删除

./sbin/rabbitmqctl list_exchanges name type durable auto_delete

6.9 查看绑定

./sbin/rabbitmqctl list_bindings

七、RabbitMQ 的安装

7.1 下载 erlang

https://www.erlang.org/downloads/22.3

版本参照 rabbitMQ 官网的对应版本

7.2 下载 RabbitMQ

image-20210409150627460

7.3 上传服务器并解压

注意 RabbitMQ压缩包为 .xz 格式,要先用 xz 命令进行解压为 .tar 文件,然后使用 tar 命令进行解压

xz -d rabbitmq-server-generic-unix-3.7.16.tar.xz:解压 .xz 文件

tar -xvf rabbitmq-server-generic-unix-3.7.16.tar:解压 .tar 文件

然后在 /usr/local 下创建一个 RabbitMQ文件夹用来存储RabbitMQ 软件运行时的数据等等,并将解压后的文件也移动到当前文件夹下。

7.4 安装 Erlang

  1. 安装 Erlang 编译所依赖的环境

yum install make gcc gcc-c++ build-essential openssl openssl-devel unixODBC unixODBC-devel kernel-devel m4 ncurses-devel

  1. 在 /usr/local 目录下创建一个erlang文件夹,因为erlang编译安装默认是装在/usr/local下的bin和lib中,这里我们将他统一装到/usr/local/erlang中,方便查找和使用

mkdir -p /usr/local/erlang

  1. 编译Erlang
1
2
cd otp_src_22.0/        #进入Erlang目录下
./configure --prefix=/usr/local/erlang --without-javac #编译 erlang,这里不要使用java编译器了
  1. 安装 Erlang

make && make install

  1. 配置 Erlang 环境变量
1
2
3
4
5
6
7
8
9
 vim /etc/profile           //编译环境配置文件


//添加如下信息
export ERLANG_HOME=/usr/local/erlang
export PATH=${ERLANG_HOME}/bin:${PATH}

//让配置生效
source /etc/profile
  1. 创建软连接

ln -s /usr/local/erlang/bin/erl /usr/local/bin/erl

7.5 安装 RabbitMQ

  1. 配置环境变量
1
2
3
4
5
vim /etc/profile    //切换到目录

//添加如下信息
export RABBITMQ_HOME=/usr/local/RabbitMQ_Softwork/rabbitmq_server-3.8.11
export PATH=${RABBITMQ_HOME}/sbin:${PATH}
  1. 开启web 管理界面
1
2
3
4
5
//切换到 sbin 目录下
cd /usr/local/RabbitMQ_Softwork/rabbitmq_server-3.8.11/sbin

//开启管理界面
./rabbitmq-plugins enable rabbitmq_management
  1. 设置开机启动
1
2
3
4
5
6
7
8
vim /etc/rc.d/rc.local

//添加如下代码到 rc.local 文件中
//注意:1.手动启动,用户登陆后会去加载/etc/profile中的配置文件中 Erlang和RabbitMQ环境
// 2.开机启动,在系统识别用户前加载配置文件中的环境。

source /etc/profile //表示加载配置文件
/usr/local/RabbitMQ_Softwork/rabbitmq_server-3.8.11/sbin/rabbitmq-server -detached //后台启动
  1. 后台启动 RabbitMQ

/usr/local/RabbitMQ_Softwork/rabbitmq_server-3.8.11/sbin/rabbitmq-server -detached

7.6 浏览器访问 RabbitMQ

浏览器端口 15672访问 RabbitMQ web管理界面,初始用户名和密码都为 guest

可以看到Login failed (登录失败),User can only log in via localhost (用户只能通过本地主机登录),因为rabbitmq从3.3.0开始禁止使用guest/guest管理员权限通过除localhost外的访问

解决方案:重新创建用户,设置权限进行登录

1
2
3
4
5
6
7
8
9
10
11
12
//添加用户
rabbitmqctl add_user root 123456 //创建用户名为root 密码为123456的用户

//给用户设置标签
rabbitmqctl set_user_tags root administrator

//查看所有用户列表
rabbitmqctl list_users

//但是这样只能登录,无权访问虚拟主机,需要添加权限操作
//给root用户在虚拟主机"/"上的配置、写、读的权限
rabbitmqctl set_permissions root -p / ".*" ".*" ".*"
image-20210409163648224
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# 帮助命令
[root@RabbitMQ ~]# rabbitmqctl help
Error:

Usage

rabbitmqctl [--node <node>] [--timeout <timeout>] [--longnames] [--quiet] <command> [<command options>]

Available commands:

Help:

help Displays usage information for a command
version Displays CLI tools version

Nodes:

await_startup Waits for the RabbitMQ application to start on the target node
reset Instructs a RabbitMQ node to leave the cluster and return to its virgin state
rotate_logs Instructs the RabbitMQ node to perform internal log rotation
shutdown Stops RabbitMQ and its runtime (Erlang VM). Monitors progress for local nodes. Does not require a PID file path.
start_app Starts the RabbitMQ application but leaves the runtime (Erlang VM) running
stop Stops RabbitMQ and its runtime (Erlang VM). Requires a local node pid file path to monitor progress.
stop_app Stops the RabbitMQ application, leaving the runtime (Erlang VM) running
wait Waits for RabbitMQ node startup by monitoring a local PID file. See also 'rabbitmqctl await_online_nodes'

Cluster:

await_online_nodes Waits for <count> nodes to join the cluster
change_cluster_node_type Changes the type of the cluster node
cluster_status Displays all the nodes in the cluster grouped by node type, together with the currently running nodes
force_boot Forces node to start even if it cannot contact or rejoin any of its previously known peers
force_reset Forcefully returns a RabbitMQ node to its virgin state
forget_cluster_node Removes a node from the cluster
join_cluster Instructs the node to become a member of the cluster that the specified node is in
rename_cluster_node Renames cluster nodes in the local database
update_cluster_nodes Instructs a cluster member node to sync the list of known cluster members from <seed_node>

Replication:

cancel_sync_queue Instructs a synchronising mirrored queue to stop synchronising itself
sync_queue Instructs a mirrored queue with unsynchronised mirrors (follower replicas) to synchronise them

Users:

add_user Creates a new user in the internal database
authenticate_user Attempts to authenticate a user. Exits with a non-zero code if authentication fails.
change_password Changes the user password
clear_password Clears (resets) password and disables password login for a user
delete_user Removes a user from the internal database. Has no effect on users provided by external backends such as LDAP
list_users List user names and tags
set_user_tags Sets user tags

Access Control:

clear_permissions Revokes user permissions for a vhost
clear_topic_permissions Clears user topic permissions for a vhost or exchange
list_permissions Lists user permissions in a virtual host
list_topic_permissions Lists topic permissions in a virtual host
list_user_permissions Lists permissions of a user across all virtual hosts
list_user_topic_permissions Lists user topic permissions
list_vhosts Lists virtual hosts
set_permissions Sets user permissions for a vhost
set_topic_permissions Sets user topic permissions for an exchange

Monitoring, observability and health checks:

environment Displays the name and value of each variable in the application environment for each running application
list_bindings Lists all bindings on a vhost
list_channels Lists all channels in the node
list_ciphers Lists cipher suites supported by encoding commands
list_connections Lists AMQP 0.9.1 connections for the node
list_consumers Lists all consumers for a vhost
list_exchanges Lists exchanges
list_hashes Lists hash functions supported by encoding commands
list_queues Lists queues and their properties
list_unresponsive_queues Tests queues to respond within timeout. Lists those which did not respond
ping Checks that the node OS process is up, registered with EPMD and CLI tools can authenticate with it
report Generate a server status report containing a concatenation of all server status information for support purposes
schema_info Lists schema database tables and their properties
status Displays status of a node

Parameters:

clear_global_parameter Clears a global runtime parameter
clear_parameter Clears a runtime parameter.
list_global_parameters Lists global runtime parameters
list_parameters Lists runtime parameters for a virtual host
set_global_parameter Sets a runtime parameter.
set_parameter Sets a runtime parameter.

Policies:

clear_operator_policy Clears an operator policy
clear_policy Clears (removes) a policy
list_operator_policies Lists operator policy overrides for a virtual host
list_policies Lists all policies in a virtual host
set_operator_policy Sets an operator policy that overrides a subset of arguments in user policies
set_policy Sets or updates a policy

Virtual hosts:

add_vhost Creates a virtual host
clear_vhost_limits Clears virtual host limits
delete_vhost Deletes a virtual host
list_vhost_limits Displays configured virtual host limits
restart_vhost Restarts a failed vhost data stores and queues
set_vhost_limits Sets virtual host limits
trace_off
trace_on

Node configuration:

decode Decrypts an encrypted configuration value
encode Encrypts a sensitive configuration value
set_cluster_name Sets the cluster name
set_disk_free_limit Sets the disk_free_limit setting
set_log_level Sets log level in the running node
set_vm_memory_high_watermark Sets the vm_memory_high_watermark setting

Definitions:

export_definitions Exports definitions in JSON or compressed Erlang Term Format.
import_definitions Imports definitions in JSON or compressed Erlang Term Format.

Deprecated:

node_health_check DEPRECATED. Performs intrusive, opinionated health checks on a fully booted node. See https://www.rabbitmq.com/monitoring.html#health-checks instead

Feature flags:

enable_feature_flag Enables a feature flag on target node
list_feature_flags Lists feature flags

Operations:

close_all_connections Instructs the broker to close all connections for the specified vhost or entire RabbitMQ node
close_connection Instructs the broker to close the connection associated with the Erlang process id
eval Evaluates a snippet of Erlang code on the target node
exec Evaluates a snippet of Elixir code on the CLI node
force_gc Makes all Erlang processes on the target node perform/schedule a full sweep garbage collection
hipe_compile Only exists for backwards compatibility. HiPE support has been dropped starting with Erlang 22. Do not use

Queues:

delete_queue Deletes a queue
purge_queue Purges a queue (removes all messages in it)

Use 'rabbitmqctl help <command>' to learn more about a specific command

八、Java客户端访问 RabbitMQ

消息生产者代码模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class MessageProvider {
public static void main(String[] args) throws Exception{
//1.建立连接
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("root");
factory.setPassword("123456");
factory.setHost("39.100.119.221");
Connection conn = factory.newConnection();

//2.获取信道,声明交换机
//获取信道
Channel channel = conn.createChannel();
//声明交换机
String exchangeName = "hello-exchange";
channel.exchangeDeclare(exchangeName,"direct",true);
//声明路由键
String routingKey = "hola";

//3.发布消息
byte[] messageBodyBytes = "Hello RabbitMQ".getBytes();
channel.basicPublish(exchangeName,routingKey,null,messageBodyBytes);

//4.关闭资源
channel.close();
conn.close();
}
}

消息生产者主要关注的就是生产消息,然后将消息交给交换机。剩下的消息的转接都由交换机去完成。

消费者传输消息时需要声明交换机的类型,包括(directfanouttopicheaders),通过信道来传输数据,因此要建立信道和交换机之间的关联。

最后需要定义路由键,因为需要通过路由键来绑定交换机和消息队列。

消息消费者代码模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class MessageConsumer {
public static void main(String[] args) throws Exception{
//1.获取连接
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("root");
factory.setPassword("123456");
factory.setHost("39.100.119.221");
Connection conn = factory.newConnection();
if(conn!=null)
System.out.println("连接获取成功!");

//2.获取信道、声明交换机、声明队列、定义路由键
//获取信道
Channel channel = conn.createChannel();
//声明交换机
String exchangeName = "hello-exchange";
channel.exchangeDeclare(exchangeName,"direct",true);
//声明队列
String queueName = channel.queueDeclare().getQueue();
String routingKey = "hola";

//3.通过路由键绑定队列与交换机
channel.queueBind(queueName,exchangeName,routingKey);

//4.接收消息
while(true){
//消费消息
boolean autoAck = false;
String consumerTag = "";
channel.basicConsume(queueName,autoAck,consumerTag,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//路由键
String routingKey = envelope.getRoutingKey();
//消息类型
String contentType = properties.getContentType();
System.out.println("路由键为:"+routingKey);
System.out.println("消息类型为:"+contentType);
long deliveryTag = envelope.getDeliveryTag();

//确认消息
channel.basicAck(deliveryTag,autoAck);

//消息的内容
String message = new String(body);
System.out.println("消息的内容为:"+message);
}
});
}
}
}
  • 消费者只关注从队列中获取数据,队列需要和交换机进行绑定,因此需要声明路由键、交换机、队列。

​ 然后通过 channel.queueBind(queueName,exchangeName,routingKey)来绑定交换机和队列。

  • 消费者接收消息是通过 channel.basicConsume() 方法来进行的,详细介绍如上。

最后注意Java连接RabbitMQ 是通过 5672 端口进行的,而 15672是浏览器访问 RabbitMQ管理界面的端口,因此需要在Linux中打开 5672 端口。

九、RabbitMQ 集群

9.1 为什么使用集群?

(1)允许消费者和生产者在 RabbitMQ 结点崩溃时仍然能够保证正常的通信;

(2)增加结点来扩展 RabbitMQ 处理更多的消息,承载更多的业务量。

9.2 集群的特点

集群是由多个结点组成的,但不是每个结点都有所有队列的完整数据。—— 结点的不完全拷贝性

  1. RabbitMQ 会始终记录以下四种类型的内部数据

(1)队列元数据 包括队列的名称、属性,比如是否可以持久化,是否自动删除;

(2)交换机元数据 包括交换机的名称、属性、类型;

(3)绑定元数据 内部是一张表格,记录如何将消息路由到队列;

(4)vhost元数据 为vhost 内部的队列、交换机、绑定提供命名空间和安全属性;

  1. 存储形式的不同

在单一节点中,RabbitMQ 会将上述的四种类型的元数据存储在内存中,同时将可持久化的队列、交换机、绑定存储到磁盘上。存储到磁盘上保证了重启后能够恢复数据状态;

在集群中创建队列,只会在单个节点上创建完整的队列信息(元数据、状态、内容)。结果是只有队列所有者知道队列有关的所有信息,如果这个结点崩溃,该结点的队列和绑定就消失了,该队列的任何消息也就都消失了。好在 RabbitMQ 2.6.0 之后提供了 镜像队列来避免节点崩溃导致队列不可用的情况。

如上所说,RabbitMQ 可以共享 user、vhost、exchange等,所有的数据状态都是必须在所有结点上复制的,例外就是队列。

集群中有内存结点和磁盘结点两种类型,内存结点性能更好、速度更快,但是对于需要持久化的队列、交换机、绑定而言就必须使用磁盘节点,它保证了重启后仍然能够恢复数据。因此集群中必须至少有1个磁盘节点,如果这个结点崩溃了,那该集群可以继续路由消息,但是不能创建队列、交换机、绑定,不能创建用户、修改用户权限等等。也就是说如何唯一的磁盘节点崩溃,那么集群仍然可以运行,但是不能更改任何东西直到它恢复。

  1. 为什么默认情况下不让队列的内容和状态复制到所有结点?

(1)存储空间 —– 如果将队列的内容和状态复制到所有的结点,那么新增结点反而没有增大容量,而是增加了冗余数据;

(2)性能 —– 如果需要将消息发布拷贝到每一个结点,那么对于网络负载还有磁盘负载都会有所增加,与建立集群的初衷相违背。

9.3 集群的异常处理

如果集群的结点崩溃了,那么该结点的队列和关联的绑定就都丢失了。

解决办法:如果该结点消息已经进行了持久化,那么等待结点恢复就可以了;

​ 如果未进行持久化,需要使用双活冗余队列、镜像队列。

9.4 集群的搭建

这里使用比较热门的方法,使用 docker 来下载启动搭建 rabbitmq 集群

  1. 安装 rabbitmq 镜像

docker pull rabbitmq:3.6.15-management

后面的 -management 是指包含网页控制台的。

安装成功后使用 docker images来查看现有的镜像。

列举一下Docker常用命令:

(1)容器启动: docker start 容器名称;

(2)容器停止: docker stop 容器名称;

(3)删除容器: docker rm 容器名称/容器ID;

(4)删除镜像: docker rmi 镜像名称/镜像ID;

(5)查看所有镜像:docker images;

(6)查看运行中的容器:docker ps;

(7)查看所有容器: docker ps -a;

(8)进入docker目录:docker exec -it /bin/bash;

(9)启动容器:docker run -d -h hostName -p HostPort:ContainerPort –name ContainerName 镜像名/镜像ID:tag

  1. 启动多个 rabbitmq
1
2
3
4
5
6
7
8
//启动第一个  端口映射 5672:5672 15672:15672
docker run -d -p 5672:5672 -p 15672:15672 -h rabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' --name myrabbit1 rabbitmq:management

//启动第二个 端口映射 5673:5672 15673:15672
docker run -d -p 5673:5672 -p 15673:15672 -h rabbit2 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' --name myrabbit2 --link myrabbit1:rabbit1 rabbitmq:management

//启动第二个 端口映射 5674:5672 15674:15672
docker run -d -p 5674:5674 -p 15674:15674 -h rabbit3 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' --name myrabbit3 --link myrabbit1:rabbit1 --link myrabbit2:rabbit2 rabbitmq:management

注意:多个容器之间必须通过 --link进行连接,此属性不能少;

​ Erlang Cookie 必须相同,原因是:RabbitMQ 是通过 Erlang语言编写的,Erlang Cookie相当于各个结点之间的通信秘钥,Erlang结点通过交换 Erlang Cookie来获取认证。

  1. 加入RabbitMQ 结点到集群
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//设置结点1
docker exec -it myrabbit1 bash //进入容器
rabbitmqctl stop_app //同步数据
rabbitmqctl reset
rabbitmqctl start_app
exit

//设置结点2
docker exec -it myrabbit2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbit1
rabbitmqctl start_app
exit

//设置结点3
docker exec -it myrabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbit1
rabbitmqctl start_app
exit

注意:由于初始时每个结点都是独立的状态,不知道其它结点的存在,因此需要停止程序然后重置结点来同步数据,然后再加入到集群中。 --ram 表示设置为内存结点,忽略此参数默认为磁盘结点

  1. 这样就启动了3个结点,一个磁盘结点,两个内存结点,3个结点一起构成了 RabbitMQ 集群

  1. 集群其余操作
1
2
3
4
5
6
7
8
9
10
//更改结点类型
rabbitmqctl stop_app
rabbitmqctl change_cluster_node_type dist //更改为磁盘结点
rabbitmqctl change_cluster_node_type ram //更改为内存结点
rabbitmqctl start_app

//移除结点
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app

集群启动时,先是磁盘结点然后是内存结点(顺序是固定地);集群关闭时,先是内存结点然后是磁盘结点

十、镜像队列

https://blog.csdn.net/u013256816/article/details/71097186

参考文章:

https://zhuanlan.zhihu.com/p/269917155

https://blog.csdn.net/qq_39135287/article/details/95725385?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242

https://juejin.cn/post/6844903554721775629#heading-12

https://www.cnblogs.com/vipstone/p/9362388.html