news 2026/11/2 15:26:39

手搓 LVS-DR 负载均衡

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手搓 LVS-DR 负载均衡

手搓 LVS-DR 负载均衡:从原理到 6 节点双机轮询(附 ARP 抑制详解)

前段时间从零搭了一套 6 节点高可用集群:2 台 LVS 调度器 + 2 台 Nginx + 2 台 BIND DNS,用 Keepalived 做双活互备。
本篇是这个系列的第一篇:不用任何自动化工具,纯手工把 LVS-DR 配起来——因为只有手工做过一遍,才知道 Keepalived 到底替你做了什么。
全程 Rocky Linux 9,所有 IP 都是真实实验环境。

一、先看最终效果

在任意客户端上连续访问 VIP:

$curlhttp://192.168.88.200<h1>Web Node: web1(192.168.88.21)</h1>$curlhttp://192.168.88.200<h1>Web Node: web2(192.168.88.22)</h1>$curlhttp://192.168.88.200<h1>Web Node: web1(192.168.88.21)</h1>

两次请求落在两台不同的后端机器上——这就是负载均衡成立的铁证。
但更值得讲的是:为什么这个"改一下 MAC 地址"的转发模式,能成为生产机房扛大流量的标配?

二、集群拓扑

客户端 │ ┌───────────────┴───────────────┐ │ ①www.yhy.com? ②HTTP请求 │ ▼ │ DNS VIP 192.168.88.50 Web VIP 192.168.88.200 │ │ ┌──────┴──────┐ VRRP心跳 ┌────────┴──────┐ │ lvs2 (.12) │◀───────────▶│ lvs1 (.11) │ │ DNS主/WEB备 │ │ WEB主/DNS备 │ └──────┬──────┘ └──────┬────────┘ │ DR转发 │ DR转发(仅改MAC) ▼ ▼ dns1(.31) ⇄ dns2(.32) web1(.21) web2(.22) BIND主从同步 Nginx Nginx
主机IP角色
lvs1 / lvs2.11 / .12LVS 调度器(Keepalived 双活,本篇先只看 lvs1)
web1 / web2.21 / .22Nginx 后端
dns1 / dns2.31 / .32BIND 主从
Web VIP.200对外提供 Web 服务的虚拟 IP
DNS VIP.50对外提供 DNS 服务的虚拟 IP

后端首页写入自己的节点名,是整个实验最重要的"小动作":负载均衡的难点从来不是配通,而是证明请求真的被分发了。

三、LVS 三种模式,为什么选 DR

模式数据路径特点
NAT请求、响应都过调度器(双向改 IP)简单,但调度器是带宽瓶颈
DR只有请求过调度器(仅改 MAC),响应直连客户端性能之王,要求同网段
TUNIP 隧道封装跨网段,配置复杂

DR 高性能的秘密:HTTP 场景下请求是小流量、响应(网页/图片)是大流量。DR 让调度器只处理进门的小包,出门的大包由后端直接发往客户端——调度器压力极小。

DR 模式一次请求的完整旅程

客户端 (.1) │ ① 发包:目标IP=192.168.88.200,目标MAC=lvs1的MAC(ARP解析来的) ▼ lvs1:IPVS 命中 VIP:80 → 按 rr 算法选中 web1 │ ② 只改帧的【目标MAC】→ web1的MAC(源/目标IP都不动!) ▼ web1:lo:0 上也挂着 .200 │ ③ 目标IP是我 lo 上的地址 → 收下,交给 Nginx │ ④ 响应:源IP=.200,从 ens160 直接发回客户端 ★完全不经过 lvs1★ ▼ 客户端收到响应(全程以为在和 .200 说话)

四、灵魂三问:DR 模式的三个"必须"

Q1:为什么后端必须绑 VIP?
包的目标 IP 是 .200,web1 如果不认识这个 IP,内核直接丢包。所以 RS 必须把 VIP 配在自己身上——绑在lo 回环口。

Q2:为什么是 /32 掩码?
如果给 lo 配 .200/24,内核会认为整个 88 网段都在 lo 上,路由直接乱套。/32 表示"这就是一个孤立地址,只用于收包,不参与路由"。

Q3:为什么必须压 ARP?(DR 模式的灵魂)
现在网段里有 3 台机器都有 .200(lvs1 的 ens160、web1/web2 的 lo)。客户端 ARP 广播"谁是 .200?"——三台都会抢答,流量可能直连后端绕过调度器,负载均衡直接失效。

解法:让后端"闭嘴":

# web1 / web2 上执行cat>/etc/sysctl.d/99-arp.conf<<'EOF' net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.default.arp_ignore = 1 net.ipv4.conf.default.arp_announce = 2 EOFsysctl--system
  • arp_ignore=1:收到 ARP 请求时,只有"目标 IP 恰好配在收到请求的那块网卡上"才应答。ARP 从 ens160 进来,VIP 在 lo 上 → 不应答 ✅
  • arp_announce=2:对外发 ARP 时只用本网卡自己的 IP 做源地址,不拿 lo 上的 VIP 说事

结果:全网只有调度器应答 VIP 的 ARP → 流量必然先进调度器 → IPVS 才有分发权。

五、动手:三步配出双机轮询

第 1 步:后端(web1、web2 执行相同内容)

# VIP 绑到 lo,掩码必须 /32ipaddradd192.168.88.200/32 dev lo# ARP 抑制(上面已写 sysctl 文件的这里会自动生效)sysctlnet.ipv4.conf.all.arp_ignore# 应输出 = 1

第 2 步:调度器(lvs1)

# VIP 挂到真实网卡ipaddradd192.168.88.200/32 dev ens160# 安装 IPVS 管理工具dnf-yinstallipvsadm# 建虚拟服务:-t TCP服务,-s rr 轮询算法ipvsadm-A-t192.168.88.200:80-srr# 挂两台后端:-r 真实服务器,-g 表示 DR 模式ipvsadm-a-t192.168.88.200:80-r192.168.88.21:80-gipvsadm-a-t192.168.88.200:80-r192.168.88.22:80-g# 查看规则表ipvsadm-Ln

ipvsadm -Ln的关键输出:

TCP 192.168.88.200:80 rr -> 192.168.88.21:80 Route 1 0 0 -> 192.168.88.22:80 Route 1 0 0

Route即 DR 转发(直接路由)。

第 3 步:验证

foriin1234;docurl-shttp://192.168.88.200;done# web1 → web2 → web1 → web2 交替出现

再在 lvs1 上看分发计数,两台的 Conns 都在涨,说明真的在分:

ipvsadm-Ln--stats

加餐 1:会话保持(生产常用)

# -p 60:同一客户端 60 秒内粘在同一台后端ipvsadm-E-t192.168.88.200:80-srr-p60

加餐 2:眼见为实——响应真的不过调度器

lvs1 上抓包,然后客户端访问 VIP:

tcpdump-nn-iens160host客户端IP and port80

你会看到只有请求方向的包,没有响应包——响应从 web1/web2 直接连回客户端了。这就是 DR 的性能来源。

六、两个我亲手踩过的坑

坑 1:在持有 VIP 的机器上 curl VIP,会无限挂起

配完后我在 lvs1 上验证curl http://192.168.88.200,一直卡死。原因很反直觉:

  • lvs1 自己持有 .200 → 本机 curl 时源 IP 被内核选成 .200
  • 请求被 IPVS 转发给 web1,web1 回包给"客户端"——客户端 IP 是 .200
  • web1 一看:.200 是我自己 lo 上的地址!→ 回包走 loopback,永远出不了网卡
  • SYN-ACK 消失,curl 挂死

结论:DR 模式下,调度器和后端都不能当自己 VIP 的客户端。验证请用干净的第三方机器。(后端上 curl VIP 也是同理——会被本机 Nginx 劫持,永远只返回自己。)

坑 2:手工配置重启即失

ip addr add和ipvsadm -A都是内存态,重启全没。生产上的做法是用 Keepalived 把它们变成配置文件,还能附赠健康检查和 VIP 漂移——这正是系列第二篇的内容。

七、本篇命令速查

ipvsadm-A-tVIP:80-srr# 添加虚拟服务(rr 轮询)ipvsadm-a-tVIP:80-rRS:80-g# 挂后端(-g = DR 模式)ipvsadm-E-tVIP:80-srr-p60# 改为带会话保持ipvsadm-Ln/-Ln--stats# 规则表 / 分发计数ipvsadm-C# 清空所有规则ipaddraddVIP/32 dev lo# RS 侧绑 VIPsysctlnet.ipv4.conf.all.arp_ignore# 验证 ARP 抑制生效

系列预告

  • 第二篇:《Keepalived 双活互备实战:两组 VRRP、健康检查与故障切换》——手工命令如何变成配置文件、TCP_CHECK 自动摘除故障节点、两组 VRRP 实现双活、priority-0 通告与 GARP 的切换细节
  • 第三篇:《一次 DNS 全链路排障:健康检查全绿但 VIP 不通》——listen-on 盲区,一个健康检查永远测不出的问题

如果这篇对你有帮助,欢迎点赞收藏;实验环境为 VMware + Rocky Linux 9,6 台 1C1G 虚拟机即可完整复现。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 15:25:16

小Why的循环置换【牛客tracker 每日一题】

小Why的循环置换 时间限制&#xff1a;1 秒 空间限制&#xff1a;256M 网页链接 牛客tracker 牛客tracker & 每日一题&#xff0c;完成每日打卡&#xff0c;即可获得牛币。获得相应数量的牛币&#xff0c;能在【牛币兑换中心】&#xff0c;换取相应奖品&#xff01;助力每…

作者头像 李华
网站建设 2026/11/2 15:03:24

Dolphin-Mistral 24B威尼斯版:掌控你的无审查AI

Dolphin-Mistral 24B威尼斯版&#xff1a;掌控你的无审查AI 导语&#xff1a;Dolphin-Mistral 24B威尼斯版正式发布&#xff0c;这款由dphn.ai与Venice.ai联合打造的大语言模型以"无审查"和"用户控制权"为核心卖点&#xff0c;挑战现有AI服务模式&#xff…

作者头像 李华
网站建设 2026/11/2 14:55:48

C++仿C#实现事件处理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/2 14:51:52

自研轻量级服务监控雷达:主动探活、负载感知与告警实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华