1、本文是在同一台服务器上拥有不同的docker容器,每个容器都有自己的rabbitmq服务
2、这里演示3个docker,15672为主节点,15673和15674分别为从节点
一、创建多个RabbitMQ容器
1、创建15672主节点容器
docker run -d --hostname rabbitmq1 --name myrabbit1 -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
2、创建15673从节点1容器
注意15673的端口,-p 5673:5672 -p 15673:15672
docker run -d --hostname rabbitmq2 --name myrabbit2 -p 5673:5672 -p 15673:15672 --link myrabbit1:rabbit1 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
3、创建15674从节点2容器1
docker run -d --hostname rabbitmq3 --name myrabbit3 -p 5674:5672 -p 15674:15672 --link myrabbit1:rabbit1 --link myrabbit2:rabbit2 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management
参数解释:
-d 容器后台运行
--hostname rabbitmq1 容器的主机名为 rabbitmq1,到时候从节点进行绑定的时候,需要根据这个节点名进行映射
--name myrabbit1 容器名为myrabbit1 ,在宿主机上运行“docker ps”命令时显示的名称
-p "5672:5672" 消息通讯端口,容器端口:宿主机端口
-p "15672:15672" 后台管理端口
--link myrabbit1:rabbit1 (必须)容器互通,相当于myrabbit2 ping 成功 myrabbit1
-e RABBITMQ_DEFAULT_USER=admin 设置rabbitmq默认用户为admin
-e RABBITMQ_DEFAULT_PASS=admin 设置rabbitmq默认密码为admin
-e RABBITMQ_ERLANG_COOKIE='rabbitcookie' 设置rabbitmq的cookie为“rabbitcookie”,可以自定义为其他文本,容器保持一致即可
--add-host="rabbitmq1":192.168.12.186 (可选)修改容器内部的hosts名,即rabbitmq1对应该ip
--restart=unless-stopped docker (可选)容器重启后重启MQ
-
启动完毕后,在网页打开ip:15672访问看看是否正常
-
用户:admin
-
密码:admin
-
如果还访问不了,注意看一下服务器的防火墙有没有开放对应的端口!
-
当服务器的防火墙开放端口后,依旧访问不了,可以进入容器里面,开启rabbitMQ服务
docker exec -it myrabbit1 bash
rabbitmqctl start_app
注意:
- rabbitmq的cookie也要保持一致否则建立不了集群关系
- 如果是在不同的服务器,--add-host后面的参数一定要记得填写对应的ip
二、将RabbitMQ节点加入到集群中
1、15672主节点容器
# 命令行的形式进入myrabbit1容器
docker exec -it myrabbit1 bash
#停止当前的MQ
rabbitmqctl stop_app
#目的是清除节点上的历史数据(如果不清除,无法将节点加入到集群)
rabbitmqctl reset
#启动应用
rabbitmqctl start_app
exit
2、15673从节点1容器
# 命令行的形式进入myrabbit2容器
docker exec -it myrabbit2 bash
#首先停止当前MQ
rabbitmqctl stop_app
rabbitmqctl reset
#将rabbitmq2节点加入到rabbitmq1(主节点)集群当中【rabbitmq1服务器的主机名】
rabbitmqctl join_cluster --ram rabbit@rabbitmq1
#重新启动MQ
rabbitmqctl start_app
# 退出容器
exit
#按下CTRL+Q+P 不停止运行,退出容器
3、15674从节点2容器
docker exec -it myrabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq1
rabbitmqctl start_app
exit
三、测试
1、登录主节点,ip:15672
2、在主节点15672创建交换机
3、发现从节点15673也有该交换机
4、在从接待15673创建队列,并发送消息
5、主节点15672收到消息
6、验证集群状态
root@rabbitmq1:/# rabbitmqctl cluster_status -n rabbit@rabbitmq1
RABBITMQ_ERLANG_COOKIE env variable support is deprecated and will be REMOVED in a future version. Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead.
Cluster status of node rabbit@rabbitmq1 ...
Basics
Cluster name: rabbit@rabbitmq1
Disk Nodes
rabbit@rabbitmq1
RAM Nodes
rabbit@rabbitmq2
rabbit@rabbitmq3
Running Nodes
rabbit@rabbitmq1
rabbit@rabbitmq2
rabbit@rabbitmq3
Versions
rabbit@rabbitmq1: RabbitMQ 3.9.11 on Erlang 24.2
rabbit@rabbitmq2: on Erlang
rabbit@rabbitmq3: on Erlang
......
至此,单台服务器docker搭建rabbitmq集群完成!
四、在多台服务器上部署RabbitMQ集群
因为RabbitMQ是通过Erlang实现的,Erlang Cookie相当于不同节点之间相互通讯的秘钥,Erlang节点通过交换Erlang Cookie获得认证。
1、通过RabbitMQ容器启动日志里面的home dir路径作为根路径获取Erlang Cookie所在位置。使用:“docker logs 容器名称/ID”查看,所以Erlang Cookie的全部路径就是“/var/lib/rabbitmq/.erlang.cookie”。
2、复制Erlang Cookie到其他RabbitMQ节点
需读取其中一个节点的cookie, 并复制到其他节点(节点之间通过cookie确定相互是否可通信)。而cookie存放在/var/lib/rabbitmq/.erlang.cookie。也就说把其中一台的.erlang.cookie替换其他服务器的.erlang.cookie,其它步骤雷同单机部署方式。
- 宿主机和容器之间复制命令如下:
- 容器复制文件到宿主机:docker cp 容器名称:容器目录 物理机目录
- 宿主机复制文件到容器:docker cp 物理机目录 容器名称:容器目录
- 设置Erlang Cookie文件权限:“chmod 600 /var/lib/rabbitmq/.erlang.cookie”。
3、将节点加入集群,添加--add-host参数即可
五、通过nginx实现负载均衡
这里需要另外找一台服务器作为负载均衡服务器,在该服务上面随便建立一个文件夹用来存放nginx的配置文件:/home/nginx/nginx_rabbitmq.conf
文件内容:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 5s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
#rabbitmq管理界面
upstream rabbitManage { # 负载均衡配置,默认轮询,将客户的请求,平均分摊到下面的服务器上
server ip1主:15672;
server ip2从:15672;
server ip3从:15672;
}
server {
listen 15673;
server_name ip_nginx; # 负载均衡服务器Ip
location / {
proxy_pass http://rabbitManage;
index index.html index.htm;
}
}
}
# rabbitmq通信
stream{
upstream rabbitTcp{
server ip1主:5672;
server ip2从:5672;
server ip3从:5672;
}
server {
listen 5673;
server_name ip_nginx; # 负载均衡服务器Ip
location / {
proxy_pass http://rabbitTcp;
index index.html index.htm;
}
}
}
配置完毕后启动nginx:
docker run -it -d --name nginxMQ -v /home/nginx/nginx_rabbitmq.conf:/etc/nginx/nginx.conf --privileged --net=host nginx
启动完毕后通过负载的地址进行统一访问MQ
后台地址:ip_nginx:15673
通讯地址:ip_nginx:5673
六、如何给RabbitMQ容器添加用户
这里添加用户名test 密码 test,拥有超级管理员角色和权限
rabbitmqctl -n rabbit@rabbitmq1 add_user test test
rabbitmqctl -n rabbit@rabbitmq1 set_user_tags test administrator
rabbitmqctl -n rabbit@rabbitmq1 set_permissions -p / test ".*" ".*" ".*"
七、碰到的问题
unable to connect to epmd (port 4369) on rabbitmq1: nxdomain (non-existing domain)
原因:不能解析rabbitmq1主机名
详细报错内容
[root@rabbitmq2 ~]# rabbitmqctl join_cluster rabbit@rabbitmq1
Clustering node rabbit@rabbitmq2 with rabbit@rabbitmq1
Error: unable to perform an operation on node 'rabbit@rabbitmq1'. Please see diagnostics information and suggestions below.
Most common reasons for this are:
* Target node is unreachable (e.g. due to hostname resolution, TCP connection or firewall issues)
* CLI tool fails to authenticate with the server (e.g. due to CLI tool's Erlang cookie not matching that of the server)
* Target node is not running
In addition to the diagnostics info below:
* See the CLI, clustering and networking guides on https://rabbitmq.com/documentation.html to learn more
* Consult server logs on node rabbit@rabbitmq1
* If target node is configured to use long node names, don't forget to use --longnames with CLI tools
DIAGNOSTICS
===========
attempted to contact: ['rabbit@rabbitmq1']
rabbit@rabbitmq1:
* unable to connect to epmd (port 4369) on vm-246: nxdomain (non-existing domain)
Current node details:
* node name: 'rabbitmqcli-11445-rabbit@rabbitmq2'
* effective user's home directory: /var/lib/rabbitmq
* Erlang cookie hash: NhgpfPAyGCfXaw13WdYU9w==
解决方案
vim /etc/hosts 中把各个服务器的ip和容器主机名即hostname 加上
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
ip1主 rabbitmq1
ip2从 rabbitmq2
ip3从 rabbitmq3
注意:一定不要加上rabbit@
,比方说我之前配成 ip1主 rabbit@rabbitmq1
小结
如果采用多机部署方式,需读取其中一个节点的cookie, 并复制到其他节点(节点之间通过cookie确定相互是否可通信)。而cookie存放在/var/lib/rabbitmq/.erlang.cookie。也就说把其中一台的.erlang.cookie替换其他服务器的.erlang.cookie,其它步骤雷同单机部署方式。
原文链接