LVS 与 NGINX:探究两种主流负载均衡

LVS 与 NGINX:探究两种主流负载均衡

LVS VS NGINX: Exploring the Advantages and Disadvantages of Two Mainstream Load Balancing Schemes

  • Title: LVS 与 NGINX:探究两种主流负载均衡
  • Tag: lvs、nginx
  • Author: Tacks
  • Create-Date: 2023-10-26
  • Update-Date: 2023-10-26

0、Ref

0、Keyword

  • Linux Virtual Server LVS - Linux虚拟服务器
  • Load Balance LB - 负载均衡
  • Global Load Balance GLB - 全局负载均衡/地域负载均衡
  • Client IP CIP - 客户端访问 IP
  • Virtual IP VIP - 虚拟IP地址 (面向外部接收用户请求)
  • Director IP DIP - 负载均衡节点内部通讯 IP
  • Real IP RIP - 后端服务器 IP
  • Director Server DS - 前端负载均衡节点
  • Real Server RS - 后端真实服务器
  • High Available HA - 高可用
  • Domain Name System DNS 域名解析系统
  • Network Address Translation NAT 网络地址转换
  • Round-robin rr 轮循
  • Weight-round-robin wrr 加权轮循
  • IP-hash IP哈希
  • Least-connections lc 最少连接数
  • Weight-least-connections wlc 权重最少连接数
  • IP Virtual Server IPVS
  • iptables Linux防火墙的管理工具
  • Virtual Router Redundancy Protocol VRRP 虚拟路由冗余协议

1、负载均衡 🔀

负载均衡( Load Balance )是一种电子计算机技术,用来在多个计算机、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。

1.1 什么是负载均衡?

『负载均衡』 Load Balance , 顾名思义,就是将负载进行平均分配出去。

在业务规模还很小的时候,例如个人博客网站,通常来说单机就能满足负载需求,但随着互联网的流量越来越大,就需要多台服务器,设计高可用的集群来应对。 为了解决并发能力,增强网络处理能力,减轻单个机器的负载,提升整体服务性能。负载均衡通过动态调度请求,将大量流量分发到不同的服务器上,从而保证各个服务器的负载相对均衡。负载均衡就是组建高可用集群的关键技术。

[User Request]                                      [App Server]
    |   \                                         / 
[Request]   ——> [Internet]   ——>    [Load Balancer] -> [App Server]
    |   /                                         \
[User Request]                                     [App Server]

生活中的负载均衡

试想一下,每天上下班的高峰期,如果地铁只有一个出入闸机,那么必定要排上很长的队,每个人花费的时间都取决于这一个队伍的长度;好在地铁通常会有很多个闸机,并且出口和入口不能同时共用,假设有8个入口闸机,那么用户会根据队伍长度均衡的排在不同的闸机队伍后面,从而大大减少用户等待时间,这也提高地铁运行效率。当然 Web 世界中,一个网站的响应时间太久往往会丧失用户。但就算地铁提供了8个入口闸机,高峰期该堵还是会堵,毕竟地铁还是很经济实惠,除去排队时间,不会遇到路上堵车的情况。那你说为什么不多开几个闸机呢,这取决于当前地铁站能容纳的人数,以及地铁车次的安排。所以负载均衡也不能解决所有性能问题,但是负载均衡是高可用的关键技术之一。

1.2 负载均衡需要具备什么能力?

  • 流量分发和调度
    • 将来自客户端的请求按照一定的策略分发到后端的服务器上
  • 健康检查和故障转移
    • 监控服务器的健康状态,并在服务器故障时自动将流量转移到其他可用服务器上
  • 可扩展性和水平扩展
    • 支持添加额外的负载均衡节点或服务器,以处理更大规模的流量

1.3 负载均衡有哪些种类?

1.3.1 从网络层次上考虑(OSI网络模型的不同层)

既然要处理网络流量,那就先来看一下 OSI 七层网络模型如下:

【OSI七层网络模型】                 【ICP/IP四层网络模型】                  【传输数据名称】
==============================================================================================
                [七层]
[应用层]        ------->        |                               |      ------> (消息报文 `Message-Data`)
[表示层]        ------->        | 应用层 {HTTP/HTTPS/DNS/FTP/..}|      ------> (表示数据 `Presentation-Data`)
[会话层]        ------->        |                               |      ------> (会话数据 `Session-Data`)

                [四层]
[传输层]        ------->        | 传输层 {TCP/UDP}|                    ------> (段`Segments`/数据报 `User-Datagram`)

[网络层]        ------->        | 网络层 {ARP/IP/ICMP}|                ------> (数据包 `Packets`)

[数据链路层]    ------->        | 数据链路层   |                        ------> (帧 `Frames`)
[物理层]        ------->        |             |                        ------> (比特 `Bits`)

那么根据 OSI 模型可以将负载均衡分为:

其中 二层负载均衡通常来说都是硬件来实现的,七层负载均衡通常来说是软件层面实现。

二层负载均衡(数据链路层)
  • 用于局域网内部,提供虚拟 IP 地址,虚拟 MAC 地址接收数据,再流量进行分发到真正的 MAC 主机实例上,最后 MAC 主机直接响应用户
  • 相关用法:
    • 以太网链路聚合
      • 以太网链路聚合,多条以太网物理链路捆绑在一起成为一条逻辑链路,从而实现增加链路带宽的目的
      • 链路聚合控制协议:LACP(Link Aggregation Control Protocol)
      • 增加链路带宽,链路互相动态备份
    • PPP 捆绑技术
      • 将多个物理链路合并或者捆绑成一个大逻辑链路的机制
      • 增加带宽,减少延时,线路备份
  • 优缺点:
    • 效率高
      • Client (请求某IP) => MAC LB (二层负载和真实服务器IP相同,经过负载修改真正 MAC地址) => Server1 (服务集群:明确的MAC地址) => Client (直接响应)
    • 不能跨子网
      • 由于提供虚拟 MAC,再经过负载均衡器后,修改真实的 MAC 地址,这表明负载均衡器和真实服务器是二层可达
三层负载均衡(网络层)
  • 外部对虚拟的 IP 地址请求,负载均衡接收后分配后端实际的IP地址响应,不同机器不同的IP。
  • 相关用法:
    • OSPF
    • RIP
  • 优缺点:
    • 可以跨子网
四层负载均衡 (传输层)

四层负载均衡,也称之为四层交换机,就是三层 VIP + 四层 PORT,来进行路由转发分配到真实的服务器。

四层负载均衡工作在 OSI 模型的传输层,主要是 TCP/UDP 协议,这两种协议中除了包含源IP、目标IP以外,还包含源端口号及目的端口号。通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。

  • 主要基于 TCP 协议的负载均衡,通过 IP + PORT 来进行转发
  • 转发模式:
    • DR Direct Routing
      • 三角传输: 通过修改 MAC 地址,让流量经过二层转发到达应用服务器
      • 优点:高效,应用服务器直接把应答响应给到客户端,不需要经过负载均衡
      • 缺点:依赖于二层负载,需要在同一个局域网内,所有应用服务器统一对外需要配置 VIP
    • NAT Network Address Translation
      • 修改数据包的目的IP地址,让流量到达应用服务器,应用服务器处理完毕后,仍然需要让响应回到负载均衡器进行 源IP 改成 VIP 才能让客户端识别出来
      • 优点:应用服务器无需配置 VIP
      • 缺点:负载均衡器需要以网关的形式存在,流量流入流出都要经过,必须在同一个局域网内
    • TUNNEL
      • 源设备和目标设备之间建立一条虚拟通道,将数据包封装在通道中传输,类似 DR,但是需要支持 Tunnel
    • FULLNAT
      • 可以摆脱局域网的限制
七层负载均衡 (应用层)

七层负载均衡,也称之为七层交换机,七层在四层上面,所以七层一般来说也是支持四层负载。除了根据 IP+PORT 来进行负载分流,也能通过 HOST、URL、Header 等进行分配。

七层负载均衡工作在 OSI 模型的应用层,应用层协议较多,常用 HTTP、DNS 等。七层负载就可以基于这些协议来负载。负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接受到客户端发送的真正应用层内容的报文,然后再根据该报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。

四层和七层的负载均衡区别
  • OSI 网络模型的层级不同
    • 四层负载对应传输层
    • 七层负载对应应用层
  • TCP 连接建立
    • 四层负载,本身充当路由转发作用,在接收到客户端的流量以后通过修改数据包的地址信息将流量转发到后端服务器 ,只需要建立一次 TCP 连接 , 客户端直接和真实后端服务器连接
    • 七层负载,充当中间人代理作用,七层负载均衡会跟客户端建立一层完整的连接将应用层的请求流量解析出来,再根据调度均衡算法选一台应用服务器并与之建立连接,需要建立两次 TCP 连接
  • 灵活性
    • 四层负载,仅支持网络层的转发,不解析用户请求内容
    • 七层负载,从应用层可以解析用户请求内容,从而进行不同的处理
  • 效率
    • 四层负载,更加底层高效
    • 七层负载,相对来说没有四层那么高效,但是功能更加丰富
  • 具体代表协议
    • 四层负载均衡:IP、MAC
    • 七层负载均衡:HTTP、DNS

1.3.2 从载体设备考虑(硬件/软件)

硬件负载均衡

使用专用的物理设备(如负载均衡器或应用交换机)来进行流量分发和负载均衡。例如 F5、A10

F5 Big-IP

F5 Network Big-IP 是一种专门用于负载均衡的网络设备,其性能和处理能力非常强大,通过硬件抗压,可以达到每秒百万级别的请求数量,但是部署复杂度和运维成本较高,主要是价钱贵。

  • 优点
    • 支持全局负载均衡
    • 支持复杂均衡算法
    • 性能贼牛 吞吐量大,单机每秒百万并发不成问题
    • 安全性高 一些防火墙、防DDOS攻击等
  • 缺点
    • 贵:F5价格在15w~55w,A10价格在55w-100w
软件负载均衡

通过软件实现负载均衡功能,通常在服务器上运行的应用程序或服务来实现。

软件负载均衡,应用最广泛,相对于硬件价格的昂贵,软件开发的成本要低的多,更何况还有很多开源的负载均衡软件。

  • LVS
  • Nginx
  • HAProxy
  • DNS

LVS-负载均衡

  • 四层负载均衡
    • 基于4层的网络协议的,抗负载能力强,对于服务器的硬件要求除了网卡外,其他没有太多要求
    • 抗负载能力强,抗负载能力强、性能高、能达到F5硬件的60%,对内存和cpu资源消耗比较低
  • VIP
    • 需要用虚拟 IP
  • 支持负载均衡算法
    • rr(轮循)、wrr(加权轮循)、lc(最小连接)、wlc(权重最小连接)
  • 灵活度相对较低
    • 可配置项不多,相对于 七层负载均衡

Nginx-负载均衡

  • 七层负载均衡
    • 基于 7 层的 HTTP/HTTPS 协议,可以基于URL、Header等做分流操作
  • 高性能
    • 基于事件驱动的设计模型,可以处理大量的并发连接,一般来说可以支持过万并发
  • 多种负载均衡算法
    • Nginx 自带 轮询、权重、IP哈希,可以引入第三方调度策略
  • 支持健康检查
    • 自身被动式健康检查 ngx_http_upstream_module
    • 第三方主动监控检查 nginx_upstream_check_module yaoweibin/nginx_upstream_check_module
    • 可以定期检查后端服务器的健康状态,如果某个服务器宕机,Nginx 可以自动将其从服务器列表中移除,避免向它发送请求

HAProxy-负载均衡

  • 支持四、七层负载均衡
    • 既可以在传输层(TCP/四层)进行负载均衡,也可以在应用层(HTTP/七层)进行负载均衡
  • 优化健康检测机制
  • 支持会话保持
    • 客户端IP、Cookie、Session
  • HAProxy 可以对 Mysql进行负载均衡,对后端的DB节点进行检测和负载均衡

DNS-负载均衡

DNS 域名解析系统,位于应用层,妥妥的七层负载均衡,DNS 自定向下是一个树形结构,(根域名服务器=>一级域名服务器=>二级域名服务器=>三级域名服务器=>…=>本地域名服务器)。那么 DNS 查询就是一个逆向的过程,先请求本地域名服务器,然后再向上层,一旦命中就会返回,通常来说每一层都会有对应缓存。

DNS 实现负载均衡,就是依靠 DNS 查询缓存。每次一个域名通过 DNS 解析到不同 IP,每个 IP 对应不同的服务器实例,这样就完成了流量的调度。

① [Client] 请求 www.xxx.com =>  [CDN] 
② [CDN] 解析返回 IP => [Client]
③ [Client] 请求 IP => [Server]
  • 用途
    • 虽然简单,但是缺点也比较明显,负载均衡可配置的地方也不灵活,通常不会直接拿来当负载均衡
    • 通常会用先 DNS 来做基于地理级别的全局负载均衡,内部再用更细粒度的更灵活的负载均衡方式。
  • 优点
    • 实现简单,成本低
    • 无需自己开发或维护负载均衡设备
  • 缺点
    • 可用性差
      • 故障切换延迟大,服务器升级不方便
      • 由于 DNS 和 用户 之间有层层的缓存,如本地、路由器、运营商等
      • 如果发生故障,即使立马修改 DNS,用户本地生效并不及时
    • 流量调度不均衡,粒度太粗
      • 跟运营商的 Local-DNS 也有关系,有可能并不会随机分配 IP,由于缓存和受服务地区用户限制,可能你访问的 IP 总是同一个
    • 负载均衡策略单一
      • 支持 rr 轮询,不支持权重、哈希等其他策略
    • 负载的机器 IP 数量有限
      • 由于 DSN 底层是 UDP 协议传输
      • UDP 的 报文受链路的最大传输单元 MTU 限制,通常 1500 字节
      • DNS 中,当我们查询一个域名时,DNS 服务器会返回一个或多个与该域名对应的 IP 地址 ,那么这个列表有多少 IP 地址就受网络链路层传输 MTU 大小限制

1.3.3 从地理结构考虑(本地/全局)

本地负载均衡 (Local Load Balance)

本地负载均衡是指对本地的服务器群做负载均衡。

本地负载均衡能有效地解决数据流量过大、网络负荷过重的问题,并且不需花费昂贵开支购置性能卓越的服务器,充分利用现有设备,避免服务器单点故障造成数据流量的损失。其有灵活多样的均衡策略把数据流量合理地分配给服务器群内的服务器共同负担。即使是再给现有服务器扩充升级,也只是简单地增加一个新的服务器到服务群中,而不需改变现有网络结构、停止现有的服务。

全局负载均衡 (Global Load Balance)

全局负载均衡是指对分别放置在不同的地理位置、有不同网络结构的服务器集群 作负载均衡。

通常是在全球范围内对服务器进行负载均衡。这种方式主要是通过将用户的请求路由到最近的或者性能最好的数据中心,以提供最佳的用户体验。全局负载均衡通常基于 DNS 解析,通过解析不同的 IP 地址将用户的请求路由到不同的数据中心。全局负载均衡可以提供灾难恢复和避免单点故障的能力。

1.4 常见的负载均衡算法有哪些?

负载均衡算法是一组规则,负载均衡器遵循这些规则来确定最适合每个不同客户端请求的服务器。通常有静态算法和动态算法实现流量分发。

静态 Static load balancing algorithms

静态负载平衡算法在分配工作负载时不考虑系统的当前状态,不会知道哪些服务器运行缓慢以及哪些服务器没有被充分使用。配置相对容易。

  • 轮询/加权轮询 Round Robin
    • 含义:将请求按顺序轮流地分配到每个节点上
      • 加权:根据服务器性能,可以权重稍微多一些在性能比较好的机器上
    • 优缺点
      • 简单高效、易于水平扩展
  • 随机 Random
    • 含义:基于统计概率理论,将请求随机分配到每个节点,随着调用次数越多,实现调用情况也趋于平均分配
    • 优缺点
      • 简单高效、类似轮询
  • 哈希 Hash
    • 含义:哈希+取模;
      • 根据客户端的IP地址,通过哈希函数计算得到一个数值,用该数值对服务器节点数进行取模,然后得到的序号就是要访问的节点
    • 优缺点
      • 同一个IP的请求会落到相同的节点,有利于测试、灰度发布;
      • 但如果某个用户成为热点用户,容易导致某个节点故障,大量流量访问同一个节点,这个时候可以结合轮询处理
  • …

动态 Dynamic load balancing algorithms

动态负载平衡算法会考虑每台服务器的当前可用性、工作负载和运行状况,可以将流量从负担过重或性能不佳的服务器转移到未充分利用的服务器,从而保持分配的均匀和高效。

  • 最少连接 Least Connections
    • 含义:将请求尽可能给当前连接数最少的机器处理
      • 根据每个节点当前的连接情况,动态地选取其中当前积压连接数最少的一个节点处理当前请求
      • 根据机器的连接数的倒数,动态分配权重
    • 优缺点:
      • 动态变化,根据节点状况实时变化;
      • 复杂度上升
  • 最短响应时间
    • 含义:能者多劳,响应速度快的机器多分配一些请求
      • 根据请求的响应时间,来动态调整每个节点的权重,将响应速度快的服务节点分配更多的请求
      • 根据响应时间进行计算打分,动态分配权重
    • 优缺点:
      • 动态变化
      • 复杂度上升
  • …

1.5 负载均衡的好处?

  • 高并发性
    • 通过一定的 算法策略, 将流量均衡的分配到后端实例,以此来提高集群的并发处理能力
  • 高可用性
    • 负载均衡根据监控服务器性能来选择实例,当某实例负载过高或异常时,会减少流量流入或跳过实例
  • 可扩展性/可伸缩性
    • 根据流量大小,增加或减少后端服务器实例
  • 安全防护
    • 过滤器、黑名单处理等

2、LVS

LVS (Linux Virtual Server) Linux 虚拟服务器, 是一个开源的软件,可以实现 Linux 平台下的简单负载均衡。 由章文嵩博士发起的一个开源项目,官方网站为 www.linuxvirtualserver.org 。现在 LVS 已经是 Linux 内核标准的一部分,工作在四层 网络层,用于多服务器的负载均衡,从而实现高可用高性能的服务器集群。

目标

  • 利用集群技术为 Linux 构建高性能、高可用的服务器,提供良好的可扩展性、可靠性和可服务性。

    LVS 与 NGINX:探究两种主流负载均衡

2.1 LVS 集群的三层架构

负载均衡层 Load Balancer

整个集群系统的前端机,将客户端的请求均衡到一组服务器上,让客户端认为所有的服务都来自同一个IP地址

负载均衡器是服务器集群系统的单一入口点,有两种方式实现。( LVS 通常我们是指 IPVS 的四层负载均衡)

  • IPVS 四层 ->详情
    • 在Linux内核内部实现IP负载均衡

即所谓的第四层交换。运行在主机上的 IPVS 充当真实服务器集群前端的负载均衡器,它可以将基于 TCP/UDP 的服务的请求,和指定的调度算法,可以定向转发到真实服务器。

  • KTCPVS 七层 ->详情
    • 在Linux内核内部实现应用程序级负载均衡

即所谓的七层交换。由于用户空间的第七层切换开销非常高,因此最好在内核内部实现,以避免用户空间和内核空间之间的上下文切换和内存复制的开销。尽管KTCPVS的可扩展性低于 IPVS ,但它很灵活,因为在请求重定向到一台服务器之前,请求的内容是已知的。但是貌似这个用的并不是很多,也很少更新了。

服务器群组 Server Cluster

一组运行实际网络服务的服务器,例如 Web、Mail、DNS 等服务

服务器集群的节点数可以根据系统承受的负载而改变。当所有服务器都过载时,可以添加更多新服务器来处理不断增加的工作负载。

数据共享存储 Data Storager

为服务器提供共享的存储空间,方便服务器之间拥有相同的内容、提供相同的服务。

共享存储可以是数据库系统、网络文件系统或分布式文件系统。

2.2 LVS 工作的三种负载均衡方式

基于 IPVS 三种实现方式,分别是通过 NAT 的虚拟服务器(NAT)、通过 IP 隧道的虚拟服务器(TUN) 、 通过直接路由的虚拟服务器(DR)

对比 NAT TUN DR
主要实现方式 地址转换 封装 IP 修改 MAC 地址
对服务器要求 无 支持IP隧道 支持虚拟网卡设备
对节点要求 内部 IP,服务节点隐蔽 公用 IP 地址,节点安全暴露 公用 IP 地址,节点安全暴露
网关 负载均衡作为网关 服务器的节点同自己的网关或者路由器连接,不经过负载均衡器 服务器的节点同自己的网关或者路由器连接,不经过负载均衡器
IP 仅需要一个合法的 IP 地址作为 VIP 地址 每个服务器都需要有一个合法的 IP 地址,可以从路由到客户端 VIP + 每个服务器都需要有一个合法的 IP 地址,可以从路由到客户端

VS/NAT (Virtual Server via Network Address Translation)

通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器

  • [VS/NAT] 请求和响应都必须要经过处理报文
[Client] -> [VS/NAT] -> 重写请求报文的 目标地址 -> 调度策略, 选择真实后端服务器  -> [Real Server] -> 处理中

[Real Server] -> 响应报文 -> [VS/NAT] -> 重写响应报文的 源地址 -> [Client]

LVS 与 NGINX:探究两种主流负载均衡

LVS 与 NGINX:探究两种主流负载均衡

大致流程

  • Client 客户端请求到 DS (Director Server),数据报文通过内核空间的 PREROUTING 链 (至于什么 PREROUTING ,参考 iptables 四表五链)
    • 请求报文 源IP=CIP 目标IP=VIP
  • PREROUTING 检查数据包,发现目标IP是本机,然后送到 INPUT 链
  • IPVS 发现请求的是集群服务,发生修改 IP , NAT 的精髓, 修改数据包的目标IP地址为后端服务器IP, 然后将数据包发至 POSTROUTING 链
    • 请求报文 源IP=CIP 目标IP=RIP
  • POSTROUTING 链通过选路,将报文发送给 RS(Real Server)
  • RS 比对发现目标为自己的IP,开始构建响应报文发回给 DS
    • 响应报文 源IP=RIP 目标IP=CIP
  • DS 在返回给客户端之前,先修改报文的源IP,改为自己的 VIP,NAT 的精髓,然后响应
    • 响应报文 源IP=VIP 目标IP=CIP

特点精髓

  • RS 使用私有地址,对外不可见
  • DS 负载均衡充当网关,请求响应必须经过 DS,所以容易成为瓶颈
  • DS 负责修改报文IP

VS/TUN (Virtual Server via IP Tunneling)

为了避免 VS/NAT 中间调度处理能力成为凭借,调度器把请求报文通过 IP隧道 转发至后端的真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。

  • [VS/TUN] 需要 支持IP隧道

IP 隧道(IP tunning)是一种数据包封装技术,它可以将原始数据包封装并添加新的包头(内容包括新的源地址及端口、目标地址及端口),从而实现将一个目标为调度器的VIP地址的数据包封装,通过隧道转发给后端的真实服务器(Real Server)

[Client] -> [VS/TUN] -> 重写请求报文的 目标地址 -> 调度策略, 选择真实后端服务器 -> IP隧道进行转发  -> [Real Server] -> 处理中 -> [Client]

LVS 与 NGINX:探究两种主流负载均衡

LVS 与 NGINX:探究两种主流负载均衡

大致流程

  • Client 客户端请求到 DS (Director Server),数据报文通过内核空间的 PREROUTING 链 (至于什么 PREROUTING ,参考 iptables 四表五链)
    • 请求报文 源IP=CIP 目标IP=VIP
  • PREROUTING 检查数据包,发现目标IP是本机,然后送到 INPUT 链
  • IPVS 发现请求的是集群服务,请求报文的首部再次封装一层IP报文 , DR 的精髓, 然后将数据包发至 POSTROUTING 链
    • 封装报文 源IP=DIP 目标IP=RIP
    • 请求报文 源IP=CIP 目标IP=VIP
  • POSTROUTING 链 根据最新封装的IP报文,将数据包发至RS
    • 封装报文 源IP=DIP 目标IP=RIP
  • RS 比对发现目标为自己的IP,然后拆包,发现里面还有一层IP首部,而且目标是 VIP, 然后处理请求,向外发送网卡
    • 响应报文 源IP=VIP 目标IP=CIP

特点精髓

  • RIP、VIP、DIP 全是公网地址
  • 请求报文经过 DS,响应报文不经过 DS
  • RS 要支持 IP隧道功能

VS/DR (Virtual Server via Direct Routing)

在 VS/TUN 由于需要在LVS调度器与真实服务器之间创建隧道连接,这同样会增加服务器的负担。那就看看 DR 直接路由

  • [VS/DR] 调度器和真实服务器需要在同一个物理网段

DR模式也叫直接路由模式,通过改写请求报文的 MAC 地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。VS/DR 要求调度器与真实服务器都有一块网卡连 在同一物理网段上,

  • [VS/DR] VIP 地址需要在调度器与后端所有的服务器间共享

VIP 地址需要在调度器与后端所有的服务器间共享,因为最终的真实服务器给客户端回应数据包时需要设置源IP为VIP地址,目标IP为客户端IP,这样客户端访问的是调度器的VIP地址,回应的源地址也依然是该VIP地址(真实服务器上的VIP),客户端是感觉不到后端服务器存在的

LVS 与 NGINX:探究两种主流负载均衡

LVS 与 NGINX:探究两种主流负载均衡

大致流程

  • Client 客户端请求到 DS (Director Server),数据报文通过内核空间的 PREROUTING 链 (至于什么 PREROUTING ,参考 iptables 四表五链)
    • 请求报文 源IP=CIP 目标IP=VIP
  • PREROUTING 检查数据包,发现目标IP是本机,然后送到 INPUT 链
  • IPVS 发现请求的是集群服务,发生修改 MAC , DR 的精髓, 请求报文中的源MAC地址修改为DIP的MAC地址,将目标MAC地址修改RIP的MAC地址, 然后将数据包发至 POSTROUTING 链
    • 请求报文 源IP=CIP 目标IP=VIP
    • 请求报文 源MAC=DS的MAC 目标MAC=RS的MAC
  • POSTROUTING 链 检查目标MAC地址 为 RS的MAC地址,那么此时数据包将会发至 RS,DS和RS在同一个网络中,所以是通过二层来传输
  • RS 比对发现目标为自己的MAC,开始构建响应报文,通过网卡向外发送,由于RS统一对外网卡都是一个 VIP
    • 响应报文 源IP=VIP 目标IP=CIP

特点精髓

  • 请求报文的目标MAC地址修改为挑选出的RS的MAC地址
  • DS 和 RS 必须同一个物理网络中
  • 请求报文经过 DS,响应报文不经过 DS

2.3 LVS 负载调度算法

DS 负载调度器是根据各个服务器 RS 的负载情况,动态地选择一台服务器来处理和响应用户请求。

  • 轮询 rr (Round-Robin)
  • 加权轮询 wrr (Weighted-Round-Robin)
  • 最少连接调度 lc (Least-Connections)
  • 加权最少连接调度 wlc (Weighted-Least-Connections)
  • 基于局部性的最少链接 lblc (Locality-Based Least Connections)
  • 带复制的基于局部性最少链接 lblcwr (Locality-Based Least Connections with Replication)
  • 目标地址散列 dh (Destination Hashing)
  • 源地址散列 sh (Source Hashing)
  • 最短的期望的延迟 sed (Shortest Expected Delay)
  • 最少队列调度 nq (Never Queue)

2.4 Keepalived

一些疑问

  • 经常见到这个 LVS + Keepalived ,那他到底是什么?

Keepalived 是一个用 C 语言编写的路由软件, 详情参考 官网。 该项目的主要目标是为 Linux 系统和基于 Linux 的基础设施提供简单而强大的负载均衡和高可用性设施。

  • 通过前面可以理解 LVS 只是负责负载均衡,依据调度策略找到目标 RS,那如果后台的 RS 的服务挂掉以后,LVS 会健康检查摘除有问题的 RS 吗?

不会,所以 引入 Keepalived 。 Keepalived一个基于 VRRP 协议来实现的 LVS 服务高可用方案,可以利用其来解决单点故障。一个LVS服务会有2台服务器运行 Keepalived,一台为主服务器 master ,一台为备份服务器 backup ,但是对外表现为一个虚拟IP,主服务器会发送特定的消息给备份服务器,当备份服务器收不到这个消息的时候,即主服务器宕机的时候, 备份服务器就会接管虚拟IP,继续提供服务,从而保证了高可用性

  • 什么是 VRRP 协议 ?

虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master 和多个 backup,master 上面有一个对外提供服务的 VIP( Virtual IP Address)(该路由器所在局域网内其他机器的默认路由为该 vip),master 会发组播,当 backup 收不到 vrrp 包时就认为 master 宕掉了,这时就需要根据 VRRP 的优先级来选举一个 backup 当 master 。这样的话就可以保证路由器的高可用了。

Keepalived 实现了一组检查器,以根据负载平衡服务器池的健康状况动态、自适应地维护和管理它们。另一方面高可用性是通过 VRRP 协议实现的。VRRP 是路由器故障转移的基本模块。此外,Keepalived 还实现了一组 VRRP 有限状态机挂钩,提供低级和高速协议交互。为了提供最快的网络故障检测,Keepalived 实现了 BFD 协议。VRRP 状态转换可以考虑 BFD 提示来驱动快速状态转换。Keepalived 框架可以单独使用,也可以一起使用,以提供弹性基础设施。

3、Nginx

Nginx 最常用功能之一就是负载均衡,经常用的就是七层负载均衡,基于七层的 HTTP/HTTPS 协议实现,经常用在 Web 后端服务器上。不过来后也提供了四层负载均衡,如基于 TCP/UDP 协议的,会用到如数据库、邮件等服务上

3.1 Nginx 的四层和七层负载均衡

Nginx 的负载均衡主要是由 代理模块 (proxy) 和 上游模块 (upstream) 共同的作用下实现的。

Nginx 通过代理模块的反向代理功能将用户请求转发到上游服务器组,上游模块通过指定的负载均衡策略及相关的参数配置将用户请求转发到目标服务器上

upstream 和 server 是同一个层级的。

upstream 模块

  • 作用:
    • 定义 upstream 上游的后端服务器群组、负载均衡策略
# 定义 一组服务器作为上游,名字为 backend
upstream backend {
    server backend1.example.com       weight=5;     # 默认的端口号80,并设置权重为5。这意味着在负载均衡时,该服务器将获得更多的请求
    server backend2.example.com:8080;               # 指定服务器端口号为 8080,默认权重为1
    server unix:/tmp/backend3;                      # 可以用于与本地套接字通信的后端服务器

    server backup1.example.com:8080   backup;       # 被标记为备份状态,表示只有在其他所有服务器都不可用时才会被使用
    server backup3.example.com:8080   down;         # 被标记为停用状态,
}

proxy 模块

  • 作用:
    • 定义反向代理,用来代理到上游模块
server {
    location / {
        # 反向代理
        proxy_pass http://backend;

        # 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

3.1.1 HTTP 负载均衡

HTTP 负载均衡是在应用层(七层)上进行的负载均衡 ,Nginx 通过使用反向代理模块来实现 HTTP 负载均衡。

当客户端发送 HTTP 请求时,Nginx 会根据预先配置的算法(如轮询、IP哈希等)将请求转发给后端的多个服务器,然后将响应返回给客户端。

具体模块 :

相关配置 :

轮询 (Round-Robin)
http {
    upstream backend {
        ; weight  配置权重
        server 192.168.1.100:9001 weight=5;
        server 192.168.1.101:9002 weight=1;
        server 192.168.1.101:9003 weight=1;
    }

    server {
        listen 9999;

        location / {
            proxy_pass http://backend;
        }
    }
}
哈希 (IP Hash)
http {
    upstream backend {
        hash $remote_addr;
        ; hash $remote_addr consistent;
        server 192.168.1.100:9001; 
        server 192.168.1.101:9002;
        server 192.168.1.101:9003;
    }

    server {
        listen 9999;

        location / {
            proxy_pass http://backend;
        }
    }
}
最少连接 (least_conn)
http {
    upstream backend {
        least_conn;
        server 192.168.1.100:9001 weight=5;
        server 192.168.1.101:9002 weight=1;
        server 192.168.1.101:9003 weight=1;
    }

    server {
        listen 9999;
        proxy_pass backend;
    }
}

3.1.2 TCP/UDP 负载均衡

TCP/UDP 负载均衡是在传输层(四层)上进行的负载均衡 , 不同于 LVS 实现的四层负载均衡, LVS属于Linux内核层,Nginx属于用户层相对更灵活控制管理, Nginx 通过使用 Stream 模块来实现 TCP/UDP 负载均衡。

其实一开始Nginx 只能作为 七层负载均衡,后来在 1.9 后引入。需要 ngx_stream_core_module 模块支持,默认这个模块不会编译,需要加编译参数 –with-stream 。

具体模块:

相关配置:

TCP/UDP 和 HTTP 的负载均衡配置略微不同,但基本上还是类似的,需要最外面有一个 stream 的大括号,来包括 upstream 和 server

轮询 (Round-Robin)
  • Nginx 默认使用轮询负载均衡策略 , weight 对应每个服务器的权重
stream {
    upstream backend {
        server 192.168.1.100:9001 weight=5;
        server 192.168.1.101:9002 weight=1;
        server 192.168.1.101:9003 weight=1;
    }

    server {
        ; 默认是 TCP
        listen 9999;
        ; 可以配置监听端口为 udp
        ; listen 9999 udp;
        proxy_pass backend;
    }
}
哈希 (IP Hash)
  • Nginx 利用 hash 指令,把 客户端 IP($remote_addr)作为哈希键,其可将同一 IP 客户端始终转发给同一台后端服务器,实现简单的会话保持
  • 关于一致性哈希: 会用到 consistent 指令
    • 原因:当后端服务器的增加或者减少,之前计算的 hash 就会发生变化,导致原本分配到某个服务器的请求被分配到另一个服务器上。
    • 解决:将服务器列表中的每个服务器映射到一个虚拟环上,同时将请求的哈希值也映射到这个虚拟环上。当有新的服务器加入或离开时,只会影响到该服务器周围的一小段区域,而不会影响整个哈希环,
stream {
    upstream backend {
        hash $remote_addr;
        ; hash $remote_addr consistent;
        server 192.168.1.100:9001 weight=5;
        server 192.168.1.101:9002 weight=1;
        server 192.168.1.101:9003 weight=1;
    }

    server {
        listen 9999;
        proxy_pass backend;
    }
}
最少连接 (least_conn)
  • Nginx 配置 least_conn ,将请求发送到当前连接数最少的后端服务器,以实现负载均衡
stream {
    upstream backend {
        least_conn;
        server 192.168.1.100:9001 weight=5;
        server 192.168.1.101:9002 weight=1;
        server 192.168.1.101:9003 weight=1;
    }

    server {
        listen 9999;
        proxy_pass backend;
    }
}

3.2 Nginx 负载调度算法

  • 轮询 rr (Round-Robin)
  • 加权轮询 wrr (Weighted-Round-Robin)
  • 最少连接调度 lc (Least-Connections)
  • 最快响应时间 lt (Least time)
  • 普通哈希 gh (Generic hash)
  • IP 哈希 Hash
  • 随机 Random

3.3 Nginx 的健康检查

Nginx upstream 模块中默认的检测机制是通过用户的真实请求去检查被代理服务器的可用性,这是一种被动的检测机制。

通过 upstream 模块中 server 指令的指令值参数 max_fails 及 fail_timeout 实现对被代理服务器的检测和熔断。

http {
  upstream http_backend {
      # 10s内出现3次错误,该服务器将被熔断10s
      server 192.168.1.100:9001 max_fails=3 fail_timeout=10s;
      server 192.168.1.101:9001 max_fails=3 fail_timeout=10s;
      server 192.168.2.100:9001 max_fails=3 fail_timeout=10s;
  }

  server {
      proxy_connect_timeout 5s;               # 与被代理服务器建立连接的超时时间为5s
      proxy_read_timeout 10s;                 # 获取被代理服务器的响应最大超时时间为10s

      # 当与被代理服务器通信出现指令值指定的情况时,认为被代理出错
      # 并将请求转发给上游服务器组中 的下一个可用服务器
      proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
      proxy_next_upstream_tries 3;            # 转发请求最多3次
      proxy_next_upstream_timeout 10s;        # 总尝试超时时间为10s

      location /http/ {
          proxy_pass http://http_backend;
      }
  }
}

4、总结一下

首先说明哈,虽然 LVS 和 Nginx 都有四层和七层负载均衡能力,但是你懂的,大家通常都是用他的强项,所以一般情况下没有特殊说明,LVS 用的四层负载均衡, Nginx 用的七层负载均衡。

LVS 主要是利用转发, Nginx 主要是利用反向代理,来实现流量的负载均衡。

LVS

1、抗负载能力强;

LVS 工作方式逻辑简单,工作在网络层,仅仅做请求分发处理,不用处理流量解析,属于 Linux 内核层,稳如老狗哇,LVS 都不行,你加机器吧 。

2、可配置性低;

通常来说一旦确定了 LVS 的模式,除了日常添加或者减少机器,就没有什么其他配置,相对简单。

3、成熟方案;

自身有完整的双机热备方案,如LVS+Keepalived,一般项目实施中用得最多的还是 LVS/DR+Keepalived 。

4、无流量;

无流量,LVS 只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会受到大流量的影响。

5、强依赖网络环境;

LVS 需要向托管商至少申请多一个ip来做VIP。

Nginx

1、负载压力且稳定

虽然没有 LVS 牛逼, 10万并发一般能扛得住

2、对网络依赖项小;

理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,还需要单独申请 VIP

3、配置简单容易上手

开发人员,虽然不配置 LVS ,但是 Nginx 应该没少折腾,配置也容易上手

4、内置被动检查机制

负载均衡,上游多台服务器,可以配置max_fails=3 fail_timeout=10s, 10s内出现3次错误,该服务器将被熔断10s。

  • LVS + NGINX
# 流量方向
[Client] 
  |
[DNS] 
  |
[LVS]
  |
[Nginx]
  |
[APP]
本作品采用《CC 协议》,转载必须注明作者和本文链接
明天我们吃什么 悲哀藏在现实中 Tacks
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!