Skip to content

LVS-负载均衡

LVS 核心概念

LVS 是由章文嵩博士开发的开源负载均衡解决方案,通过将客户端请求分发到多台后端服务器(Real Server),构建高性能、高可用的虚拟服务器集群系统。其核心组件包括:

  • 负载均衡器(Director Server):接收客户端请求,通过调度算法分发流量。
  • 真实服务器(Real Server, RS):实际处理请求的后端服务器。
  • 虚拟 IP(VIP):客户端访问的统一入口地址,由负载均衡器管理。

工作模式详解

LVS 支持三种主流工作模式,适用于不同网络环境和性能需求:

NAT 模式

  • 原理:负载均衡器修改请求包的目标 IP 和端口(VIP → RIP),并将响应包源 IP 改回 VIP。双向流量均需经过负载均衡器
  • 特点
    • 支持端口映射(如将外部 80 端口映射到内部 8080)。
    • 负载均衡器易成瓶颈(需处理全量流量),适合小型集群(10-20 台)。
    • 真实服务器网关必须指向负载均衡器。

DR 模式

  • 原理:负载均衡器仅修改请求包的 目标 MAC 地址(指向选定的 RS),响应包由 RS 直接返回客户端(不经过负载均衡器)。
  • 特点
    • 高性能(负载均衡器仅处理请求分发),支持百台级服务器。
    • 要求负载均衡器与 RS 在同一局域网,且 RS 需配置 VIP 并启用 ARP 抑制(避免地址冲突)。
    • 不支持端口映射。

TUN 模式

  • 原理:负载均衡器将请求包封装在 IP 隧道中(新增 IP 头),RS 解封后处理请求并直接响应客户端。
  • 特点
    • 支持跨网段/异地部署(如云环境多区域集群)。
    • RS 需支持 IP 隧道协议(如 Linux IPIP 模块)。
    • 运维复杂度较高,适用特定场景。

三种模式对比

特性NAT 模式DR 模式TUN 模式
性能瓶颈高(全流量经过)低(仅请求分发)中(隧道封装开销)
网络要求可跨网段必须同一局域网支持跨网段/异地
RS 系统要求无特殊限制需支持 ARP 抑制需支持 IP 隧道协议
典型应用场景小型内部集群高并发本地集群(如电商)分布式/跨地域服务
端口映射支持不支持不支持

调度算法

LVS 根据业务需求选择不同调度策略:

  • 静态算法

    • 轮询(RR):依次分配请求至各 RS(性能均衡场景)。
    • 加权轮询(WRR):按 RS 权重分配流量(处理能力差异场景)。
    • 源 IP 哈希(SH):同一客户端 IP 固定分发至特定 RS(会话保持场景)。
  • 动态算法

    • 最少连接(LC):优先选择当前连接数最少的 RS(长连接服务)。
    • 加权最少连接(WLC):综合权重与连接数的最优分配(默认推荐算法)。

各IP地址代表的含义

缩写全称中文名称角色与含义
CIPClient IP客户端 IP 地址发起请求的终端用户设备的 IP 地址。
VIPVirtual IP虚拟 IP 地址对外提供服务的 IP 地址。客户端直接访问的这个IP,它通常配置在负载均衡器(LVS Director)和所有Real Server上。
DIPDirector IP调度器 IP 地址负载均衡器(LVS Director)与后端服务器通信时使用的内部 IP 地址
RIPReal Server IP真实服务器 IP 地址后端真正处理请求的应用服务器(如Nginx、Apache)的物理 IP 地址

核心优势

  1. 高性能:工作在网络四层,无应用层解析开销,吞吐量可达千兆级。
  2. 高可用:支持与 Keepalived 集成实现双机热备,自动屏蔽故障节点。
  3. 扩展性:DR/TUN 模式可扩展至上百台服务器,适应业务增长。
  4. 透明性:客户端与 RS 无需感知集群存在,无缝接入现有架构。

LVS-NAT模式搭建

mermaid
graph TD
    subgraph "External Network (VMNET8)"
        A[WAN Client<br/>IP: 192.168.148.150]
    end

    subgraph "LVS Load Balancer"
        B[LVS Load Balancer]
        B_ens32[ens32: 192.168.148.130]
        B_ens33[ens33: 192.168.148.161]
    end

    subgraph "Internal Network (VMNET1)"
        C[Real Server<br/>HTTP Server 1<br/>IP: 192.168.148.131<br/>GW:192.168.148.130]
        D[Real Server<br/>HTTP Server 2<br/>IP: 192.168.148.132<br/>GW:192.168.148.130]
        E[Real Server<br/>HTTP Server 3<br/>IP: 192.168.148.133<br/>GW:192.168.148.130]
    end

    A -->|VMNET8| B_ens33
    B_ens32 -->|VMNET1| C
    B_ens32 -->|VMNET1| D
    B_ens32 -->|VMNET1| E

    style A fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style B fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    style C fill:#f1f8e9,stroke:#33691e,stroke-width:2px
    style D fill:#f1f8e9,stroke:#33691e,stroke-width:2px
    style E fill:#f1f8e9,stroke:#33691e,stroke-width:2px

环境准备

IP地址主机操作系统预装软件
192.168.148.130;VIP:192.168.159.130lvs-serveropenEuler-24.03(LTS)ipvsadm,内核模块ip_vs
192.168.148.131lvs-real01openEuler-24.03(LTS)nginx
192.168.148.132lvs-real02openEuler-24.03(LTS)nginx

lvs-server配置

VIP配置

我这里使用的是VMWare增加的虚拟网卡,网卡类型选择的是主机模式主要用于区分开集群内IP段

内核配置

bash
# 开启路由转发功能,因为调度器同时承载着网关的角色
sed -i 's/net.ipv4.ip_forward = 0"/net.ipv4.ip_forward = 1/' /etc/sysctl.conf
sysctl -p

# 加载内核模块ip_vs
modprobe ip_vs

# 查看lp_vs
lsmod |grep ip_vs

配置LVS负载池

bash
dnf -y install ipvsadm

# 指定集群的VIP地址(Virtual IP),rr指定轮询调度算法
ipvsadm -A -t 192.168.148.161:80 -s rr

# -m表示NAT模式,-w指定权重值
ipvsadm -a -t 192.168.148.161:80 -r 192.168.148.131:80 -m -w 1
ipvsadm -a -t 192.168.148.161:80 -r 192.168.148.132:80 -m -w 1

# 保存规则
ipvsadm-save -n > /etc/sysconfig/ipvsadm

# 查看规则
ipvsadm -L

real后端集群配置

安装nginx服务

bash
dnf -y install nginx
hostname -I > /usr/share/nginx/html/index.html

网卡配置

LVS后端服务的网卡只需要将网关地址设置成lvs-server的同网段IP地址

bash
vim /etc/sysconfig/network-scripts/ifcfg-ens32
GATEWAY=192.168.148.130

# 重启网卡
systemctl restart NetworkManager
nmcli conn down ens32; nmcli conn up ens32

测试

bash
curl 192.168.159.130

LVS-RD模式搭建

mermaid
flowchart TD
    subgraph Internet[公网 Internet]
        Client[客户端 Client<br/>CIP: 访问者IP]
    end

    Firewall[防火墙]
    Switch[核心交换机]

    subgraph LVS_Cluster[LVS 负载均衡集群]
        VS[负载均衡器 VS<br/>主机名: lvs-server<br/>DIP: 192.168.148.130<br/>管理VIP: 192.168.148.161]
    end

    subgraph App_Servers[Web 应用服务器池]
        RS1[真实服务器 RS-1<br/>主机名: lvs-real01<br/>RIP: 192.168.148.131<br/>绑定隐藏VIP: 192.168.148.161]
        RS2[真实服务器 RS-2<br/>主机名: lvs-real02<br/>RIP: 192.168.148.132<br/>绑定隐藏VIP: 192.168.148.161]
    end

    Client -->|"请求: Client -> VIP(192.168.148.161)"| Firewall
    Firewall -->|请求包| Switch
    Switch -->|"请求: Client -> VIP(192.168.148.161)"| VS

    VS -->|"1. 接收请求<br/>2. 根据调度算法(如: rr/wlc)<br/>选择一台RS (lvs-real01/02)<br/>3. 仅修改目标MAC地址<br/>(源/目的IP、端口不变)"| Switch

    Switch -->|"数据帧: 目标MAC为 lvs-real01"| RS1
    Switch -->|"数据帧: 目标MAC为 lvs-real02"| RS2

    RS1 -->|"响应: VIP(192.168.148.161) -> Client<br/>(直接返回客户端,不经过VS)"| Client
    RS2 -->|"响应: VIP(192.168.148.161) -> Client<br/>(直接返回客户端,不经过VS)"| Client

    %% 样式
    style Internet fill:#f0f8ff
    style LVS_Cluster fill:#f0fff0
    style App_Servers fill:#fff0f5
    style Client fill:#bae1ff
    style VS fill:#baffc9
    style RS1 fill:#ffdfba
    style RS2 fill:#ffdfba

NOTE

这种模式搭建的LVS负载均衡存在弊端,这里搭建的LVS并没有健康检查,如果后端服务节点的服务宕机了,那么LVS依旧会负载,并不会剔除掉有问题的节点,可以使用Keepalived来规避

环境准备

IP地址VIP主机操作系统预装软件
192.168.148.130192.168.148.161lvs-serveropenEuler-24.03(LTS)ipvsadm,内核模块ip_vs
192.168.148.131192.168.148.161lvs-real01openEuler-24.03(LTS)nginx
192.168.148.132192.168.148.161lvs-real02openEuler-24.03(LTS)nginx

网络拓扑要求

  • 所有节点(调度器、Real Server)必须在同一局域网(二层互通),确保 MAC 地址可直达。
  • Real Server 的默认网关不可指向调度器,需指向实际路由器(如 192.168.148.1

调度器配置(lvs-server)

安装 ipvsadm

bash
dnf install ipvsadm -y
systemctl enable --now ipvsadm

配置VIP

bash
cat > /etc/sysconfig/network-scripts/ifcfg-ens32:0 << "EOF"
DEVICE=ens32:0
ONBOOT=yes
IPADDR=192.168.148.161
NETMASK=255.255.255.255
EOF

systemctl restart NetworkManager
nmcli conn down ens32;nmcli conn up ens32
  • NETMASK:子网掩码必须为/32位

ip_vs配置

bash
# 加载内核模块ip_vs
modprobe ip_vs

# 查看lp_vs
lsmod |grep ip_vs

内核配置

bash
# 替换为实际网卡名
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens32.send_redirects = 0


# 内核配置生效
sysctl -p

# 注解:
# 开启路由转发功能,因为调度器同时承载着网关的角色
# 禁止转发重定向报文
# 禁止默认转发重定向报文
# 禁止ens32网卡转发重定向报文

配置LVS负载池

bash
dnf -y install ipvsadm

# 指定集群的VIP地址(Virtual IP),rr指定轮询调度算法
ipvsadm -A -t 192.168.148.161:80 -s rr

# -g表示DR模式,-w指定权重值
ipvsadm -a -t 192.168.148.161:80 -r 192.168.148.131:80 -g -w 1
ipvsadm -a -t 192.168.148.161:80 -r 192.168.148.132:80 -g -w 1

# 保存规则使用 -n参数禁止反向解析,直接保存 IP 地址
ipvsadm-save -n > /etc/sysconfig/ipvsadm

# 查看规则
ipvsadm -Ln

# 清理规则
ipvsadm --clear
# 清空错误规则
ipvsadm -C

Real 配置(lvs-real)

后端节点配置一样,后端所有节点都要配置

安装nginx服务

bash
dnf -y install nginx

# Real Server 1
echo "Real Server 1 ($(hostname -I))" > /usr/share/nginx/html/index.html
# Real Server 2
echo "Real Server 2 ($(hostname -I))" > /usr/share/nginx/html/index.html

# 启动服务
nginx

配置VIP

bash
cat > /etc/sysconfig/network-scripts/ifcfg-ens32:0 << "EOF"
DEVICE=ens32:0
ONBOOT=yes
IPADDR=192.168.148.161
NETMASK=255.255.255.255
EOF

systemctl restart NetworkManager
nmcli conn down ens32;nmcli conn up ens32

内核配置

bash
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens32.send_redirects = 0
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.ens32.arp_ignore = 1
net.ipv4.conf.ens32.arp_announce = 2


# 内核配置生效
sysctl -p

# 注解:
# 开启路由转发功能,因为调度器同时承载着网关的角色
# 禁止转发重定向报文
# 禁止默认转发重定向报文
# 禁止ens32网卡转发重定向报文
# ARP 抑制

客户端访问测试

LVS的DR模式在server端请求VIP地址是不会通的,这是正常现象,必须使用客户端请求VIP地址

bash
curl 192.168.148.161

Keepalived+LVS 部署

环境准备

角色IP地址VIP功能
LVS主节点192.168.148.130192.168.148.161运行Keepalived MASTER,流量分发
LVS备节点192.168.148.131192.168.148.161运行Keepalived BACKUP
Nginx负载均衡192.168.148.132绑定VIP到lo负载均衡代理后端Tomcat
Nginx负载均衡192.168.148.133绑定VIP到lo负载均衡代理后端Tomcat
Tomcat192.168.148.134-Tomcat管理Java业务
Tomcat192.168.148.135-Tomcat管理Java业务

核心要求

  • 所有节点时间同步(chronyd
  • 关闭防火墙:systemctl disable --now firewalld
  • 禁用SELinux:setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

时间同步

bash
dnf -y install ntpdate
# 日期同步
ntpdate ntp1.aliyun.com

通用基础配置(所有节点执行)

加载IPVS内核模块

bash
modprobe ip_vs
echo "ip_vs" >> /etc/modules-load.d/ipvs.conf  # 开机自启
lsmod | grep ip_vs  # 验证

LVS节点配置(主备节点)

内核优化

bash
cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.ens32.send_redirects = 0
EOF
sysctl -p

安装服务

bash
# ipvsadm用于调试
dnf install -y keepalived ipvsadm

Keepalived主节点配置

bash
cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
    router_id LVS_MASTER  # 唯一标识
}

vrrp_instance VI_1 {
    state MASTER
    interface ens32       # 网卡名(ip a查看)
    virtual_router_id 51  # 主备必须一致
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111    # 主备密码一致
    }
    virtual_ipaddress {
        192.168.148.161/32 dev ens32  # VIP绑定
    }
    # 非抢占模式(防抖动)
    nopreempt
    # 单播通信(避免VRRP广播风暴)
    unicast_src_ip 192.168.148.130   # 本机IP
    unicast_peer {
        192.168.148.131              # 对端IP
    }
}

virtual_server 192.168.148.161 80 {
    delay_loop 6
    lb_algo wrr           # 加权轮询
    lb_kind DR            # DR模式
    #persistence_timeout 30  # 会话保持
    protocol TCP

    # 真实服务器1(HTTP健康检查)
    real_server 192.168.148.132 80 {
        weight 1
        HTTP_GET {
            url {
                path /health_check
                status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }
    # 真实服务器2(同上)
    real_server 192.168.148.133 80 {
        weight 1
        HTTP_GET {
            url {
                path /health_check
                status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }
}
EOF

Keepalived备节点配置

bash
cat > /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
    router_id LVS_BACKUP  	# 唯一标识
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens32       	# 网卡名(ip a查看)
    virtual_router_id 51  	# 主备必须一致
    priority 90				# 低于主节点
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111    	# 主备密码一致
    }
    virtual_ipaddress {
        192.168.148.161/32 dev ens32  # VIP绑定
    }
    # 非抢占模式(防抖动)
    nopreempt
    # 单播通信(避免VRRP广播风暴)
    unicast_src_ip 192.168.148.131   # 本机IP
    unicast_peer {
        192.168.148.130              # 对端IP
    }
}

virtual_server 192.168.148.161 80 {
    delay_loop 6
    lb_algo wrr           # 加权轮询
    lb_kind DR            # DR模式
    persistence_timeout 30  # 会话保持
    protocol TCP

    # 真实服务器1(HTTP健康检查)
    real_server 192.168.148.132 80 {
        weight 1
        HTTP_GET {
            url {
                path /health_check
                status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }
    # 真实服务器2(同上)
    real_server 192.168.148.133 80 {
        weight 1
        HTTP_GET {
            url {
                path /health_check
                status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 2
        }
    }
}
EOF

启动服务

bash
systemctl enable --now keepalived
# 查看LVS规则
ipvsadm -Ln

负载均衡配置

配置VIP

bash
ip addr add 192.168.148.161/32 dev lo
# 持久化(重启后生效)
echo 'ip addr add 192.168.148.161/32 dev lo' >> /etc/rc.local
chmod +x /etc/rc.d/rc.local

内核优化

bash
# ARP抑制(关键!)
cat >> /etc/sysctl.conf << EOF
net.ipv4.ip_forward = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
EOF
sysctl -p

作用:避免Real Server响应VIP的ARP请求导致IP冲突

配置Nginx负载均衡和健康检查

bash
# health.conf
cat > /etc/nginx/conf.d/www.conf << "EOF"
upstream tomcat_servers {
	ip_hash;
	server 192.168.148.134:8080 weight=1;
	server 192.168.148.134:8080 weight=1;
}

server {
    listen 80;
    location / {
        proxy_pass http://tomcat_servers;
	    index index.jsp;
	    proxy_set_header HOST $host;
	    proxy_set_header X-Real-IP $remote_addr;
	    proxy_set_header Client-IP $remote_addr;
	    proxy_set_header X-For $proxy_add_x_forwarded_for;
    }

    location /health_check {
        allow 192.168.148.0/24;  # 仅允许LVS网段访问
        deny all;
        return 200 "OK";
    }
}
EOF
nginx -s reload

后端Tomcat部署

安装JDK

bash
wget https://download.java.net/java/GA/jdk22.0.1/c7ec1332f7bb44aeba2eb341ae18aca4/8/GPL/openjdk-22.0.1_linux-x64_bin.tar.gz
tar xvf openjdk-22.0.1_linux-x64_bin.tar.gz -C /usr/local/
# 编辑环境变量配置文件
cat >> /etc/profile << "EOF"
export JAVA_HOME=/usr/local/jdk-22.0.1
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:$CLASSPATH
export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin
export PATH=$PATH:${JAVA_PATH}
EOF

source /etc/profile
# 检测
java -version

安装Tomcat

bash
# Tomcat下载:
https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.108/bin/apache-tomcat-9.0.108.tar.gz

# 解压
tar xf apache-tomcat-9.0.108.tar.gz -C /usr/local/
mv /usr/local/apache-tomcat-9.0.108 /usr/local/tomcat
# 可选的操作
echo 'export TOMCAT_HOME=/usr/local/tomcat' >>/etc/profile
source /etc/profile

# 启动程序
/usr/local/tomcat/bin/startup.sh
# 关闭程序
/usr/local/tomcat/bin/shutdown.sh

创建测试页面

bash
hostname -I > /usr/local/tomcat/webapps/ROOT/index.jsp

健康检查与故障切换验证

模拟节点故障

bash
# 在132上停止Nginx
nginx -s stop

主备切换测试

bash
# 停止主节点Keepalived
systemctl stop keepalived

验证

备节点应接管VIP(ip a show ens32),且LVS规则自动同步