首页 / 资讯中心 / 文章详情

LVS负载均衡核心技术与高可用部署实战:三大模式、调度算法与排障指南

LVS负载均衡核心技术与高可用部署实战:三大模式、调度算法与排障指南 ★ FEATURED ARTICLE
前几年接手过一批流量高峰期的电商活动高峰期每秒几万并发请求打过来单机应用根本扛不住。当时用的就是LVS这套方案几台普通服务器叠在一起稳定扛过了所有大促。这么多年下来我始终觉得LVS是最被低估的负载均衡方案之一——很多人一提起负载均衡就是Nginx、网关却忽略了这个Linux内核自带的四层分发器。这篇文章我不讲教科书理论直接按我实际部署和排障的经验把LVS的核心技术、三种工作模式、调度算法和常见坑一次讲透。如果你正在搭建高并发服务、打算入手负载均衡或者只是好奇一台机器怎么把流量均匀分给后端集群这篇文章都适合你。哪怕你只有几台低配服务器LVS也能给你跑出接近硬件负载均衡的效果。1. 从“服务排队”说起负载均衡到底在解决什么问题先聊点最朴素的。你去银行办事只有一个柜台排队的人越来越多后面的人只能干等。解决办法很简单多开几个柜台然后找个大堂经理把客户分到不同窗口。负载均衡干的就是大堂经理这件事LVS就是那个站在集群入口、把用户请求按策略分发给后端服务器的核心角色。1.1 单机瓶颈与负载均衡的江湖门派单台服务器能承载的并发连接数、吞吐量、CPU处理能力都是有上限的。当业务量上去了要么把单机性能堆到顶——买更贵的硬件这叫垂直扩展要么加机器、把流量分散到多台机器上这叫水平扩展。负载均衡就是为了让水平扩展能落地而生的组件。目前市面上常见的负载均衡产品大概分两类软件负载均衡Nginx、HAProxy、LVS硬件负载均衡F5、A10贵而且不灵活软件方案里Nginx和HAProxy做的是七层应用层分发能读懂HTTP协议、做路径转发、带超时重试、缓存策略。而LVS做的是四层传输层分发工作在Linux内核态它根本不关心你传输的是HTTP还是MySQL协议直接基于IP地址和端口做转发。这带来一个很关键的结果LVS的处理性能极高吞吐能力强于七层方案延迟也更低。但代价是它不会帮你解析URL、不会帮你做会话保持里的Cookie判断。LVS和Nginx不是替代关系更多时候是上下级关系外层LVS分流量内层Nginx反代到应用。1.2 四层与七层LVS为什么站在更底层的位置打个比方七层负载均衡像快递分拣员他得看包裹面单上的地址、是否易碎、要不要冷链然后决定送哪个站点四层负载均衡像高速路口的分流牌不看车里装的货只看这辆车要去哪个城市直接指向对应的高速车道。因为LVS不出内核它把数据包转发、连接跟踪、调度决策这些原本要靠用户态程序处理的事全放到内核模块ip_vs里完成。转发路径短、上下文切换少所以单台LVS处理几十万并发连接是常见的事有些优化得好的生产环境甚至能跑到百万级并发。这也是为什么我总建议如果你的业务只是HTTP API且对性能有要求不要一上来就纠结Nginx够不够用先用LVS把入口流量分好后面再用七层做精细路由两层配合才最合理。1.3 LVS的三层架构调度器、VIP 与后端真实服务器LVS的架构可以拆成三块LBDirector负载调度器运行ip_vs内核模块对外暴露一个虚拟IPVIPVIP客户端访问的入口IP也就是“大堂经理”站的位置RSReal Server后端真正处理业务请求的服务器它们使用真实IPRIP整个流程是客户端请求到达VIP - 调度器根据算法选一台RS - 把数据包转发过去 - RS处理完把响应返回给客户端。这里有个容易混淆的点LVS不修改业务数据它只负责“带路”。不同工作模式下它带路的方式完全不一样这也是LVS进阶学习中最容易卡住的环节。下面重点拆。2. LVS三大工作模式深度拆解LVS支持三种工作模式DR模式Direct Routing直接路由、NAT模式Network Address Translation网络地址转换、Tunnel模式IP隧道。它们在数据包转发路径上有本质区别决定了性能和适用场景。我直接按生产环境的推荐顺序来说。2.1 DR模式生产环境的首选DR模式是我在绝大多数场景下的首选。核心思路是调度器只修改数据链路层的MAC地址不改IP包内容。具体流程客户端的请求包到达LVS调度器目标IP是VIP调度器根据调度算法选出一台RS调度器把数据帧的目标MAC地址改成RS的MAC地址重新封装后扔进交换机RS收到这个包后会发现目标IP是VIP恰好本机lo网卡上配置了这个VIP于是收下处理RS处理完直接把响应包源IP写成VIP绕过调度器直接回给客户端这个“响应不走调度器”的设计是关键。我见过不少人第一次看到DR模式的拓扑图就懵了为什么调度器只进不出原因就在这里——请求量一般远小于响应量尤其是HTTP场景响应体通常比请求体大得多让响应直接从RS走调度器的压力就只剩处理入口流量那一小半了。DR模式的优点性能最好因为进出流量分离调度器吞吐压力小配置简单不需要额外的地址转换RS服务器可以使用任意操作系统只要能支持在lo上配置VIP缺点也很明显调度器和RS必须在同一个二层网络里否则改MAC地址的方式就不生效。跨机房跨网段没法用DR。另外RS的lo接口上不能对外响应VIP的ARP请求否则整个网络会乱套。2.2 NAT模式网关式转发如果你刚接触LVSNAT模式可能是最好理解的一个调度器改IP地址像网关一样把请求转发给后端。流程客户端请求VIP调度器把目标IP从VIP改成RS的RIP转发给RSRS处理完把响应回给调度器因为RS默认网关是调度器调度器再把响应源IP从RIP改回VIP回给客户端全程都是地址转换所以RS根本不需要配置VIP。这个模式对网络环境的要求最宽松调度器和后端服务器可以跨网段RS只需要把默认网关指向调度器即可。但代价也实在所有流量无论请求还是响应都要经过调度器进出调度器很容易成为性能瓶颈。如果你的业务响应体很大比如图片、文件下载接口NAT模式下调度器的网卡带宽很快就会被打满。NAT模式适合对小规模集群做隔离测试或者跨网段环境下不得不做转发的场景。生产环境流量一大我基本不推荐。2.3 Tunnel模式与模式选型对比Tunnel模式IPIP隧道在调度器和RS之间再封一层IP包把原始请求包完整地包在新包里传给RSRS解包后处理同时响应也直接回给客户端像DR模式一样绕过调度器。它能解决DR模式的二层限制允许调度器和RS跨网段部署。代价是额外封包、解包会带来一些性能损耗而且系统需要加载ipip模块内核配置要跟得上。三种模式的横向对比对比项DR模式NAT模式Tunnel模式响应是否经过调度器否是否后端是否需要配置VIP是lo上配置否是跨网段支持否是是性能最高最低中等配置复杂度简单简单较复杂适用场景同机房大流量集群跨网段小规模跨机房大流量我的经验是同机房同网段用DR不同机房再考虑TunnelNAT能不用就不用。如果你刚上手建议直接拿DR模式练踩一遍ARP的坑之后你对整个数据链路就通了。3. 核心调度算法与“等开销”设计思想算法是LVS的灵魂。调度的本质回答一个问题集群里有这么多台RS这一秒来了一个新连接该给谁基于“等开销负载均衡”这个思路好的调度算法要尽量让每个后端节点处理的“总代价”趋于一致——这里的代价不只是连接数还包含权重、活跃连接数、负载动态变化等因素。LVS的内核里就集成了十多种算法下面我挑生产中最常用的几种把原理和选型逻辑一起讲。3.1 基础轮询算法RRRound Robin轮询按顺序把新请求轮流分给每一台RS。1-2-3-1-2-3谁都不吃亏。实现最简单开销也最小。但它完全不看后端当前的状态如果两台机器配置差距大、或者某台机器已经快被压垮了RR照样会把流量分过去。WRRWeighted RR加权轮询在RR基础上给每台RS设置权重性能好的机器权重设置大一些分到的连接自然就多。比如A机器权重3、B机器权重1每4个新连接里大约有3个给A、1个给B。加权轮询已经能解决大部分“机器性能不齐”的问题但它依然是静态的。如果某台机器因为磁盘IO抖动变慢了权重并不会自动降下来所以RR和WRR适合后端服务状态相对平稳的场景。3.2 连接数与权重算法LCLeast Connections最少连接这个算法看的是当前活跃连接数新连接永远分配给当前活跃连接数最少的RS。思路很直接谁手上活儿少新任务就给谁。活跃连接数怎么定义LVS内核里用公式表示active * 256 inactive。active指的是当前正在传输数据的连接数inactive指的是已经建立但当前空闲的连接数。乘256是为了让活跃连接在比较中占主导权重避免“一堆空闲连接但实际没在干什么”的服务器干扰判断。WLCWeighted LC加权最少连接这是LVS默认的调度算法在LC的基础上引入权重计算方式成了(active * 256 inactive) / weight。权重越大的机器算出来的值越小被选中概率越高。它是标准调度算法里的常青树能兼顾动态连接数和静态权重适合大多数TCP长连接和HTTP短连接混合的场景。还有一种SEDShortest Expected Delay最短期望延迟它的计算方式是(active 1) * 256 / weight它不只看当前连接数还会预估“如果这个新连接也给你你的总负担会变成多少”更偏前瞻性。在RS能力差异明显的环境下SED的表现往往优于WLC。3.3 目标地址散列与等开销思想除了上面基于连接数的算法还有两类散列算法DHDestination Hashing目标地址散列和SHSource Hashing源地址散列。DH根据目标IP地址做哈希同一个目标IP的请求固定发到同一台RSSH根据源IP做哈希同一个客户端固定映射到同一台RS。这类算法的核心价值是实现会话保持——不用依赖后端应用做Session复制同一个用户始终落在同一台机器上。但代价是负载均衡能力变弱因为某个IP如果流量大它对应的那台RS就会被压得比较重。LVS还有几个更高阶的“等开销”算法LBLC基于局部性的最少连接目标是缓存集群这类场景。它优先把请求调度给“最近被访问过的目标IP”所在的那台RS如果那台RS还没满就继续给它满了才找其他负载低的RS。LBLCR带复制的LBLC在LBLC基础上允许一个目标IP的请求被多台RS分担适合热点缓存场景。这两种算法都体现了“等开销”的思想在维持目标请求局部性的前提下尽量均衡每台RS的处理成本。3.4 算法选型建议不同场景选算法我一般这样判断后端机器配置完全一致、业务无状态RR简单高效后端机器配置有差异WRR或WLC长连接场景数据库、WebSocket、TCP推送WLC或LC需要会话保持且后端不做Session共享SH缓存集群、热点数据明显LBLC或LBLCR拿不准WLC它是LVS的默认选项整体均衡效果最稳记住一点算法不是越复杂越好。调度器执行算法本身也有开销如果你只有三五台RS、流量也普通RR完全够用别为了炫技上LBLCR反而增加排查难度。4. 生产环境实操keepalived LVS部署理论讲了这么多最终还是要落到配置上。这里我给出一个我常用的生产级部署方案keepalived LVS DR模式。keepalived负责VIP漂移和RS健康检查LVS负责流量分发。4.1 环境规划假设场景是两台LVS调度器做主备两台RS跑Nginx提供HTTP服务整个集群对外暴露一个VIP。角色IP地址说明LVS-Master192.168.1.10主调度器LVS-Backup192.168.1.11备调度器VIP192.168.1.100对外虚拟IPRS1192.168.1.20Nginx后端1RS2192.168.1.30Nginx后端2所有机器在同一网段满足DR模式的二层网络要求。4.2 配置实现先在后端RS上配置VIP和ARP抑制。每台RS在lo网卡上绑定VIP同时设置内核参数禁止对外响应VIP的ARP请求否则交换机流量会直接绕过调度器跑到RS上彻底乱套。# 在每台RS上执行 ifconfig lo:0 192.168.1.100 netmask 255.255.255.255 up echo 1 /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 /proc/sys/net/ipv4/conf/all/arp_announce echo 1 /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 /proc/sys/net/ipv4/conf/lo/arp_announcearp_ignore1表示只回答目标IP是本网卡IP的ARP请求arp_announce2表示发送ARP通告时使用最优本地地址。这两个参数组合起来RS上的VIP就变成“只收包不回广播”的状态了。接下来配置keepalived。主备两台LVS调度器的配置几乎一样只有state和priority不同。下面以Master为例global_defs { router_id LVS_MASTER } 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 { 192.168.1.100/24 dev eth0 label eth0:0 } } virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo wlc lb_kind DR persistence_timeout 60 protocol TCP real_server 192.168.1.20 80 { weight 3 TCP_CHECK { connect_timeout 3 retry 3 delay_before_retry 3 } } real_server 192.168.1.30 80 { weight 1 TCP_CHECK { connect_timeout 3 retry 3 delay_before_retry 3 } } }配置里有几个参数值得细说lb_algo wlc调度算法选加权最少连接lb_kind DR模式选DRpersistence_timeout 60连接保持时间同一个源IP在60秒内的新请求会被尽量分到同一台RS对依赖Session的业务很友好TCP_CHECKkeepalived每3秒探测RS的80端口一次连续失败3次就把RS从调度列表中摘除恢复后再加回来Backup节点的配置只需要把state改成BACKUP、priority改成90其他完全一致。4.3 参数解析与验证方法配置完启动keepalived服务systemctl restart keepalived然后验证调度是否生效。最常用的工具是ipvsadm它是LVS的用户态管理工具ipvsadm -L -n --stats输出会列出每台RS当前的连接数、流量、活跃/非活跃连接数等指标一眼能看出调度是否均衡。另外还需要验证VIP是否漂移成功ip addr show eth0Master上应该能看到eth0:0绑定了192.168.1.100Backup上没有。手动停掉Master的keepalived服务等几秒VIP应该自动漂移到Backup上这就是主备高可用生效了。注意DR模式下RS的lo:0配置是临时的一旦重启就没了。建议把VIP绑定和ARP参数写进开机启动脚本或systemd单元避免机器重启后集群失灵。5. 常见故障排查与生产避坑指南LVS本身很稳定但涉及多台机器、多个网络环节故障总是免不了。这一节我把这几年遇到最多的坑和排查思路整理成清单希望能帮你少走弯路。5.1 现象速查表故障现象可能原因排查方向客户端无法访问VIPkeepalived没起来 / VIP没绑定ip addr show确认VIPps -ef能ping通VIP但业务不通后端RS端口挂了 / RS从集群摘除ipvsadm -L -n看RS状态是否为Active部分用户能访问部分不能persistence_timeout导致的会话绑定 / 某台RS故障检查TCP_CHECK是否误判观察RS负载流量不经过调度器直接打进RSARP抑制没配置好检查RS的arp_ignore和arp_announce访问时好时坏某台RS响应慢导致超时看RS负载、网络延迟检查keepalived日志后端日志里出现大量非VIP源IPNAT模式正常现象 / DR配置错误确认实际使用的模式其中最隐蔽、也最容易让人摸不着头脑的是ARP问题。5.2 ARP问题详解DR模式下所有RS的lo上都绑定了VIP。如果RS没有做ARP抑制它会对外广播“这个VIP在我这里”交换机会把发给VIP的流量直接送到RS调度器反而收不到流量了。此时你从客户端测试会发现服务能通但流量根本没走LVS直接打到某一台RS上了——负载均衡整个形同虚设而且行为变得完全不可控。这个问题的排查有个简单方法在客户端抓包看目标MAC地址的厂商前缀如果指向的是RS的网卡MAC而不是调度器的基本就是ARP抑制配置失效了。或者直接登录调度器看ipvsadm -L -n --stats里的连接数——如果一直为0但业务又正常那铁定流量没经过调度器。我再补一个很多人忽略的细节修改arp_ignore和arp_announce后建议把RS的网卡down掉再up一次或者重启网络服务确保内核参数重新加载生效只echo一次有时候不生效。5.3 健康检查与容灾技巧keepalived自带的TCP_CHECK能检测端口是否在监听但检测不到更深层的问题。比如后端应用进程还在、端口正常但线程池已经打满或者依赖的数据库连不上此时TCP_CHECK依然会判定RS健康。我常用的增强方案是加一层HTTP_GET检查用curl请求后端的一个专用健康检查接口接口返回2xx才判定为健康。配置如下real_server 192.168.1.20 80 { weight 3 HTTP_GET { url { path /healthcheck status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } }后端业务在/healthcheck接口里除了确认自身存活还要检查下游依赖数据库、Redis连接池是否正常。这样“假死”的RS就会及时被摘除避免把用户请求转发给一台实际已经无法完成业务的机器。另外建议在生产环境至少部署两台LVS做Keepalived主备并把keepalived的nopreempt关掉让主备切换后不会立刻抢占回主节点减少切换抖动。如果主节点挂了、备节点接管后主节点恢复时又抢回VIP期间会产生几秒的VIP归属切换对长连接不友好。设置nopreempt可以避免这类无谓的来回切换。5.4 与Nginx搭配使用的架构实践最后聊聊LVS怎么跟Nginx配合。我的基本经验是LVS管入口Nginx管路由。一个成熟的高并发架构分层大致是这样客户端 - LVS四层分发基于VIP天然扛高并发LVS - Nginx集群每台Nginx做反向代理、缓存、静态资源服务Nginx - 应用服务器Tomcat/Node/PHP按域名、URI路径分流转发这样做的原因很简单LVS虽然吞吐大但它不能根据URL做路径转发也不了解HTTP协议的语义Nginx能精细控制路由、头部修改、重试策略。两者各干各擅长的事互相弥补。具体到配置上我用的方案是LVS后端RS指向Nginx的80端口Nginx再通过upstream配置指向应用集群。此时Nginx的keepalive连接、超时重试、gzip压缩等能力都能发挥出来而LVS只需要管“把连接分给哪台Nginx”。如果你的业务全是HTTP API、且后端无状态甚至可以LVS直接指向应用服务器省掉Nginx一层减少链路延迟。这样的情况我实际也验证过效果很好前提是应用层做好了连接管理和优雅停机否则滚动发布时连接断开的问题会非常突出。最后说点实在的做了这么多年LVS踩过最大的坑不是内核参数配错而是“启用LVS后想当然地认为高可用已经万事大吉”。Keepalived只能做简单探活业务侧的深度健康检查还得靠应用自己暴露接口这一点在架构设计时就要想清楚。另外LVS有一个不太被注意的优势是它不绑定任何特定云厂商。无论你在物理机房、私有云还是公有云的VPC里只要网络层满足要求都能搭起来跑。比起云平台自带的负载均衡产品它多了一份自主可控的踏实感。初次尝试的人可以直接在一台虚拟机里装两个RS和一个Director用ipvsadm手动添加虚拟服务和真实服务器先把RR和WLC的调度效果跑通然后再引入keepalived做高可用——链路熟悉之后再看生产环境心里就有底了。
阅读完成 · 觉得有帮助?
咨询建站