【实践】docker简易搭建RabbitMQ集群

2021-02-02 16:50:25 浏览数 (1)

RabbitMQ3

1.摘要

本文介绍RabbitMQ搭建普通集群模式和镜像集群模式的操作指南。

2. 内容

RabbitMQ有2种集群模式,分别是普通集群模式和镜像集群模式。

第一种 普通集群模式:rabbitmq集群与其他集群有些不同,rabbitmq集群同步的指是复制队列,元数据信息的同步,即同步的是数据存储信息;消息的存放只会存储在创建该消息队列的那个节点上。并非在节点上都存储一个完整的数据。在通过非数据所在节点获取数据时,通过元数据信息,路由转发到存储数据节点上,从而得到数据 。

第二种 镜像集群模式:与普通集群模式区别 主要是消息实体会主动在镜像节点间同步数据,而不是只存储数据元信息。 故普通集群模式 但凡数据节点挂了,容易造成数据丢失但镜像集群模式可以保证集群只要不全部挂掉,数据就不会丢失,当相对于性能来说,镜像集群模式会比普通集群模式多出消耗数据的传输。故取决于业务场景进行取舍。

2.1 普通集群模式

(1)拉取rabbitmq镜像

在centos窗口中,执行如下命令:

代码语言:javascript复制
docker pull rabbitmq:3.7-management
1

(2)创建映射数据卷目录,启动rabbitmq容器

在centos窗口中,执行如下命令创建文件夹:

代码语言:javascript复制
mkdir rabbitmqcluster
cd rabbitmqcluster/
mkdir rabbitmq01 rabbitmq02 rabbitmq03

操作日志如下:

代码语言:javascript复制
[root@localhost rabbitmqcluster]# pwd
/home/soft/
[root@localhost soft]# mkdir rabbitmqcluster
[root@localhost soft]# cd rabbitmqcluster/
[root@localhost rabbitmqcluster]# mkdir rabbitmq01 rabbitmq02 rabbitmq03

注:请读者自行找寻创建数据映射目录。 创建完成映射目录后,在centos窗口中,执行如下命令创建容器:

代码语言:javascript复制
docker run -d --hostname rabbitmq01 --name rabbitmqCluster01 -v /home/soft/rabbitmqcluster/rabbitmq01:/var/lib/rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' rabbitmq:3.7-management

docker run -d --hostname rabbitmq02 --name rabbitmqCluster02 -v /home/soft/rabbitmqcluster/rabbitmq02:/var/lib/rabbitmq -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie'  --link rabbitmqCluster01:rabbitmq01 rabbitmq:3.7-management

docker run -d --hostname rabbitmq03 --name rabbitmqCluster03 -v /home/soft/rabbitmqcluster/rabbitmq03:/var/lib/rabbitmq -p 15674:15672 -p 5674:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie'  --link rabbitmqCluster01:rabbitmq01 --link rabbitmqCluster02:rabbitmq02  rabbitmq:3.7-management

注: --hostname 设置容器的主机名RABBITMQ_ERLANG_COOKIE 节点认证作用,部署集成时 需要同步该值

启动容器成功后,读者可以访问 http://192.168.9.219:15672/#/ http://192.168.9.219:15673/#/ http://192.168.9.219:15674/#/ 查看是否正常启动成功。账号/密码:guest / guest。 读者登陆后,查看overview Tab页,可看到节点信息。

(3)容器节点加入集群

首先在centos窗口中,执行如下命令,进入第一个rabbitmq节点容器:

代码语言:javascript复制
docker exec -it rabbitmqCluster01 bash

进入容器后,操作rabbitmq,执行如下命令:

代码语言:javascript复制
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit

操作日志信息如下:

代码语言:javascript复制
[root@localhost rabbitmq01]# docker exec -it rabbitmqCluster01 bash
root@rabbitmq01:/# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq01 ...
root@rabbitmq01:/# rabbitmqctl reset
Resetting node rabbit@rabbitmq01 ...
root@rabbitmq01:/# rabbitmqctl start_app
Starting node rabbit@rabbitmq01 ...
 completed with 3 plugins.
root@rabbitmq01:/# exit
exit

接下来,进入第二个rabbitmq节点容器,执行如下命令:

代码语言:javascript复制
docker exec -it rabbitmqCluster02 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit

操作日志信息如下:

代码语言:javascript复制
[root@localhost rabbitmq01]# docker exec -it rabbitmqCluster02 bash
root@rabbitmq02:/# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq02 ...
root@rabbitmq02:/# rabbitmqctl reset
Resetting node rabbit@rabbitmq02 ...
root@rabbitmq02:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq01
Clustering node rabbit@rabbitmq02 with rabbit@rabbitmq01
root@rabbitmq02:/# rabbitmqctl start_app
Starting node rabbit@rabbitmq02 ...
 completed with 3 plugins.
root@rabbitmq02:/# exit
exit

最后,进入第三个rabbitmq节点容器,执行如下命令:

代码语言:javascript复制
docker exec -it rabbitmqCluster03 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit

操作日志信息如下:

代码语言:javascript复制
[root@localhost rabbitmq01]# docker exec -it rabbitmqCluster03 bash
root@rabbitmq03:/#  rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq03 ...
root@rabbitmq03:/# rabbitmqctl reset
Resetting node rabbit@rabbitmq03 ...
root@rabbitmq03:/# rabbitmqctl join_cluster --ram rabbit@rabbitmq01
Clustering node rabbit@rabbitmq03 with rabbit@rabbitmq01
root@rabbitmq03:/# rabbitmqctl start_app
Starting node rabbit@rabbitmq03 ...
 completed with 3 plugins.
root@rabbitmq03:/# exit
exit

执行上述操作,这时候 再查看 http://192.168.9.219:15672/#/ 的overview面板中的Nodes信息,可查看到节点信息。

在这里插入图片描述

(4)负载均衡设置

有了集群之后 还要设置负载均,为了防止出现对单一节点造成高负载的情况。 本次测试用例 采用nginx中间件。读者可根据自身需要进行选择。

1. 配置nginx_rabbitmq.conf信息 本机上存放着一个nginx配置文件:/home/soft/nginx/nginx_rabbitmq.conf

nginx_rabbitmq.conf

代码语言:javascript复制
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 192.168.9.219:15672;
        server 192.168.9.219:15673;
        server 192.168.9.219:15674;
    }
    server {
        listen       15675;
        server_name  192.168.9.219; 
        location / {  
            proxy_pass   http://rabbitManage;
            index  index.html index.htm;  
        }  

    }
}
# rabbitmq通信
stream{
    upstream rabbitTcp{
        server 192.168.9.219:5672;
        server 192.168.9.219:5673;
        server 192.168.9.219:5674;
    }

    server {
        listen 5675;
        proxy_pass rabbitTcp;
    }
}

注:这里配置rabbitmq管理界面 以及通信反向代理

2.启动nginx容器

在centos窗口中,执行如下命令:

代码语言:javascript复制
docker run -it -d --name nginxRabbitmq -v /home/soft/nginx/nginx_rabbitmq.conf:/etc/nginx/nginx.conf  --privileged --net=host nginx

接着读者可以通过 http://192.168.9.219:15675 进行管理 以及通过 5675 端口 进行rabbitmq通信。

2.2 镜像集群

跟第一种 普通集群模式相比,该模式加入镜像队列供,以及加入keepalived实现HA高可用进行容灾。 架构图如下:

在这里插入图片描述

(1)拉取镜像

在https://hub.docker.com/_/rabbitmq?tab=tags&page=1&ordering=last_updated 网址获取需要的RabbitMQ版本号。

在Ubuntu窗口中,执行如下命令:

代码语言:javascript复制
docker pull rabbitmq:3.8.11-management

(2)创建映射数据卷目录,启动rabbitmq容器

在shell命令窗口执行如下命令创建文件夹:

代码语言:javascript复制
mkdir rabbitmqcluster
cd rabbitmqcluster/
mkdir rabbitmq01 rabbitmq02 rabbitmq03

注:请读者自行找寻创建数据映射目录,例如pwd得到辉哥的大目录为/home/datadisk/rabbitmq/rabbitmqcluster 。

创建完成映射目录后,在centos窗口中,执行如下命令创建容器:

代码语言:javascript复制
docker run -d --hostname rabbitmq01 --name rabbitmqCluster01 -v /home/datadisk/rabbitmq/rabbitmqcluster/rabbitmq01:/var/lib/rabbitmq -p 15673:15672 -p 5673:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie' rabbitmq:3.8.11-management

docker run -d --hostname rabbitmq02 --name rabbitmqCluster02 -v /home/datadisk/rabbitmq/rabbitmqcluster/rabbitmq02:/var/lib/rabbitmq -p 15674:15672 -p 5674:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie'  --link rabbitmqCluster01:rabbitmq01 rabbitmq:3.8.11-management

docker run -d --hostname rabbitmq03 --name rabbitmqCluster03 -v /home/datadisk/rabbitmq/rabbitmqcluster/rabbitmq03:/var/lib/rabbitmq -p 15675:15672 -p 5675:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitmqCookie'  --link rabbitmqCluster01:rabbitmq01 --link rabbitmqCluster02:rabbitmq02  rabbitmq:3.8.11-management

注: --hostname 设置容器的主机名RABBITMQ_ERLANG_COOKIE 节点认证作用,部署集成时 需要同步该值

说明:如果安全组的端口关闭的话,记得打开公有云安全组和宝塔中的15673,15674,15675的端口号。

启动容器成功后,读者可以访问 http://114.67.117.226:15673/#/ http://114.67.117.226:15674/#/ http://114.67.117.226:15675/#/

查看是否正常启动成功。账号/密码:guest / guest。 读者登陆后,查看overview Tab页,可看到节点信息。

(3)容器节点加入集群

<1> 首先在shell窗口中,执行如下命令,进入第一个rabbitmq节点容器:

代码语言:javascript复制
docker exec -it rabbitmqCluster01 bash

进入容器后,操作rabbitmq,执行如下命令:

代码语言:javascript复制
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit

<2> 接下来,进入第二个rabbitmq节点容器,执行如下命令:

代码语言:javascript复制
docker exec -it rabbitmqCluster02 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit

<3> 紧接着,进入第三个rabbitmq节点容器,执行如下命令:

代码语言:javascript复制
docker exec -it rabbitmqCluster03 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq01
rabbitmqctl start_app
exit

rabbitmqctl join_cluster {cluster_node} [–ram]表示将节点加入指定集群中。在这个命令执行前需要停止RabbitMQ应用并重置节点。参数“--ram”表示同步 rabbit@rabbitmq01的内存节点,忽略次参数默认为磁盘节点。

经过以上3步,组件了3个节点的集群。

<4> 最后,实现镜像模式集群。进入rabbitmqCluster01容器中

代码语言:javascript复制
docker exec -it rabbitmqCluster01 bash

执行如下命令:

代码语言:javascript复制
rabbitmqctl set_policy -p / ha-all "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

这行命令在vhost名称为/创建了一个策略,策略名称为ha-all,策略模式为 all 即复制到所有节点,包含新增节点,策略正则表达式为 “^” 表示所有匹配所有队列名称

<1> RabbitMQ镜像策略set_policy

添加vhosts

代码语言:javascript复制
 rabbitmqctl add_vhost <vhost>
 rabbitmqctl delete_vhost <vhost>
 rabbitmqctl list_vhosts [<vhostinfoitem> ...]

参数设置格式:

代码语言:javascript复制
#设置
rabbitmqctl set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern>  <definition>

#清除
rabbitmqctl clear_policy [-p <vhost>] <name>

#查看
rabbitmqctl list_policies [-p <vhost>]

例如:

代码语言:javascript复制
##set_policy
rabbitmqctl set_policy -p vh_test1 ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'

Setting policy "ha" for pattern "^" to "{"ha-mode":"all","ha-sync-mode":"automatic"}" with priority "0"


##list_policies
rabbitmqctl list_policies -p vh_test1

Listing policies
vh_test1    ha  all ^   {"ha-mode":"all","ha-sync-mode":"automatic"}    0

##clear_policy
rabbitmqctl clear_policy -p vh_test1 ha

Clearing policy "ha"

参数 [1] ha-mode:策略键 1.all 队列镜像在群集中的所有节点上。当新节点添加到群集时,队列将镜像到该节点 2.exactly 集群中的队列实例数。 3.nodes 队列镜像到节点名称中列出的节点。

[2] ha-sync-mode:队列同步 1.manual手动<默认模式>.新的队列镜像将不会收到现有的消息,它只会接收新的消息。 2.automatic自动同步.当一个新镜像加入时,队列会自动同步。队列同步是一个阻塞操作。

为用户赋权: rabbitmqctl set_permissions -p /vhost1 user_admin '.*' '.*' '.*' 该命令使用户user_admin具有/vhost1这个virtual host中所有资源的配置、写、读权限以便管理其中的资源

执行上述操作,这时候 再查看 http://114.67.117.226:15673/#/ 的overview面板中的Nodes信息,可查看到节点信息。

6.集群节点信息

(4)负载均衡设置

有了集群之后 还要设置负载均,为了防止出现对单一节点造成高负载的情况。 本次测试用例 采用nginx中间件。读者可根据自身需要进行选择。

<1> 本机上存放着两个nginx配置文件

增加nginx目录,增加配置文件后,用docker启动NGINX反向代理。

/home/datadisk/nginx/nginx_rabbitmq_1.conf nginx_rabbitmq_1.conf

代码语言:javascript复制
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 114.67.117.226:15673;
        server 114.67.117.226:15674;
        server 114.67.117.226:15675;
    }
    server {
        listen       15676;
        server_name   114.67.117.226; 
        location / {  
            proxy_pass   http://rabbitManage;
            index  index.html index.htm;  
        }  

    }
}
# rabbitmq通信
stream{
    upstream rabbitTcp{
        server 114.67.117.226:5673;
        server 114.67.117.226:5674;
        server 114.67.117.226:5675;
    }

    server {
        listen 5676;
        proxy_pass rabbitTcp;
    }
}

/home/datadisk/nginx/nginx_rabbitmq_2.conf nginx_rabbitmq_2.conf

代码语言:javascript复制
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 114.67.117.226:15673;
        server 114.67.117.226:15674;
        server 114.67.117.226:15675;
    }
    server {
        listen       15677;
        server_name   114.67.117.226; 
        location / {  
            proxy_pass   http://rabbitManage;
            index  index.html index.htm;  
        }  

    }
}
# rabbitmq通信
stream{
    upstream rabbitTcp{
        server 114.67.117.226:5673;
        server 114.67.117.226:5674;
        server 114.67.117.226:5675;
    }

    server {
        listen 5677;
        proxy_pass rabbitTcp;
    }
}

注:这里配置rabbitmq管理界面 以及通信反向代理

<2> 启动两个nginx容器

在centos窗口中,执行如下命令:

代码语言:javascript复制
docker run -it -d --name nginxRabbitmq1 -v /home/datadisk/nginx/nginx_rabbitmq_1.conf:/etc/nginx/nginx.conf  --privileged --net=host nginx

docker run -it -d --name nginxRabbitmq2 -v /home/datadisk/nginx/nginx_rabbitmq_2.conf:/etc/nginx/nginx.conf  --privileged --net=host nginx

完成nginx的配置。如果docker本地没有NGIX,则会先自动从仓库pull最新的nginx镜像。

这时候 可以通过访问 http://114.67.117.226:15676/#/ 以及 http://114.67.117.226:15677 进行测试。是否搭建成功。

(5)安装keepalived 实现HA

<1> Keepalived说明

Keepalive简介

Keepalived是Linux下一个轻量级别的高可用解决方案。高可用(High Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭义的来讲就是之主机的冗余和接管,

它与HeartBeat RoseHA 实现相同类似的功能,都可以实现服务或者网络的高可用,但是又有差别,HeartBeat是一个专业的、功能完善的高可用软件,它提供了HA 软件所需的基本功能,比如:心跳检测、资源接管,检测集群中的服务,在集群节点转移共享IP地址的所有者等等。HeartBeat功能强大,但是部署和使用相对比较麻烦,

与HeartBeat相比,Keepalived主要是通过虚拟路由冗余来实现高可用功能,虽然它没有HeartBeat功能强大,但是Keepalived部署和使用非常的简单,所有配置只需要一个配置文件即可以完成,

Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态,它根据TCP/IP参考模型的第三、第四层、第五层交换机制检测每个服务节点的状态,如果某个服务器节点出现异常,或者工作出现故障,Keepalived将检测到,并将出现的故障的服务器节点从集群系统中剔除,这些工作全部是自动完成的,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点。

后来Keepalived又加入了VRRP的功能,VRRP(Vritrual Router Redundancy Protocol,虚拟路由冗余协议)出现的目的是解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断稳定运行,因此Keepalvied 一方面具有服务器状态检测和故障隔离功能,另外一方面也有HA cluster功能,下面介绍一下VRRP协议实现的过程。

VRRP协议与工作原理

在现实的网络环境中。主机之间的通信都是通过配置静态路由或者(默认网关)来完成的,而主机之间的路由器一旦发生故障,通信就会失效,因此这种通信模式当中,路由器就成了一个单点瓶颈,为了解决这个问题,就引入了VRRP协议。

熟悉网络的学员对VRRP协议应该不陌生,它是一种主备模式的协议,通过VRRP可以在网络发生故障时透明的进行设备切换而不影响主机之间的数据通信,这其中涉及到两个概念:物理路由器和虚拟路由器。

VRRP可以将两台或者多台物理路由器设备虚拟成一个虚拟路由,这个虚拟路由器通过虚拟IP(一个或者多个)对外提供服务,而在虚拟路由器内部十多个物理路由器协同工作,同一时间只有一台物理路由器对外提供服务,这台物理路由设备被成为:主路由器(Master角色),一般情况下Master是由选举算法产生,它拥有对外服务的虚拟IP,提供各种网络功能,如:ARP请求,ICMP 数据转发等,而且其它的物理路由器不拥有对外的虚拟IP,也不提供对外网络功能,仅仅接收MASTER的VRRP状态通告信息,这些路由器被统称为“BACKUP的角色”,当主路由器失败时,处于BACKUP角色的备份路由器将重新进行选举,产生一个新的主路由器进入MASTER角色,继续提供对外服务,整个切换对用户来说是完全透明的。

每个虚拟路由器都有一个唯一的标识号,称为VRID,一个VRID与一组IP地址构成一个虚拟路由器,在VRRP协议中,所有的报文都是通过IP多播方式发送的,而在一个虚拟路由器中,只有处于Master角色的路由器会一直发送VRRP数据包,处于BACKUP角色的路由器只会接受Master角色发送过来的报文信息,用来监控Master运行状态,一一般不会发生BACKUP抢占的情况,除非它的优先级更高,而当MASTER不可用时,BACKUP也就无法收到Master发过来的信息,于是就认定Master出现故障,接着多台BAKCUP就会进行选举,优先级最高的BACKUP将称为新的MASTER,这种选举角色切换非常之快,因而保证了服务的持续可用性。

Keepalvied的工作原理

上面我们介绍了Keepalived通过VRRP实现高可用性的工作原理,而Keepalived作为一个高性能集群软件,它还能实现对集群中服务器运行状态的监控以及故障隔离,下面我们介绍一下Keepalived对服务器运行状态和故障隔离的工作原理。

Keepalived工作在TCP/IP 参考模型的 三层、四层、五层,也就是分别为:网络层,传输层和应用层,根据TCP、IP参数模型隔层所能实现的功能,Keepalived运行机制如下:

在网络层:我们知道运行这4个重要的协议,互联网络IP协议,互联网络可控制报文协议ICMP、地址转换协议ARP、反向地址转换协议RARP,在网络层Keepalived在网络层采用最常见的工作方式是通过ICMP协议向服务器集群中的每一个节点发送一个ICMP数据包(有点类似与Ping的功能),如果某个节点没有返回响应数据包,那么认为该节点发生了故障,Keepalived将报告这个节点失效,并从服务器集群中剔除故障节点。

在传输层:提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP,传输控制协议TCP可以提供可靠的数据输出服务、IP地址和端口,代表TCP的一个连接端,要获得TCP服务,需要在发送机的一个端口和接收机的一个端口上建立连接,而Keepalived在传输层里利用了TCP协议的端口连接和扫描技术来判断集群节点的端口是否正常,比如对于常见的WEB服务器80端口。或者SSH服务22端口,Keepalived一旦在传输层探测到这些端口号没有数据响应和数据返回,就认为这些端口发生异常,然后强制将这些端口所对应的节点从服务器集群中剔除掉。

在应用层:可以运行FTP,TELNET,SMTP,DNS等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived工作方式,例如:可以通过编写程序或者脚本来运行Keepalived,而Keepalived将根据用户的设定参数检测各种程序或者服务是否允许正常,如果Keepalived的检测结果和用户设定的不一致时,Keepalived将把对应的服务器从服务器集群中剔除。

Keepalived体系结构

img

keepalived也是模块化设计,不同模块复杂不同的功能,它主要有三个模块,分别是core、check和VRRP,其中: core模块:为keepalived的核心组件,负责主进程的启动、维护以及全局配置文件的加载和解析; check:负责健康检查,包括常见的各种检查方式; VRRP模块:是来实现VRRP协议的。

system call:系统调用 watch dog:监控check和vrrp进程的看管者,check负责检测器子进程的健康状态,当其检测到master上的服务不可用时则通告vrrp将其转移至backup服务器上。

除此之外,keepalived还有下面两个组件: libipfwc:iptables(ipchains)库,配置LVS会用到 libipvs*:配置LVS会用到 注意,keepalived和LVS完全是两码事,只不过他们各负其责相互配合而已。

keepalived正常启动的时候,共启动3个进程: 一个是父进程,负责监控其子进程;一个是VRRP子进程,另外一个是checkers子进程; 两个子进程都被系统watchlog看管,两个子进程各自负责复杂自己的事。 Healthcheck子进程检查各自服务器的健康状况,,例如http,lvs。如果healthchecks进程检查到master上服务不可用了,就会通知本机上的VRRP子进程,让他删除通告,并且去掉虚拟IP,转换为BACKUP状态。

Keepalived作用: Keepalived主要用作RealServer的健康状态检查以及LoadBalance主机和BackUP主机之间failover的实现。Keepalived的作用是检测web服务器的状态,如果有一台web服务器死机,或工作出现故障,Keepalived将检测到,并将有故障的web服务器从系统中剔除,当web服务器工作正常后Keepalived自动将web服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的web服务器。

<2> 启动keepalived

【以下内容实际未执行成功,无法实现高可用。以后有空再尝试。需要特别明白keepalived的参数意思。】

在两个nginx容器分别安装keepalived,并编写keepalived配置文件以及启动keepalived。

1.1 进入nginxRabbitmq1容器中,执行如下命令:

代码语言:javascript复制
docker exec -it nginxRabbitmq1 bash
apt-get  -y update
apt-get -y  install vim
apt-get -y install keepalived

安装完成后,编写keekpalived.conf,

代码语言:javascript复制
vim /etc/keepalived/keepalived.conf

内容如下:

代码语言:javascript复制
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
       114.67.117.227
    }
}
virtual_server  114.67.117.227 15678 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server  114.67.117.226 15676 {
        weight 1
    }
}
virtual_server 114.67.117.227 5678 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 114.67.117.226 5676 {
        weight 1
    }
}

保存完配置,启动keepalived

代码语言:javascript复制
service keepalived start

注:interface 表示绑定的网络接口,请用ip addr 查看本机的网卡进行替换 ,virtual_router_id 表示keepalived家族标识信息,全局唯一,节点间保持相同

在主机命令行下允许以下命令可以查看容器内启动的进程:

代码语言:javascript复制
docker top nginxRabbitmq1

1.2 进入nginxRabbitmq2容器中,执行如下命令:

代码语言:javascript复制
docker exec -it nginxRabbitmq2 bash
apt-get  -y update
apt-get -y  install vim
apt-get -y install keepalived

安装完成后,编写keekpalived.conf,

代码语言:javascript复制
vim /etc/keepalived/keepalived.conf

内容如下:

代码语言:javascript复制
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
       114.67.117.228
    }
}
virtual_server  114.67.117.228 15678 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server  114.67.117.226 15677 {
        weight 1
    }
}
virtual_server 114.67.117.228 5678 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 114.67.117.226 5677 {
        weight 1
    }
}

保存完配置,启动keepalived

代码语言:javascript复制
service keepalived start

(6)主机上安装keepaplived进行转发

在shell窗口中,执行如下命令:

代码语言:javascript复制
apt-get -y install keepalived

安装完成后,编写配置文件keepalived.conf

代码语言:javascript复制
vim /etc/keepalived/keepalived.conf

内容如下:

代码语言:javascript复制
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
       114.67.117.228
    }
}
virtual_server  114.67.117.228 15678 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 114.67.117.227 15676 {
        weight 1
    }
    real_server 114.67.117.227 15677{
        weight 1
    }
}
virtual_server 114.67.117.228 5678 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP
    real_server 114.67.117.227 5676 {
        weight 1
    }
    real_server 114.67.117.227 5677 {
        weight 1
    } 
}

保存完配置后,启动keepalived

代码语言:javascript复制
service keepalived start

接着读者可以通过http://114.67.117.226:15678进行管理 以及通过 5678 端口 进行rabbitmq通信。 可以测试停止nginxRabbitmq1或者nginxRabbitmq2进行测试,本文就不再赘述测试过程。

(7)keepalived配置文件部分说明

代码语言:javascript复制
vrrp_instance VI_1 {              --- vrrp协议相关配置(vip地址设置)

    state MASTER                  --- keepalived角色描述(状态)信息,可以配置参数(MASTER BACKUP)

    interface eth0                --- 表示将生成虚IP地址,设置在指定的网卡上(一般为外网卡)

    virtual_router_id 51          --- 表示keepalived家族标识信息

    priority 100                  --- keepalived服务竞选主备服务器优先级设置(越大越优先)

    advert_int 1                  --- 主服务组播包发送间隔时间       

    authentication {              --- 主备主机之间通讯认证机制,

        auth_type PASS            --- 采用明文认证机制

        auth_pass 123456            --- 编写明文密码(用于主备认证)

    }

    virtual_ipaddress {           --- 设置虚拟IP地址信息

       192.168.44.130

    }
   virtual_server 192.168.44.130 15678 {  --- 设置虚拟IP地址 端口转发
   
      delay_loop 3                    ---- service polling的delay时间,即服务轮询的时间间隔
    
      lb_algo rr                     --- LVS调度算法 
      
      lb_kind NAT                    --- LVS集群模式  
    
      persistence_timeout 50          --- 会话保持时间(秒为单位),即以用户在120秒内被分配到同一个后端realserver
    
      protocol TCP                    --- 健康检查用的是TCP还是UDP
    
      real_server 192.168.9.144 15676 {
        
           weight 1                   --- 给每台的权重,0表示失效(不知给他转发请求知道他恢复正常),默认是1
   
     }
  }

}

3.参考

(1)RabbitMQ 高可用集群搭建【优质】 https://blog.csdn.net/qq_28533563/article/details/107932737

(2)docker简易搭建RabbitMQ集群【优质】

https://blog.csdn.net/belonghuang157405/article/details/83540148

(2) docker安装RabbitMQ

https://blog.csdn.net/weixin_40009737/article/details/112004194

(2)Docker下配置KeepAlive支持nginx高可用

https://www.cnblogs.com/jake-jin/p/12713324.html

(2)消息中间件—RabbitMQ(集群原理与搭建篇) https://www.jianshu.com/p/6376936845ff

(3)RabbitMQ系列(九)分布式RabbitMQ概述 https://juejin.cn/post/6844904066452029454

(4)RabbitMQ系列(十)分布式RabbitMQ(集群) https://juejin.cn/post/6844904071183220749

(5)RabbitMQ系列(十一)分布式RabbitMQ(队列镜像) https://juejin.cn/post/6844904072303116302

(6)RabbitMQ系列(十二)基于RabbitMQ的分布式事务 https://juejin.cn/post/6844904147418873864

(9)RabbitMQ官方文档搜"Distributed RabbitMQ"

https://www.rabbitmq.com/documentation.html

0 人点赞