Nginx12-集群高可用

257 阅读14分钟

Nginx12-集群高可用

1、Nginx实现服务器集群

(1)单机模式

  • 在使用Nginx和Tomcat部署项目的时候,我们使用的是一台Nginx服务器和一台Tomcat服务器,架构图如下

image-20241010112058127

(2)集群模式

  • 如果Tomcat宕机了,整个系统就无法正常运行,我们可以多搭建几台Tomcat服务器,其中一台宕机了,其他服务器还能继续运行,这也就是我们常说的集群,搭建Tomcat的集群需要用到了Nginx的反向代理和负载均衡知识,架构如下

image-20241010112354463

(3)集群实现

image-20241010114429863

  • 准备3台tomcat,使用端口进行区分[实际环境应该是三台服务器]。
cp -r /opt/apache-tomcat-9.0.96 /opt/tomcat01
cp -r /opt/apache-tomcat-9.0.96 /opt/tomcat02
cp -r /opt/apache-tomcat-9.0.96 /opt/tomcat03
  • 修改三个 Tocmat 配置文件的端口,修改server.ml,将端口修改分别修改为8180,8280,8380。
vim /opt/tomcat01/conf/server.xml
vim /opt/tomcat02/conf/server.xml
vim /opt/tomcat03/conf/server.xml

image-20241010113313142

  • 在Nginx对应的配置文件中添加如下内容
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream webservice{
        server 192.168.119.162:8180;     # tomcat01
        server 192.168.119.162:8280; 	 # tomcat02
        server 192.168.119.162:8380;	 # tomcat03
    }

    server {
        listen       80;
        server_name  localhost;
        
        location / {
                proxy_pass http://webservice;
        }
        
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
  • 启动Tomcat
# 分别开不同窗口启动tomcat
/opt/tomcat01/bin/startup.sh
/opt/tomcat02/bin/startup.sh
/opt/tomcat03/bin/startup.sh

image-20241010135827707

2、Nginx高可用解决方案

(1)概述

  • 完成了上述环境的部署,我们已经解决了Tomcat的高可用性,一台服务器宕机,还有其他两台对外提供服务。
  • 但是新问题出现了,上述环境中,如果是Nginx宕机了,那么整套系统都将服务对外提供服务了,所以我们需要两台以上Nginx服务器做集群。但是两台Nginx我们访问哪一台呢?下面我们来解决这个问题。

(2)Keepalived

  • Keepalived 软件由 C 编写的,最初是专为 LVS 负载均衡软件设计的,Keepalived 软件主要是通过 VRRP 协议实现高可用功能。

  • VRRP(Virtual Route Redundancy Protocol)协议,翻译过来为虚拟路由冗余协议。

  • VRRP协议的作用

    • 选择协议:VRRP可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台。其中的虚拟路由即Virtual路由是由VRRP路由群组创建的一个不真实存在的路由,这个虚拟路由也是有对应的IP地址。而且VRRP路由1和VRRP路由2之间会有竞争选择,通过选择会产生一个Master路由和一个Backup路由。
    • 路由容错协议:Master路由和Backup路由之间会有一个心跳检测,Master会定时告知Backup自己的状态,如果在指定的时间内,Backup没有接收到这个通知内容,Backup就会替代Master成为新的Master。Master路由有一个特权就是虚拟路由和后端服务器都是通过Master进行数据传递交互的,而备份节点则会直接丢弃这些请求和数据,不做处理,只是去监听Master的状态

    image-20241010142439970

(3)Keepalived+Nginx架构图

  • VIP 是虚拟路由,是专门给用户发送请求。一旦用户发送请求到 VIP,VIP 就会发送给 Master(主)的 Nginx,如果 Master(主)Nginx 宕机了,才会发送给 Backup(备份) Nginx 路由。

image-20241010142632155

(4)环境搭建

  • 环境准备
IP主机名主/从
192.168.119.163keepalivedvip
192.168.119.164(服务器A)keepalived1Master
192.168.119.165(服务器B)keepalived2Backup

image-20241012212147122

  • Nginx:keepalived1+keepalived2安装,配置保持一致,安装参考Nginx在Linux下安装篇:blog.csdn.net/liyou123456…

  • keepalived:keepalived1+keepalived2安装

# 创建目录
mkdir /opt/keepalived
cd /opt/keepalived

# 官网地址:https://keepalived.org/
# 官网下载地址:https://keepalived.org/download.html
# 百度网盘地址:https://pan.baidu.com/s/1PHTVk4WhIJ_Pm-c89rY4jQ?pwd=1234
# 上传keepalived-2.0.20.tar.gz文件到/opt/keepalived目录

# 解压文件
tar -zxf keepalived-2.0.20.tar.gz -C /opt/keepalived

# 对 keepalived 进行配置,编译和安装
cd /opt/keepalived/keepalived-2.0.20
./configure --sysconf=/etc --prefix=/usr/local   # 安装到 /usr/local 目录下,可修改
make && make install
  • /usr/local/sbin 目录下的 keepalived:这是系统配置脚本,用来启动和关闭 keepalived

(5)keepalived配置文件

  • 配置文件路径/etc/keepalived/keepalived.conf

  • 配置文件说明如下

    • 第一部分是 global 全局配置
    • 第二部分是 vrrp 相关配置:包含四个子模块
      • vrrp_script
      • vrrp_sync_group
      • garp_group
      • vrrp_instance
    • 第三部分是 LVS 相关配置
  • 这里需要修改的是 5、6、8 行代码。

# global全局部分
global_defs {
    
   notification_email {  # 通知邮件,当 keepalived 切换 Master 和 Backup 时需要发 email 给具体的邮箱地址
     tom@test.com
     jerry@test.com
   }
   notification_email_from test@test.com   # 设置发件人的邮箱信息
   
   smtp_server 192.168.119.1   # 指定 smpt 服务地址
   
   smtp_connect_timeout 30   # 指定 smpt 服务连接超时时间
   
   router_id LVS_DEVEL   # 运行 keepalived 服务器的一个标识,可以用作发送邮件的主题信息
   
   # 默认是不跳过检查。检查收到的 VRRP 通告中的所有地址可能会比较耗时,设置此命令的意思是,如果通告与接收的上一个通告来自相同的 master 路由器,则不执行检查(跳过检查)
   vrrp_skip_check_adv_addr
   
   vrrp_strict    # 严格遵守 VRRP 协议
  
   vrrp_garp_interval 0   # 在一个接口发送的两个免费 ARP 之间的延迟。可以精确到毫秒级。默认是 0
   
   vrrp_gna_interval 0  # 在一个网卡上每组消息之间的延迟时间,默认为 0
}
  • vrrp_instance 模块内容
    • 第 3 行代码是说明当前 Nginx 服务器的角色是 Master 还是 Backup。分别在服务器 A 和 B 进行角色配置。
    • 第 5 行代码是 VIP 的 ID,如果使用相同的虚拟路由 VIP,请保持 ID 一致。
    • 第 6 行代码是优先级,请让 Master 服务器的优先级大于 Backup 服务器的优先级。如 100 > 90。
    • 第 7 行代码是 Master 和 Backup 之间通信的间隔时间,如果无法通信,说明 Master 已经宕机,则切换为 Backup。
    • 第 13 行代码是用户访问的虚拟 IP 地址,即 VIP,它会发送给 Nginx 服务器。
  • vrrp_instance 模块中我们修改的是第 3、5、6、7、13 行代码。
# 设置 keepalived 实例的相关信息,VI_1 为 VRRP 实例名称
vrrp_instance VI_1 {
    state MASTER  		  # 有两个值可选 MASTER 主,BACKUP 备
    interface ens33		  # vrrp 实例绑定的接口,用于发送 VRRP 包[当前服务器使用的网卡名称]
    virtual_router_id 51  # 指定 VRRP 实例 ID,范围是 0-255
    priority 100		  # 指定优先级,优先级高的将成为 MASTER
    advert_int 1		  # 指定发送 VRRP 通告的间隔,单位是秒。这里是心跳检查的时间
    authentication {	  # vrrp 之间通信的认证信息
        auth_type PASS	  # 指定认证方式。PASS 简单密码认证(推荐)
        auth_pass 1111	  # 指定认证使用的密码,最多 8 位
    }
    virtual_ipaddress {   # 虚拟 IP 地址设置虚拟 IP 地址,供用户访问使用,可设置多个,一行一个
        192.168.119.163
    }
}
  • 服务器A的Keepalived 的具体配置内容如下:
! Configuration File for keepalived

global_defs {
   notification_email {
     Tom@test.com
   }
   notification_email_from test@test.com
   smtp_server 192.168.119.1
   smtp_connect_timeout 30
   router_id keepalived1
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.119.163
    }
}
...
  • 服务器B的Keepalived 的具体配置内容如下:
! Configuration File for keepalived

global_defs {
   notification_email {
     Tom@test.com
   }
   notification_email_from Tom@test.com
   smtp_server 192.168.119.1
   smtp_connect_timeout 30
   router_id keepalived2
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 90
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.119.163
    }
}

(6)测试访问

  • 启动keepalived之前,咱们先使用命令 ip a,查看服务器A(MASTER)和服务器B(BACKUP)这两台服务器的IP情况。
# 服务器A
[root@localhost keepalived]# ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1d:94:ff brd ff:ff:ff:ff:ff:ff
    inet 192.168.119.164/24 brd 192.168.119.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7f3d:1c1c:b384:df37/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
# 服务器B
[root@localhost keepalived]# ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:75:69:c4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.119.165/24 brd 192.168.119.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7f3d:1c1c:b384:df37/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::8bc6:fc3c:4e91:dddf/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
  • 分别启动两台服务器的keepalived
cd /usr/local/sbin
./keepalived
  • 再次通过 ip a查看ip,服务器A(MASTER)多出来一个192.168.119.163,服务器B(BACKUP)和之前一样没变化
# 服务器A
[root@localhost sbin]# ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1d:94:ff brd ff:ff:ff:ff:ff:ff
    inet 192.168.119.164/24 brd 192.168.119.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.119.163/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7f3d:1c1c:b384:df37/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
# 服务器B
[root@localhost sbin]# ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:75:69:c4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.119.165/24 brd 192.168.119.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7f3d:1c1c:b384:df37/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::8bc6:fc3c:4e91:dddf/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
  • 服务器A(MASTER)关闭keepalived
# 服务器A
[root@localhost sbin]# ps -ef|grep keepalived
root     112299      1  0 20:48 ?        00:00:00 ./keepalived
root     112300 112299  0 20:48 ?        00:00:00 ./keepalived
root     112301 112299  0 20:48 ?        00:00:00 ./keepalived
root     125002   2471  0 21:03 pts/2    00:00:00 grep --color=auto keepalived
[root@localhost sbin]# kill -9 112299
[root@localhost sbin]# ps -ef|grep keepalived
root     125277   2471  0 21:03 pts/2    00:00:00 grep --color=auto keepalived
  • 再次通过 ip a查看ip,服务器A(MASTER)的192.168.119.163没有了,转移到了服务器B(BACKUP)上
# 服务器A
[root@localhost sbin]# ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:1d:94:ff brd ff:ff:ff:ff:ff:ff
    inet 192.168.119.164/24 brd 192.168.119.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7f3d:1c1c:b384:df37/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
# 服务器B
[root@localhost sbin]# ip a
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:75:69:c4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.119.165/24 brd 192.168.119.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet 192.168.119.163/32 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::7f3d:1c1c:b384:df37/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::8bc6:fc3c:4e91:dddf/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
  • 通过上述的测试,我们会发现,虚拟IP(VIP)会在MASTER节点上,当MASTER节点上的keepalived出问题以后,因为BACKUP无法收到MASTER发出的VRRP状态通过信息,就会直接升为MASTER。VIP也会"漂移"到新的MASTER。
  • 我们把服务器A的keepalived再次启动下,由于它的优先级高于服务器B的,所有它会再次成为MASTER,VIP也会"漂移"回去。
  • 我们现在访问虚拟服务器http://192.168.119.163/,页面显示成功

image-20241012215850332

(7)vrrp_script

  • keepalived只能做到对网络故障和keepalived本身的监控,即当出现网络故障或者keepalived本身出现问题时,进行自动切换。
  • 但是这些还不够,我们还需要监控keepalived所在服务器上的其他业务,比如Nginx,如果Nginx出现异常了,仅仅keepalived保持正常,是无法完成系统的正常工作的,因此需要根据业务进程的运行状态决定是否需要进行主备切换,这个时候,我们可以通过编写脚本对业务进程进行检测监控。
  • 需要在keepalived配置文件中添加对应的配置内容
vrrp_script 脚本名称
{
    script "脚本位置"
    interval 3 #执行时间间隔
    weight -20 #动态调整vrrp_instance的优先级
}
  • 实现步骤

    • 在服务器A,编写脚本,这里的脚本名是 ck_nginx.sh,位置在 /etc/keepalived 路径下。
      • ps 命令用于显示当前进程 (process) 的状态。

      • -C(command):指定命令的所有进程。

      • --no-header:排除标题。

    #!/bin/bash
    
    # 使用 ps 命令查询 nginx 进程数,并通过 wc -l 统计行数
    num=$(ps -C nginx --no-header | wc -l)  # 查询 Nginx 的进程数
    
    # 检查 Nginx 的进程数是否等于 0
    if [ "$num" -eq 0 ]; then
        echo "Nginx process is not running. Attempting to stop keepalived."
    
        # 尝试杀死所有 keepalived 进程
        killall keepalived
    
        # 检查 killall 命令是否执行成功
        if [ $? -eq 0 ]; then
            echo "Successfully stopped keepalived."
        else
            echo "Failed to stop keepalived. Please check permissions or if keepalived is running."
        fi
    else
        echo "Nginx is running with $num processes."
    fi
    
    • 为脚本文件设置权限
    chmod 755 /etc/keepalived/ck_nginx.sh
    
    • 配置文件添加vrrp_script,下面的vrrp_instance中加上track_script
    vrrp_script ck_nginx {
       script "/etc/keepalived/ck_nginx.sh" # 执行脚本的位置
       interval 2		# 执行脚本的周期,秒为单位
       weight -20		# 权重的计算方式
    }
    vrrp_instance VI_1 {
        state MASTER
        interface ens33
        virtual_router_id 10
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.200.111
        }
        track_script {
          ck_nginx
        }
    }
    
    • 配置文件修改完成后重新启动keepalived,把nginx关闭,再看keepalived,已经自动关闭
    [root@localhost keepalived]# cd /usr/local/sbin
    [root@localhost sbin]# ps -ef|grep nginx
    root      88865      1  0 21:47 ?        00:00:00 nginx: master process nginx
    nobody    88866  88865  0 21:47 ?        00:00:00 nginx: worker process
    root      88907   2085  0 21:47 pts/0    00:00:00 grep --color=auto nginx
    [root@localhost sbin]# ps -ef|grep keepalived
    root      86830      1  0 21:45 ?        00:00:00 ./keepalived
    root      86831  86830  0 21:45 ?        00:00:00 ./keepalived
    root      86832  86830  0 21:45 ?        00:00:00 ./keepalived
    root      89054   2085  0 21:47 pts/0    00:00:00 grep --color=auto keepalived
    [root@localhost sbin]# kill -9 86830
    [root@localhost sbin]# ps -ef|grep keepalived
    root      89378   2085  0 21:47 pts/0    00:00:00 grep --color=auto keepalived
    [root@localhost sbin]# ./keepalived
    [root@localhost sbin]# ps -ef|grep keepalived
    root      89465      1  0 21:48 ?        00:00:00 ./keepalived
    root      89466  89465  0 21:48 ?        00:00:00 ./keepalived
    root      89467  89465  0 21:48 ?        00:00:00 ./keepalived
    root      89543   2085  0 21:48 pts/0    00:00:00 grep --color=auto keepalived
    [root@localhost sbin]# nginx -s stop
    [root@localhost sbin]# ps -ef|grep keepalived
    root      89819   2085  0 21:48 pts/0    00:00:00 grep --color=auto keepalived
    
    • MASTER转移到服务器B
    # 服务器A	
    [root@localhost sbin]# ip a
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:0c:29:1d:94:ff brd ff:ff:ff:ff:ff:ff
        inet 192.168.119.164/24 brd 192.168.119.255 scope global noprefixroute ens33
           valid_lft forever preferred_lft forever
        inet6 fe80::7f3d:1c1c:b384:df37/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    
    # 服务器B
    [root@localhost keepalived]# ip a
    2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:0c:29:75:69:c4 brd ff:ff:ff:ff:ff:ff
        inet 192.168.119.165/24 brd 192.168.119.255 scope global noprefixroute ens33
           valid_lft forever preferred_lft forever
        inet 192.168.119.163/32 scope global ens33
           valid_lft forever preferred_lft forever
        inet6 fe80::7f3d:1c1c:b384:df37/64 scope link tentative noprefixroute dadfailed 
           valid_lft forever preferred_lft forever
        inet6 fe80::8bc6:fc3c:4e91:dddf/64 scope link noprefixroute 
           valid_lft forever preferred_lft forever
    
    • 如果效果没有出来,可以使用 tail -f /var/log/messages 查看日志信息,找对应的错误信息进行调试