Wisdom_xiaogui 发表于 2022-7-28 10:23

单台服务器docker如何搭建rabbitmq集群

> 1、**本文是在同一台服务器上拥有不同的docker容器,每个容器都有自己的rabbitmq服务**
> 2、**这里演示3个docker,15672为主节点,15673和15674分别为从节点**

# 一、创建多个RabbitMQ容器
1、创建15672主节点容器

```shell
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

```shell
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

```shell
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
```


参数解释:

```shell
-d 容器后台运行

--hostname rabbitmq1 容器的主机名为 rabbitmq1,到时候从节点进行绑定的时候,需要根据这个节点名进行映射

--name myrabbit1 容器名为myrabbit1 ,在宿主机上运行“docker ps”命令时显示的名称

-p "5672:5672" 消息通讯端口,容器端口:宿主机端口

-p "15672:15672" 后台管理端口

--linkmyrabbit1: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
```

1. 启动完毕后,在网页打开ip:15672访问看看是否正常

2. 用户:admin
3. 密码:admin
4. **如果还访问不了,注意看一下服务器的防火墙有没有开放对应的端口!**
5. 当服务器的防火墙开放端口后,依旧访问不了,可以进入容器里面,开启rabbitMQ服务

```shell
docker exec -it myrabbit1 bash
rabbitmqctl start_app
```

![在这里插入图片描述](https://img-blog.csdnimg.cn/fa7c79015fac419695277f49039db82d.png#pic_center)


> 注意:
> 1. rabbitmq的cookie也要保持一致否则建立不了集群关系
> 2. 如果是在不同的服务器,--add-host后面的参数一定要记得填写对应的ip



# 二、将RabbitMQ节点加入到集群中

1、15672主节点容器

```shell
# 命令行的形式进入myrabbit1容器
docker exec -it myrabbit1 bash
#停止当前的MQ
rabbitmqctl stop_app
#目的是清除节点上的历史数据(如果不清除,无法将节点加入到集群)
rabbitmqctl reset
#启动应用
rabbitmqctl start_app
exit
```

2、15673从节点1容器

```shell
# 命令行的形式进入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容器

```shell
docker exec -it myrabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq1
rabbitmqctl start_app
exit
```

# 三、测试

1、登录主节点,ip:15672

![在这里插入图片描述](https://img-blog.csdnimg.cn/8d41b32aab744449b28ed5245c081aeb.png#pic_center)



2、在主节点15672创建交换机

![在这里插入图片描述](https://img-blog.csdnimg.cn/22f64b9ed3cb48fcbc88be6afb8a1f06.png#pic_center)


3、发现从节点15673也有该交换机

![在这里插入图片描述](https://img-blog.csdnimg.cn/807385c421a24623881b96c17706a640.png#pic_center)


4、在从接待15673创建队列,并发送消息

![在这里插入图片描述](https://img-blog.csdnimg.cn/b4416ae94c30462b98d4dde994816f1b.png#pic_center)


5、主节点15672收到消息

![在这里插入图片描述](https://img-blog.csdnimg.cn/15368bbf39704eb8b7f4cb66c8fdbee3.png#pic_center)




6、验证集群状态

```shell
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
文件内容:

```java
usernginx;
worker_processes1;

error_log/var/log/nginx/error.log warn;
pid      /var/run/nginx.pid;


events {
    worker_connections1024;
}


http {
    include       /etc/nginx/mime.types;
    default_typeapplication/octet-stream;

    log_formatmain'$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.logmain;

    sendfile      on;
    #tcp_nopush   on;

    keepalive_timeout65;

    #gzipon;
       
        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_size64k;
        proxy_temp_file_write_size 64k;
        #rabbitmq管理界面
        upstream rabbitManage { # 负载均衡配置,默认轮询,将客户的请求,平均分摊到下面的服务器上
                server ip1主:15672;
                server ip2从:15672;
                server ip3从:15672;
        }
        server {
      listen       15673;
      server_nameip_nginx;# 负载均衡服务器Ip
      location / {
            proxy_pass   http://rabbitManage;
            indexindex.html index.htm;
      }
    }
}
# rabbitmq通信
stream{
        upstream rabbitTcp{
      server ip1主:5672;
      server ip2从:5672;
      server ip3从:5672;
    }

    server {
      listen       5673;
      server_nameip_nginx;# 负载均衡服务器Ip
      location / {
            proxy_pass   http://rabbitTcp;
            indexindex.html index.htm;
      }
    }
}
```

配置完毕后启动nginx:

```shell
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,拥有超级管理员角色和权限

```shell
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主机名

详细报错内容
# rabbitmqctl join_cluster rabbit@rabbitmq1

```shell
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 加上

```shell
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,其它步骤雷同单机部署方式。

原文链接

Js_Aaron 发表于 2022-7-28 10:42

写得好。我选择rocketmq

小小学生 发表于 2022-7-28 10:53

挺好的 支持一下 新手学起来

damon911 发表于 2022-7-28 11:00

不错 但是我友情提示一下(不是杠,不是挑刺)单机部署最好做成docker-compose 一键部署

zjlpsw 发表于 2022-7-28 11:13

谢谢楼主,支持分享,正需要用

a22488 发表于 2022-7-28 11:15

不错学习了

photocs 发表于 2022-7-28 11:54

跟着学习一下!

tencentma 发表于 2022-7-28 14:09

damon911 发表于 2022-7-28 11:00
不错 但是我友情提示一下(不是杠,不是挑刺)单机部署最好做成docker-compose 一键部署

同意,我一般也这样

956495971 发表于 2022-7-28 15:58

那这个挂了是不是等于集群全挂
页: [1]
查看完整版本: 单台服务器docker如何搭建rabbitmq集群