ZhouXiangの博客 后端工程师&机器学习爱好者

Java学习系列之负载均衡

2019-11-11

本文系记录对Java中负载均衡的学习资料,如有异议,欢迎联系我讨论修改。PS:图侵删!图片丢失请访问:传送门

负载均衡

负载均衡(Load Balance)建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡有两方面的含义:首先,大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间;其次,单个重负载的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后,将结果汇总,返回给用户,系统处理能力得到大幅度提高。目前负载均衡技术大多数是用于提高诸如在Web服务器、FTP服务器和其它关键任务服务器上的Internet服务器程序的可用性和可伸缩性。

负载均衡的分类

  • 二层负载均衡(mac):根据OSI模型分的二层负载,一般是用虚拟mac地址方式,外部对虚拟MAC地址请求,负载均衡接收后分配后端实际的MAC地址响应。
  • 三层负载均衡(ip):一般采用虚拟IP地址方式,外部对虚拟的ip地址请求,负载均衡接收后分配后端实际的IP地址响应。(即一个ip对一个ip的转发, 端口全放开)。
  • 四层负载均衡(tcp):在三次负载均衡的基础上,即从第四层”传输层”开始,使用”ip+port”接收请求,再转发到对应的机器。
  • 七层负载均衡(http):从第七层”应用层”开始,根据虚拟的URL或IP,主机名接收请求,再转向相应的处理服务器。

四层负载均衡

四层负载通过IP+端口号来决定哪些流量需要做负载均衡。对于需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP、UDP的流量是由哪台服务器处理的,后续连接的所偶遇流量同样转发至同一台服务器处理。这种负载均衡器无法理解应用层协议。

以常见的TCP为例,负载均衡设备在接收到第一个来自客户端的SYN请求时,选择一个最佳的服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器。TCP的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。LVS与Nginx是常见的四层负载均衡实现。

七层负载均衡

七层负载均衡在四层负载均衡的基础上,考虑应用层特征,通过报文中的真正有意义的应用层内容加负载均衡设备设置的服务器选择方式,决定最终的内部服务器。

以常见的TCP为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接受到客户端发送的真正应用层内容的报文,然后再根据该报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。负载均衡设备在这种情况下,更类似于一个代理服务器。负载均衡和前端的客户端以及后端的服务器会分别建立TCP连接。所以从这个技术原理上来看,七层负载均衡明显的对负载均衡设备的要求更高,处理七层的能力也必然会低于四层模式的部署方式。Nginx与Apache是常见的七层负载均衡实现。

四层负载均衡与七层负载均衡的区别

  • 协议上:四层基于TCP协议;七层基于HTTP协议
  • 握手次数上:四层只要1次(类似路由器);七层则要2次(代理服务器)
  • 性能上:四层高;七层较低,需识别URl、Cookie和Http Header等信息
  • 吞吐量:四层高;七层低
  • 架构设计上:四层较简单;七层较复杂
  • 功能上:四层较少;七层额外支持会话保持、图片压缩、加密等功能
  • 安全性:四层较低,无法抵御DDos攻击;七层较高,可防御SYN Flood

软件负载均衡和硬件负载均衡的区别

软件负载均衡的优点是需求环境明确,配置简单,操作灵活,成本低廉,效率不高,能满足普通的企业需求;缺点是依赖于系统,增加资源开销;软件的优劣决定环境的性能;系统的安全,软件的稳定性均会影响到整个环境的安全。

硬件负载均衡优点是独立于系统,整体性能大量提升,在功能、性能上优于软件方式;智能的流量管理,多种策略可选,能达到最佳的负载均衡效果;缺点是价格昂贵。

常见的负载均衡策略

  • 轮循均衡(Round Robin):每一次来自网络的请求轮流分配给内部中的服务器,从1至N然后重新开始。此种均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况。
  • 权重轮循均衡(Weighted Round Robin):根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器A的权值被设计成1,B的权值是 3,C的权值是6,则服务器A、B、C将分别接受到10%、30%、60%的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。
  • 随机均衡(Random):把来自网络的请求随机分配给内部中的多个服务器。
  • 权重随机均衡(Weighted Random):此种均衡算法类似于权重轮循算法,不过在处理请求分担时是个随机选择的过程。
  • 响应速度均衡(Response Time):负载均衡设备对内部各服务器发出一个探测请求(例如Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。此种均衡算法能较好的反映服务器的当前运行状态,但这最快响应时间仅仅指的是负载均衡设备与服务器间的最快响应时间,而不是客户端与服务器间的最快响应时间。
  • 最少连接数均衡(Least Connection):客户端的每一次请求服务在服务器停留的时间可能会有较大的差异,随着工作时间加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,并没有达到真正的负载均衡。最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。此种均衡算法适合长时处理的请求服务,如FTP。
  • 处理能力均衡:此种均衡算法将把服务请求分配给内部中处理负荷(根据服务器CPU型号、CPU数量、内存大小及当前连接数等换算而成)最轻的服务器,由于考虑到了内部服务器的处理能力及当前网络运行状况,所以此种均衡算法相对来说更加精确,尤其适合运用到第七层(应用层)负载均衡的情况下。
  • DNS响应均衡(Flash DNS):在Internet上,无论是HTTP、FTP或是其它的服务请求,客户端一般都是通过域名解析来找到服务器确切的IP地址的。在此均衡算法下,分处在不同地理位置的负载均衡设备收到同一个客户端的域名解析请求,并在同一时间内把此域名解析成各自相对应服务器的IP地址(即与此负载均衡设备在同一位地理位置的服务器的IP地址)并返回给客户端,则客户端将以最先收到的域名解析IP地址来继续请求服务,而忽略其它的IP地址响应。在种均衡策略适合应用在全局负载均衡的情况下,对本地负载均衡是没有意义的。
  • 哈希算法:一致性哈希,将相同参数的请求总是发送给同一提供者。当某一台提供者挂掉,原本发往该提供者的请求,基于虚拟节点,平摊到其他提供者,不会引起剧烈变动。
  • IP地址散列:通过管理发送方IP和目的地IP地址的散列,将来自同一发送方的分组(或发送至同一目的地的分组)同一转发到相同服务器的算法。当客户端有一系列业务需要处理而必须和同一服务器反复通信时,该算法能够以流(Session)为单位,保证来自同一客户端的通信能够一直在同一服务器中进行处理。
  • URL散列:通过管理客户端请求URL信息的散列,将发送至相同URL的请求转发至同一服务器的算法。

Nginx

Nginx是一个高性能的HTTP服务器、反向代理服务器、负载均衡器。Nginx具有CPU、内存资源消耗低,并发能力强、稳定性高等特点。Nginx使用了基于事件的驱动模型,因此处理请求的性能较高。

Nginx与Apache的区别

  • Nginx基于事件驱动,Apache基于流程
  • Nginx单线程处理所有请求,Apache一线程一请求
  • Nginx具有负载均衡,Apache过载后拒绝新请求
  • Nginx采用epoll模型,Apache采用Select模型
  • Nginx异步处理请求,Apache采用同步非阻塞处理请求
  • Nginx的资源占用低于Apache
  • Nginx高并发响应性能高,官方数据显示Nginx处理静态文件并发量达5w/s
  • Apache采用阻塞型处理请求,并发量上不来
  • Nginx支持负载均衡、反向代理
  • Apache运行更稳定,Bug少

Nginx的优点

  • 跨平台、配置简单
  • 非阻塞、高并发连接:处理2-3万并发连接数,官方监测能支持5万并发
  • 内存消耗小:开启10个nginx才占150M内存,Nginx采取了分阶段资源分配技术
  • Nginx处理静态文件好,耗费内存少
  • 内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上。
  • 节省宽带:支持GZIP压缩,可以添加浏览器本地缓存
  • 稳定性高:宕机的概率非常小
  • master/worker结构:一个master进程,生成一个或者多个worker进程
  • 接收用户请求是异步的:浏览器将请求发送到nginx服务器,它先将用户请求全部接收下来,再一次性发送给后端web服务器,极大减轻了web服务器的压力 一边接收web服务器的返回数据,一边发送给浏览器客户端
  • 网络依赖性比较低,只要ping通就可以负载均衡
  • 可以有多台Nginx服务器
  • 事件驱动,通信机制采用epoll模型

Nginx处理请求的过程

Nginx具有同时处理大量并发请求的能力,这是通过多进程机制和异步机制实现的。Nginx服务器启动后,会产生一个主进程-master和多个工作进程-slave,其中工作进程的数量可以在配置文件中指定。Nginx中的所有工作进程用于指定接收和处理客户端的请求。每个工作进程使用异步方式处理客户端请求。当某个工作进程接收到客户端的请求时,调用IO进行处理,如果不能立刻得到结果,就去处理其他事情;客户端在此期间也可以做一些其他事情。当IO调用返回时,就会通知此工作进程,该进程得到通知,暂时挂起当前处理的事务,去响应客户端请求。

Nginx事件驱动的理解

事件驱动模型一般由事件收集器、事件发送器、事件处理器三部分组成。其中时间收集器负责收集所有事件,例如用户的点击事件、输入事件、硬件时钟事件等;时间发送器负责将收集器收集的事件分发到目标对象;目标对象就是事件处理器所在的位置,事件处理器负责具体事件的响应时间。下面仅对事件处理器进行介绍。在基于事件驱动的模型中,有如下方法实现时间处理器:

  • 事件发送器每传递过来一个请求,目标对象就创建一个新进程用于调用事件处理器处理该请求
  • 事件发送器每传递过来一个请求,目标对象就创建一个新线程用于调用事件处理器处理该请求
  • 事件发送器每传递过来一个请求,目标对象就将其放入一个待处理列表,使用非阻塞IO的方式调用事件处理器处理该请求 由于前两种方式各有利弊,导致第三种方式逐渐演化成所谓的事件驱动处理库。事件驱动处理库又被称为IO多路复用方法,最常见的有select、poll、epoll方法。Nginx还额外支持rtsig、kqueue、dev/poll、eventport模型等。

select/poll/epoll 的工作原理

综述:select,poll,epoll都是I/O多路复用的机制。I/O多路复用可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

select:首先创建事件的描述符集合。对于一个描述符,可以关注其上的读事件、写事件以及异常事件,所以要创建三类事件的描述符集合,分别用来收集读事件描述符、写事件描述符以及异常事件描述符。select调用时,首先将时间描述符集合fd_set从用户空间拷贝到内核空间;注册回调函数并遍历所有fd,调用其poll方法,poll方法返回时会返回一个描述读写操作是否就绪的mask掩码,根据这个掩码给fd赋值,如果遍历完所有fd后依旧没有一个可以读写就绪的mask掩码,则会使进程睡眠;如果已过超时时间还是未被唤醒,则调用select的进程会被唤醒并获得CPU,重新遍历fd判断是否有就绪的fd;最后将fd_set从内核空间拷贝回用户空间。

select缺点:

  • 每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
  • 同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
  • select支持的文件描述符数量太小了,默认是1024

poll:poll是select的优化实现版,poll使用pollfd结构而不是select的fd_set结构。select需要为读事件、写事件和异常事件分别创建一个描述符集合,轮询时需要分别轮询这三个集合。而poll库只需要创建一个集合,在每个描述符对应的结构上分别设置读事件、写事件或者异常事件,最后轮询时可同时检查这三类时间是否发生。

epoll:select与poll中,都创建一个待处理事件列表,然后把这个列表发送给内核,返回的时候再去轮训这个列表,以判断事件是否发生。在描述符比较多的时候,效率极低。epoll将文件描述符列表的管理交给内核负责,每次注册新的事件时,将fd拷贝仅内核,epoll保证fd在整个过程中仅被拷贝一次,避免了反复拷贝重复fd的巨大开销。此外,一旦某个事件发生时,内核就把发生事件的描述符列表通知进程,避免对所有描述符列表进行轮询。最后,epoll没有文件描述符的限制,fd上限是系统可以打开的最大文件数量,通常远远大于2048。

select/poll/epoll 的区别

select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。

select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。

select/poll/epoll 各自的应用场景

  • select:timeout 参数精度为1ns,而poll和epoll为1ms,因此select更加适用于实时性要求比较高的场景,比如核反应堆的控制。select 可移植性更好,几乎被所有主流平台所支持
  • poll:poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用poll而不是select
  • epoll:只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接;需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势;需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试

Nginx 能抗高并发的原因

有别于多线程或多进程的模式,Nginx采用了多进程+基于事件驱动的模型,这种模型可以支持现代硬件成千上万的并发连接。Nginx中的所有工作进程用于指定接收和处理客户端的请求。每个工作进程使用异步方式处理客户端请求。当某个工作进程接收到客户端的请求时,调用IO进行处理,如果不能立刻得到结果,就去处理其他事情;客户端在此期间也可以做一些其他事情。当IO调用返回时,就会通知此工作进程,该进程得到通知,暂时挂起当前处理的事务,去响应客户端请求。由于制约WebServer响应时间的因素往往是密集的IO,所以这种异步处理方式能最大地提高吞吐量。Nginx缓存也提高了吞吐量,缓存加载进程(cache loader process)在启动时运行,把基于磁盘的缓存(disk-based cache)加载到内存中,然后退出。对它的调度很谨慎,所以其资源需求很低。缓存管理进程(cache manager process)周期性运行,并削减磁盘缓存(prunes entries from the disk caches),以使其保持在配置范围内。

Nginx 的进程模型

Nginx分为单工作进程和多工作进程模式。在多工作进程模式下,每个工作进程包含多个线程。Nginx服务器启动后,产生一个主进程,主进程执行一系列工作后产生一个或多个工作进程。主进程主要进行Nginx配置文件解析,数据结构初始化,模块配置和注册,信号处理,网络监听生成,工作进程生成和管理工作;工作进程主要进行进程初始化,模块调用和请求处理等工作,是Nginx提供服务的主体。Nginx服务器将接收到的Web请求通过代理转发到后端服务器,由后端服务器进行数据处理和页面组织,然后将结果返回。

工作进程的主要功能是与外界通信并对内部的其他进程进行管理:

  • 读取Nginx配置文件
  • 建立、绑定、关闭socket
  • 按配置生成、结束和结束工作进程
  • 接收外界指令,从而重启、升级及退出服务器等指令
  • 不中断服务,实现平滑重启,应用新配置
  • 不中断服务,实现平滑升级,升级失败进行回滚处理
  • 开启日志文件,获取文件描述符
  • 编译和处理Perl脚本

要控制nginx,只需要通过kill向master进程发送信号就行了。比如kill -HUP pid,则是告诉nginx,从容地重启nginx,我们一般用这个信号来重启nginx,或重新加载配置,因为是从容地重启,因此服务是不中断的。master进程在接收到HUP信号后是怎么做的呢?首先master进程在接到信号后,会先重新加载配置文件,然后再启动新的worker进程,并向所有老的worker进程发送信号,告诉他们可以光荣退休了。新的worker在启动后,就开始接收新的请求,而老的worker在收到来自master的信号后,就不再接收新的请求,并且在当前进程中的所有未处理完的请求处理完成后,再退出。当然,直接给master进程发送信号,这是比较老的操作方式,nginx在0.8版本之后,引入了一系列命令行参数,来方便我们管理。比如,./nginx -s reload,就是来重启nginx,./nginx -s stop,就是来停止nginx的运行。如何做到的呢?我们还是拿reload来说,我们看到,执行命令时,我们是启动一个新的nginx进程,而新的nginx进程在解析到reload参数后,就知道我们的目的是控制nginx来重新加载配置文件了,它会向master进程发送信号,然后接下来的动作,就和我们直接向master进程发送信号一样了。

工作进程的生成数量可以通过Nginx配置文件指定:

  • 接收客户端请求
  • 将请求依次送入各个功能模块进行过滤处理
  • IO调用,获取响应数据
  • 与后端服务器通信,接收后端服务器处理结果
  • 数据缓存,访问魂村索引,查询、调用缓存数据
  • 发送请求结果,响应客户端请求
  • 接收主进程指令,比如重启、升级和退出指令

Nginx中进程模型的通信

Nginx服务器启动以后,主进程根据配置文件决定生成的工作进程的数量,然后建立一张全局的工作进程表用于存放所有当前未退出的所有工作进程。主进程生成工作进程后,将新生成的工作进程加入工作进程表,建立一个单向管道并将其传递给该工作进程。该管道与普通的管道不同,它是由主进程指向工作进程的单向管道,包含了主进程向工作进程发出的指令、工作进程ID、工作进程在工作进程表中的索引和必要的文件描述符等信息。为了实现工作进程之间交互的目的,主进程在生成工作进程之后,在工作进程表中进行遍历,将该新进程的ID以及针对该进程建立的管道句柄传递给工作进程表中的其他进程,为工作进程之间的交互准备。每个工作进程捕获管道中可读事件,根据指令采取响应的措施。

Nginx反向代理和正向代理

正向代理:是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。正向代理的常见用途如下:

  • 访问原来无法访问的资源,如google
  • 可以做缓存,加速访问资源
  • 对客户端访问授权,上网进行认证
  • 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理:实际运行方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理的常见用于如下:

  • 保证内网的安全,可以使用反向代理提供WAF功能,阻止web攻击大型网站,通常将反向代理作为公网访问地址,Web服务器是内网
  • 负载均衡,通过反向代理服务器来优化网站的负载

什么是C10K问题?

指无法同时处理大量客户端(10,000)的网络套接字

Nginx为什么做动静资源分离?

动态资源、静态资源分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,提高用户访问静态代码的速度,降低对后台应用的访问次数。

Nginx的应用场景

  • HTTP服务器。Nginx是一个HTTP服务可以独立提供HTTP服务。可以做网页静态服务器。
  • 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
  • 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做负载均衡,并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。
  • Nginx搭建企业级api接口网关,可以解决跨域问题。
  • 安全架构中可以使用Nginx防ddos流量攻击。

Nginx与LVS的对比

  • Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能
  • Nginx对网络稳定性的依赖较小,Ping得通即可,同时还能区分内外网;LVS就比较依赖于网络环境,LVS需要向托管商至少申请多一个ip来做Visual IP
  • Nginx安装和配置比较简单;LVS的安装和配置、测试就要花比较长的时间
  • Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级
  • Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点;LVS的原理使其不能重发请求
  • Nginx对请求的异步处理可以帮助节点服务器减轻负载

LVS

LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案。终端互联网用户从外部访问公司的外部负载均衡服务器,终端用户的Web请求会发送给LVS调度器,调度器根据自己预设的算法决定将该请求发送给后端的某台Web服务器。LVS工作模式分为NAT模式、TUN模式、以及DR模式。

LVS的IP负载均衡技术实现过程

LVS 的 IP 负载均衡技术是通过 IPVS 模块来实现的,IPVS是LVS集群系统的核心软件,它的主要作用是:安装在 Director Server 上,同时在Director Server上虚拟出一个IP地址,用户必须通 过这个虚拟的 IP 地址访问服务器。这个虚拟 IP 一般称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达负载调度器,然后由负载调度器从Real Server列表中选取一个服务节点响应用户的请求。在用户的请求到达负载调度器后,调度器如何将请求发送到提供服务的 Real Server节点,而Real Server节点如何返回数据给用户,是IPVS实现的重点技术。

基于NAT的负载均衡

NAT(Network Address Translation)即网络地址转换,其作用是通过数据报头的修改,使得位于企业内部的私有IP地址可以访问外网,以及外部用用户可以访问位于公司内部的私有IP主机。

  • 客户端将请求发往前端的负载均衡器,请求报文源地址是CIP(客户端IP),后面统称为CIP),目标地址为VIP(负载均衡器前端地址,后面统称为 VIP)
  • 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将客户端请求报文的目 标地址改为了后端服务器的 RIP 地址并将报文根据算法发送出去
  • 报文送到 Real Server 后,由于报文的目标地址是自己,所以会响应该请求,并将响应报文返还 给 LVS
  • 然后 lvs 将此报文的源地址修改为本机并发送给客户端

NAT 技术将请求的报文和响应的报文都需要通过负载均衡器进行地址改写,因此网站访问量比较大的时候负载均衡器负载均衡调度器有比较大的瓶颈。负载均衡器只需要配置一个公网IP即可,每台内部服务器的网关地址必须是负载均衡器的内网地址。NAT技术支持IP地址和端口转换,即用户请求的端口和真实服务器的端口可以不同。

优缺点:

  • 集群中的物理服务器可以使用任何支持 TCP/IP 操作系统,只有负载均衡器需要一个合法的 IP 地址
  • 扩展性有限。当服务器节点(普通PC服务器)增长过多时,负载均衡器将成为整个系统的瓶颈,因 为所有的请求包和应答包的流向都经过负载均衡器。当服务器节点过多时,大量的数据包都交汇在负载均衡器,速度就会变慢!

基于TUN的LVS负载均衡

在LVS(NAT)模式的集群环境中,由于所有的数据请求及响应的数据包都需要经过LVS调度器转发,如果后端服务器的数量大于10台,则调度器就会成为整个集群环境的瓶颈。我们知道,数据请求包往往远小于响应数据包的大小。因为响应数据包中包含有客户需要的具体数据,所以LVS(TUN)的思路就是将请求与响应数据分离,让调度器仅处理数据请求,而让真实服务器响应数据包直接返回给客户端。

  • 客户端将请求发往前端的负载均衡器,请求报文源地址是 CIP,目标地址为 VIP
  • 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将在客户端请求报文的首部再封装一层 IP 报文,将源地址改为 DIP,目标地址改为 RIP,并将此包发送给 RS
  • RS 收到请求报文后,会首先拆开第一层封装,然后发现里面还有一层 IP 首部的目标地址是自己 lo 接口上的 VIP,所以会处理次请求报文,并将响应报文通过lo接口送给eth0网卡直接发送给客户端

优缺点:

  • 负载均衡器只负责将请求包分发给后端节点服务器,而RS将应答包直接发给用户。所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,就能处理很巨大的请求量,这种方式,一台负载均衡器能够为很多RS进行分发。而且跑在公网上就能进行不同地域的分发
  • 隧道模式的 RS 节点需要合法 IP,这种方式需要所有的服务器支持”IP Tunneling”(IP Encapsulation)协议,服务器可能只局限在部分 Linux 系统上

基于DR的LVS负载均衡

在LVS(TUN)模式下,由于需要在LVS调度器与真实服务器之间创建隧道连接,这同样会增加服务器的负担。与LVS(TUN)类似,DR模式也叫直接路由模式,其体系结构如图4所示,该模式中LVS依然仅承担数据的入站请求以及根据算法选出合理的真实服务器,最终由后端真实服务器负责将响应数据包发送返回给客户端。与隧道模式不同的是,直接路由模式(DR模式)要求调度器与后端服务器必须在同一个局域网内,VIP地址需要在调度器与后端所有的服务器间共享,因为最终的真实服务器给客户端回应数据包时需要设置源IP为VIP地址,目标IP为客户端IP,这样客户端访问的是调度器的VIP地址,回应的源地址也依然是该VIP地址(真实服务器上的VIP),客户端是感觉不到后端服务器存在的。由于多台计算机都设置了同样一个VIP地址,所以在直接路由模式中要求调度器的VIP地址是对外可见的,客户端需要将请求数据包发送到调度器主机,而所有的真实服务器的VIP地址必须配置在Non-ARP的网络设备上,也就是该网络设备并不会向外广播自己的MAC及对应的IP地址,真实服务器的VIP对外界是不可见的,但真实服务器却可以接受目标地址VIP的网络请求,并在回应数据包时将源地址设置为该VIP地址。调度器根据算法在选出真实服务器后,在不修改数据报文的情况下,将数据帧的MAC地址修改为选出的真实服务器的MAC地址,通过交换机将该数据帧发给真实服务器。整个过程中,真实服务器的VIP不需要对外界可见。

  • 客户端将请求发往前端的负载均衡器,请求报文源地址是 CIP,目标地址为 VIP
  • 负载均衡器收到报文后,发现请求的是在规则里面存在的地址,那么它将客户端请求报文的源MAC地址改为自己DIP的MAC地址,目标MAC改为了RIP的MAC地址,并将此包发送给RS
  • RS 发现请求报文中的目的 MAC 是自己,就会将次报文接收下来,处理完请求报文后,将响应 报文通过 lo 接口送给 eth0 网卡直接发送给客户端

优缺点:

  • 和 TUN(隧道模式)一样,负载均衡器也只是分发请求,应答包通过单独的路由方法返回给客户端。与VS-TUN相比,VS-DR这种实现方式不需要隧道结构,因此可以使用大多数操作系统做为物理服务器
  • DR 模式的效率很高,但是配置稍微复杂一点,因此对于访问量不是特别大的公司可以用 haproxy/nginx取代。日1000-2000W PV或者并发请求1万一下都可以考虑用haproxy/nginx
  • 所有RS节点和调度器LB只能在一个局域网里面

LVS实现的调度算法

  • 轮询调度(Round-Robin Scheduling)
  • 加权轮询调度(Weighted Round-Robin Scheduling)
  • 最小连接调度(Least-Connection Scheduling)
  • 加权最小连接调度(Weighted Least-Connection Scheduling)
  • 基于局部性的最少链接(Locality-Based Least Connections Scheduling)
  • 带复制的基于局部性最少链接(Locality-Based Least Connections with Replication Scheduling)
  • 目标地址散列调度(Destination Hashing Scheduling)
  • 源地址散列调度(Source Hashing Scheduling)
  • 最短预期延时调度(Shortest Expected Delay Scheduling)
  • 不排队调度(Never Queue Scheduling)

KeepAlived

keepalived是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。如果有一台web服务器死机,或工作出现故障,Keepalived将有故障的web服务器从系统中剔除,当web服务器工作正常后Keepalived自动将web服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的web服务器。

负载均衡的技术选型

现在对网络负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术。

第一阶段

利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。

第二阶段

随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,本人在某项目中使用过,性价比也远高于F5,商用首选,但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。

第三阶段

这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。

最终形成比较理想的基本架构为:Array/LVS —> Nginx/Haproxy —> Squid/Varnish —> AppServer。


Similar Posts

Comments