入站请求负载均衡解决方案 LVS 的介绍

概述

LVS 简介

  • LVS(Linux Virtual Server)即 Linux 虚拟服务器,是一个虚拟的服务器集群系统。

    通过 LVS 的负载均衡技术和 LINUX 操作系统可以实现一个高性能、高可用的 LINUX 服务器集群,它具有良好的可靠性、可扩展性和可操作性。它可以将来自客户端的请求分发到多台服务器上,实现多台服务器的负载均衡,提高整个系统的性能和可用性。LVS 架构从逻辑上可分为调度层、Server集群层和共享存储层。

    该项目是1998年5月由章文嵩博士主导的开源负载均衡项目,是国内最早出现的自由软件项目之一。目前 LVS 已经被集成到 Linux 内核模块中。

    在 Linux2.4 内核以前,使用 LVS 时必须要重新编译内核以支持 LVS 功能模块,但是从 Linux2.4 内核以后,已经完全内置了 LVS 的各个功能模块,无需给内核打任何补丁,可以直接使用 LVS 提供的各种功能。

  • LVS 的组成

    LVS 由两部分程序组成,即 IPVS 和 IPVSADM

    • IPVS:IP Virtual Server 的缩写,其代码工作在系统内核空间,也是实现调度的代码段。
    • IPVSADM:工作在用户空间,负责为 IPVS 内核框架编写规则,定义谁是前端集群服务器,谁是后端真实服务器(Real Server)
  • LVS 的体系结构

    使用 LVS 架设的服务器集群系统有三个部分组成:

    • 最前端的负载均衡层(调度层),用 Load Balancer 表示;
    • 中间的服务器集群层(Server集群层),用 Server Array 表示;
    • 最底端的数据共享存储层,用 Shared Storage 表示;

LVS 与 Nginx 的功能对比

简单来说,当并发连接数超过了 Nginx 的负载上限时,就需要使用 LVS 了。就目前实际环境来讲,日均页面访问量(pv)在1000万~2000 万或并发量在 5 万以下时都可以使用 Nginx。流量超过这个标准或一些大型的门户网站、电商平台也会使用 LVS,这是因为它们的流量或并发量随时可能存在高峰时段,或者说可能在某个点会超过以往所有的流量峰值。

LVS 与 Nginx 的功能对比如下:

  • LVS 比 Nginx 具有更强的抗负载能力,性能比较高(能达到 F5 性能的 60% 左右,可以支持几十万的并发量),而且 LVS 工作在网络 4 层仅做请求分发之用,没有流量,所以在效率上基本不需要太过考虑,且对内存和 CPU 资源消耗比较低,只考验网卡或 linux2.4 内核的承载能力。

    Nginx 则工作在网络的应用层,可以针对 HTTP 应用实施一些分流策略。

  • LVS 安装配置比较简单,对网络的依赖较大,但稳定性较高。Nginx 安装配置相对复杂,对网络的依赖较小。

  • LVS 不支持正则匹配处理,不能做动静态分离,而 Nginx 具有这方面的功能。

  • LVS 适用的协议范围较广。Nginx 仅能支持 HTTP、HTTPS、Email 协议,因此适用范围就大大缩小了。

  • 基本上能支持所有应用,因为 lvs 工作在 4 层,所以它可以对几乎所有应用做负载均衡,包括 http、数据库、聊天室等等。

注:LVS 需要手工动态增加命令,所以一般通过 Keepalived 来实现自动配合。

常见负载均衡对比 优势 缺点
F5(硬件) 性能好,技术支持 价格昂贵购买 2 台 1 对
Ivs 工作四层效率极其高(几十万),对数据做的转发负载均衡 在低数据量的效率不高,高效率需要在大数据量才体现(运维成本较高)
nginx 使用简单,支持 4 层(1.9 版本后支持)和 7 层反向代理缓存流量镜像 处理数据代理模式替用户去查找,找到后发送给用户并发较大(无法支持 5W 以上的并发量)
haproxy 相对复杂,支持 4 层和 7 层反向代理 处理数据代理模式替用户去查找,找到后发送给用户并发较大(无法支持 10W 以上的并发量)

LVS 负载均衡机制

  • LVS 是四层负载均衡,也就是说建立在 OSI 模型的第四层------传输层之上,传输层上有 TCP/UDP,LVS 支持 TCP/UDP 的负载均衡。因为 LVS 是四层负载均衡,因此它相对于其它高层负载均衡的解决办法,比如 DNS 域名轮流解析、应用层负载的调度、客户端的调度等,它的效率是非常高的。
  • LVS 的转发主要通过修改 IP 地址(NAT 模式,分为源地址修改 SNAT 和目标地址修改 DNAT)、修改目标 MAC(DR 模式)来实现。

LVS 调度算法

  • 调度算法决定了如何在集群节点之间分布工作负荷。当负载调度器收到来自客户端的入站请求时,调度器必须决定哪个集群节点应该处理请求。
  • 调度器用的调度方法分为两类 :静态调度和动态调度
  • 一般实际生产环境常用的调度算法有 rr、wrr、lc、wlc,常用于 HTTP、MySQL、Mail 等服务中。

静态调度

特点:只根据算法本身去调度,不考虑服务器本身

  • rr(Round Robin):轮询

    最简单的调度算法。轮询调度按照依次交替循环的方式将用户请求转发到后端不同的服务器上,调度器会将所有的请求平均分配给后端的每个主机服务器。这种算法比较适用于集群中各个节点的处理能力均衡的情况。

  • wrr(weight Round Robin):加权轮询

    加权轮询算法是在轮询算法的基础之上增加了一个权重的概念,就是给后端服务器配置权重,权重越高,调度器分配给它的请求就越多,权重的取值范围为0~100。

    假设 A 的服务器性能好,就给 A 的权重设置的高一点,设为 2,而 B 主机是 1。这样就实现 A 二个,B 一个,A 二个,B 一个的循环发,这样照顾到了服务器性能。

  • sh(source hashing):源地址散列/哈希

    主要是实现将此前的 session(会话)绑定。将此前客户的源地址作为散列键,从静态的散列表中找出对应的服务器,只要目标服务器是没有超负荷的就将请求发送过去。

    就是说某客户访问过 A 主机,现在这个客户又来了,所以客户请求会被发送到服务过他的 A 主机。

  • dh(Destination Hashing):目标地址散列/哈希

    以目的地址为关键字查找一个静态 hash 表来获得需要的 RS。以目标地址为标准挑选。

    功能是和 sh 近似的,但应用场景不同;假设 1 号客户访问了 web 集群的一个动态页面,调度器将请求转发个A 服务器,A 服务器的 PHP 将这个动态请求运行了一遍,生成了缓存并回应 1 号客户。这下 2 号客户也访问了这个动态页面,调度器应该将请求发给 A。毕竟 A 已经跑过这段程序了,有缓存。

动态调度

特点:除了算法本身,还要考虑服务器状态

  • lc(Least-Connection):最少连接

    调度器会根据后端服务器的连接数来决定将请求分发给哪一个服务器,同一时间内优先分发请求给连接数少的服务器。

    简单算法:active * 256 + inactive(谁小发给谁)

    注:

    • 活动链接(active):客户与服务器建立连接并且有数据传送
    • 非活动链接(inactive):只是建立连接,没有数据传送,没有断开连接
  • wlc(Weighted Least-Connection):加权最少连接(LVS 的理想算法)

    加权最少连接算法一般用于在集群系统中各服务器的性能相差较大的场景中,默认也是采用这种算法。

    调度器利用此算法来优化负载均衡各方面的性能,有较高权重值的服务器将承担较大的负载连接。调度器还可以自动获取后端服务器的真实负载情况,以便动态地调整其权重值。

    简单算法:( active * 256 + inactive ) / weight(谁小就发给谁)

  • sed(Shortest Expected Delay):最短期望延迟

    最短延迟调度算法是在加权最少连接(wlc )的基础上改进的,不再考虑非活动状态,把当前处于活动状态的数目 +1 来实现,数目最小的,接受下次请求,+1 的目的是考虑加权时非活动连接过多的的缺陷:当权限过大时,会倒置空闲服务器一直处于无连接状态。

    假设 A,B 的权重分别是 1、2 。而 A 的连接数为 1,B 的连接数为 2 。这样的话,用 wlc 算法得出的结果一样,而明显 B 的权重大,B 的能力较强。用 sed 算法的话,就可以避免 wlc 出现的问题。

    简单算法:(active + 1) * 256 / weight 即(活动的连接数+1)* 256 / 除以权重 (谁小发给谁)

  • nq (never queue):永不排队

    如果有一台后端服务器的连接数为 0,就将请求直接分配过去,不需要再进行SED运算,保证不会有一个主机很空闲。

    在SED基础上无论加几,第二次一定将请求分发给下一个主机。不考虑非活动连接时才用 nq,sed 要考虑活动状态连接。对于DNS 的 UDP,不需要考虑非活动连接,而 htpd 的处于保持状态的服务需要考虑非活动连接给服务器的压力。

  • LBLC(Locality-Based Least Connection):基于本地的最少连接

    这个算法主要用于 Cache 集群系统,因为 Cache 集群的中客户请求报文的目标 IP 地址的变化,将相同的目标 URL 地址请求调度到同一台服务器,来提高服务器的访问的局部性和 Cache 命中率。从而调整整个集群的系统处理能力。但是,如果 realserver 的负载处于一半负载,就用最少链接算法,将请求发送给活动链接少的主机。

  • LBLCR(Locality-Based Least Connections withReplication):带复制功能基于本地的的最少连接

    该算法首先是基于最少连接的,当一个新请求收到后,一定会将请求发给最少连接的那台主机的。但这样又破坏了 cache 命中率。但这个算法中,集群服务是 cache 共享的,假设 A 的 PHP 跑了一遍,得到缓存。但其他 realserver 可以去 A 那里拿缓存,这是种缓存复制机制。

LVS 三种工作模式的解析

LVS 相关术语释义

  • CIP(Client IP):客户端的 IP
  • VIP(Virtual IP):LVS 实例 IP,一般是暴露在公网中的地址;向外部直接面向用户请求,作为用户请求的目标的 IP 地址
  • DIP(Director IP):主要用于和内部主机通讯的 IP 地址
  • RIP(Real IP)后端服务器的真实 IP
  • DS (Director Server):指的是前端负载均衡器节点
  • RS(Real Server):后端真实的工作服务器

NAT 模式:网络地址转换

NAT(Network Address Translation)是一种外网和内网地址映射的技术。

NAT 模式是通过网络地址转换的方法来实现调度的:

  • 首先调度器(DS)接收到客户的请求数据包时(请求的目的 IP 为 VIP),根据调度算法决定将请求发送给哪个后端的真实服务器(RS)
  • 然后调度就把客户端发送的请求数据包的目标 IP 地址及端口改成后端真实服务器的 IP 地址(RIP),这样真实服务器(RS)就能够接收到客户的请求数据包了
  • 真实服务器响应完请求后,查看默认路由(NAT 模式下需要将 RS 的默认路由设置为 DS 服务器。)把响应后的数据包发送给 DS
  • DS 在接收到响应包后,把包的源地址改成虚拟地址(VIP)然后发送回给客户端。客户端无法感知到后端 RS 的存在。
  • 注意:在 NAT 模式中,Real Server 的网关必须指向 DS,否则报文无法送达客户端
  • 图中黄色数据包是从客户端到 LVS 集群的,绿色数据包是从 LVS 集群到客户端的,大概过程如下:

    1. 数据包 CIP -> VIP,如果直接将数据包塞给 RS(真实服务器),RS 会丢弃,因此 LVS 修改目标地址 VIP 为 RIP(D-NAT),此时数据包变成 CIP -> RIP 发给 RS
    2. RS 处理完成后发送数据包 RIP -> CIP,这个数据包直接塞给客户端,客户端是不会收的,因为客户端是发给 VIP 的,但是回来就变成 RIP 给客户端

    整个过程保证一个原则:怎么来的就怎么回去,按照 Socket 四元组 IP 反向发回去!比如就客户端和 LVS 而言,发来的是 CIP -> VIP,发回去就得是 VIP -> CIP,LVS 和 RS 之间也是同样的道理

  • 特点

    • 集群节点,必须在一个网络中
    • RIP 通常都是私有 IP,仅用于各个集群节点通信
    • 负载调度器必须位于客户端和真实服务器之间,充当网关,真实服务器必须将网关指向负载调度器(因为最终给 CIP 的数据包要扔回给LVS)
    • 支持端口映射,即用户请求的端口和真实服务器的端口可以不一致
    • 负载调度器操作系统必须是 Linux,RS 可以使用任意操作系统
    • 请求和响应报文都需要经过 Director Server,高负载场景中,LVS 易成为性能瓶颈
  • 缺陷

    • LVS 压力会比较大,因为请求和响应的报文都需经过 LVS 进行地址改写(一般来说流量是非对称/倾斜的,即请求报文小,响应报文大)

      因此网站访问量比较大的时候负载均衡调度器会成为整个集群的瓶颈,一般要求最多只能添加 10-20 台节点。

    • 不断得进行网络地址转换,消耗算力

DR 模式:直接路由

DR 负载均衡模式数据分发过程中不修改 IP 地址,只修改 mac 地址,由于实际处理请求的真实物理 IP 地址和数据请求目的 IP 地址一致,所以不需要通过负载均衡服务器进行地址转换,可将响应数据包直接返回给用户浏览器,避免负载均衡服务器网卡带宽成为瓶颈。因此,DR 模式具有较好的性能,也是目前大型网站使用最广泛的一种负载均衡手段。

请求的链路过程

  1. 客户端将请求发往前端的负载均衡器,请求报文源地址是 CIP,目标地址为 VIP
  2. 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将客户端请求报文的源 MAC 地址改为自己 DIP 的 MAC 地址,目标 MAC 改为了 RIP 的 MAC 地址,并将此包发送给 RS
  3. RS 发现请求报文中的目的 MAC 是自己,就会将次报文接收下来,处理完请求报文后,将响应报文通过 lo 接口送给 eth0 网卡直接发送给客户端
  • 黄色数据包流向是去向的,绿色是回向的;RS 有一个对内可见,对外隐藏的 VIP
    1. 数据包 CIP -> VIP 发送给 LVS
    2. LVS 通过修改 MAC 地址把数据包直接扔给 RS,由于 RS 也有 VIP,所以收下数据包
    3. RS 处理完成后,直接封数据包 VIP -> CIP,返回给客户端,不经过 LVS
  • 特征
    • 保证前端路由将目标地址为 VIP 报文统统发给 LVS,而不是 RS(因为 RS 的 VIP 是隐藏的)
    • RS 可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对 RIP 进行直接访问
    • RS 跟 LVS 必须在同一个物理网络中(因为 MAC 地址欺骗/ARP欺骗就只能发生在局域网中)
    • 所有的请求报文经由 LVS,但响应报文必须不能经过 LVS
    • 不支持地址转换,也不支持端口映射(因为这是链路层/2层的处理,不涉及到 IP)
    • RS 可以是大多数常见的操作系统
    • RS 的网关绝不允许指向 DIP(因为不允许它经过LVS)
    • RS 上的 lo 接口配置 VIP 的 IP 地址(对外隐藏,对内可见)
  • 缺陷:RS 和 LVS 必须在同一机房或局域网中,很显然,ARP 欺骗条件要求 LVS 和 DS 要在同一个物理局域网内

TUN 模式:隧道模式

IP 隧道技术(IP tunneling)亦称为 IP 封装技术(IP encapsulation),是将一个 IP 报文封装在另一个 IP 报文的技术,这可以使得目标为一个 IP 地址的数据报文能被封装和转发到另一个 IP 地址。

IP 隧道主要用于移动主机和虚拟私有网络(Virtual Private Network),在其中隧道都是静态建立的,隧道一端有一个 IP 地址,另一端也有唯一的 IP 地址。它的连接调度和管理与 VS/NAT 中的一样,只是它的报文转发方法不同。调度器根据各个服务器的负载情况,动态地选择一台服务器,将请求报文封装在另一个 IP 报文中,再将封装后的 IP 报文转发给选出的服务器;;服务器收到报文后,先将报文解封获得原来目标地址为 VIP 的报文,服务器发现 VIP 地址被配置在本地的 IP 隧道设备上,所以就处理这个请求,然后根据路由表将响应报文直接返回给客户。

请求的链路过程:

  1. 客户端将请求发往前端的负载均衡器,请求报文源地址是 CIP,目标地址为 VIP
  2. 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将在客户端请求报文的首部再封装一层 IP 报文,将源地址改为 DIP,目标地址改为 RIP,并将此包发送给 RS
  3. RS 收到请求报文后,会首先拆开第一层封装,然后发现里面还有一层 IP 首部的目标地址是自己 lo 接口上的 VIP,所以会处理次请求报文,并将响应报文通过 lo 接口送给 eth0 网卡直接发送给客户端
  • 隧道模式,最简单的理解就是数据包套数据包,一个数据包背上另一个数据包,到了目的地再放下来,整个流程如下:
    1. 数据包 CIP -> VIP发送给 LVS
    2. LVS 在源数据包外面套一层形成 [DIP -> RIP[CIP -> VIP]],通过 DIP -> RIP 将数据包发送给 RS(DIP 和 RIP 可以是不同的物理网络)
    3. RS 拆包接收到 CIP -> VIP 的请求处理完成之后直接封数据包 VIP -> CIP,返回给客户端,不经过 LVS
  • 特征
    • 不支持端口映射
    • RS 的系统必须支持隧道功能
    • RS 的网关不会也不能指向 DIP
    • 所有的请求报文经由 LVS,但响应报文必须不能进过 LVS
    • 集群节点不必位于同一个物理网络,但 RIP、VIP、DIP 全是公网 IP

总结

企业中最常用的是 DR 实现方式,而 NAT 配置上比较简单和方便,TUN 模式则是综合了 DR 和 NAT 的优点

相关推荐
鸠摩智首席音效师5 分钟前
.NET Core 应用程序如何在 Linux 中创建 Systemd 服务 ?
linux·运维·.netcore
叫我龙翔1 小时前
【计网】实现reactor反应堆模型 --- 多线程方案优化 ,OTOL方案
linux·运维·网络
mit6.8241 小时前
[Docker#9] 存储卷 | Volume、Bind、Tmpfs | -v/mount | MySQL 灾难恢复 | 问题
linux·运维·docker·容器·架构
Z1eaf_complete1 小时前
Docker的基础使用
运维·docker·容器·云计算
群联云防护小杜2 小时前
服务器被挂马怎么办?——解决服务器被挂马的方法和步骤
运维·服务器·网络协议·tcp/ip·安全·ddos
明志致远淡泊宁静2 小时前
记录一次服务器redis被入侵
运维·服务器·redis
Jtti2 小时前
Jtti:服务器总是自动重启怎么办?
运维·服务器
我是黄大仙2 小时前
利用飞书多维表格自动发布版本
运维·服务器·数据库·飞书
YRr YRr2 小时前
ubuntu ros 解决建完图后 保存的地图非常小的问题
linux·运维·ubuntu
石牌桥网管4 小时前
DNS Resolver解析服务器出口IP查询
运维·网络·tcp/ip·dns