前言:nginx
以前在山西的项目上使用的是lvs下的NAT模式,但另外两个模式并无涉及,今天系统的整理下关于负载均衡的相关理论与lvs各模式的相关优势与不足,知其然与因此然,然后能针对性的应用:算法
在业务初期,咱们通常会先使用单台服务器对外提供服务。随着业务流量愈来愈大,单台服务器不管如何优化,不管采用多好的硬件,总会有性能天花板,当单服务器的性能没法知足业务需求时,就须要把多台服务器组成集群系统提升总体的处理性能。不过咱们要使用统一的入口方式对外提供服务,因此须要一个流量调度器经过均衡的算法,将用户大量的请求均衡地分发到后端集群不一样的服务器上。这就是咱们后边要说的 负载均衡。windows
提升了服务的总体性能后端
提升了服务的扩展性缓存
提升了服务的高可用性安全
广义上的负载均衡器大概能够分为 3 类,包括:DNS 方式实现负载均衡、硬件负载均衡、软件负载均衡。服务器
DNS 实现负载均衡是最基础简单的方式。一个域名经过 DNS 解析到多个 IP,每一个 IP 对应不一样的服务器实例,这样就完成了流量的调度,虽然没有使用常规的负载均衡器,但也的确完成了简单负载均衡的功能。网络
经过 DNS 实现负载均衡的方式的优势:架构
实现简单,成本低,无需本身开发或维护负载均衡设备,负载均衡
经过 DNS 实现负载均衡的方式的缺点:
服务器故障切换延迟大
服务器升级不方便。咱们知道 DNS 与用户之间是层层的缓存,即使是在故障发生时及时经过 DNS 修改或摘除故障服务器,但中间因为通过运营商的 DNS 缓存,且缓存颇有可能不遵循 TTL 规则,致使 DNS 生效时间变得很是缓慢,有时候一天后还会有些许的请求流量。
流量调度不均衡,粒度太粗
DNS 调度的均衡性,受地区运营商 LocalDNS 返回 IP 列表的策略有关系,有的运营商并不会轮询返回多个不一样的 IP 地址。另外,某个运营商 LocalDNS 背后服务了多少用户,这也会构成流量调度不均的重要因素。
流量分配策略比较简单,支持的算法较少。DNS 通常只支持 RR 的轮询方式,流量分配策略比较简单,不支持权重、Hash 等调度算法。
DNS 支持的 IP 列表有限制
咱们知道 DNS 使用 UDP 报文进行信息传递,每一个 UDP 报文大小受链路的 MTU 限制,因此报文中存储的 IP 地址数量也是很是有限的,阿里 DNS 系统针对同一个域名支持配置 10 个不一样的 IP 地址。
注:实际上生产环境中不多使用这种方式来实现负载均衡,毕竟缺点很明显。文中之因此描述 DNS 负载均衡方式,是为了可以更清楚地解释负载均衡的概念。一些大公司通常也会利用 DNS 来实现地理级别的负载均衡,实现就近访问,提升访问速度,这种方式通常是入口流量的基础负载均衡,下层会有更专业的负载均衡设备实现的负载架构。
硬件负载均衡是经过专门的硬件设备来实现负载均衡功能,相似于交换机、路由器,是一个负载均衡专用的网络设备。目前业界典型的硬件负载均衡设备有两款:F5 和 A10。这类设备性能强劲、功能强大,但价格很是昂贵,通常只有 “土豪” 公司才会使用此类设备,普通业务量级的公司通常负担不起,二是业务量没那么大,用这些设备也是浪费。
硬件负载均衡的优势:
功能强大:全面支持各层级的负载均衡,支持全面的负载均衡算法。
性能强大:性能远超常见的软件负载均衡器。
稳定性高:商用硬件负载均衡,通过了良好的严格测试,通过大规模使用,稳定性高。
安全防御:除了具有负载均衡外,还具有防火墙、防 DDoS 攻击等安全功能,貌似还支持 SNAT 功能。
硬件负载均衡的缺点:
价格昂贵,就是贵。
扩展性差,没法进行扩展和定制。
调试和维护比较麻烦,须要专业人员。
软件负载均衡,能够在普通的服务器上运行负载均衡软件,实现负载均衡功能。目前常见的有 Nginx、HAproxy、LVS,了解到不少大公司使用的 LVS 都是定制版的,作过不少性能方面的优化,比开源版本性能会高出不少,
目前较为熟悉的负载均衡软件是 LVS,且大部分中小型公司使用开源的 LVS 足够知足业务需求;
软件负载均衡的优势:
简单:不管是部署仍是维护都比较简单。
便宜:买个 Linux 服务器,装上软件便可。
灵活:4 层和 7 层负载均衡能够根据业务进行选择;也能够根据业务特色,比较方便进行扩展和定制功能。
LVS 是基于 Linux 内核中 netfilter 框架实现的负载均衡系统,因此要学习 LVS 以前必需要先简单了解 netfilter 基本工做原理。netfilter 其实很复杂也很重要,平时咱们说的 Linux 防火墙就是 netfilter,不过咱们平时操做的都是 iptables,iptables 只是用户空间编写和传递规则的工具而已,真正工做的是 netfilter。经过下图能够简单了解下 netfilter 的工做机制:
netfilter 是内核态的 Linux 防火墙机制,做为一个通用、抽象的框架,提供了一整套的 hook 函数管理机制,提供诸如数据包过滤、网络地址转换、基于协议类型的链接跟踪的功能。
通俗点讲,就是 netfilter 提供一种机制,能够在数据包流通过程中,根据规则设置若干个关卡(hook 函数)来执行相关的操做。netfilter 总共设置了 5 个点,包括:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
PREROUTING :刚刚进入网络层,还未进行路由查找的包,经过此处
INPUT :经过路由查找,肯定发往本机的包,经过此处
FORWARD :经路由查找后,要转发的包,在POST_ROUTING以前
OUTPUT :从本机进程刚发出的包,经过此处
POSTROUTING :进入网络层已经通过路由查找,肯定转发,将要离开本设备的包,经过此处
数据包大体流经路径:
当一个数据包进入网卡,通过链路层以后进入网络层就会到达 PREROUTING,接着根据目标 IP 地址进行路由查找,若是目标 IP 是本机,数据包继续传递到 INPUT 上,通过协议栈后根据端口将数据送到相应的应用程序;应用程序处理请求后将响应数据包发送到 OUTPUT 上,最终经过 POSTROUTING 后发送出网卡。若是目标 IP 不是本机,并且服务器开启了 forward 参数,就会将数据包递送给 FORWARD 上,最后经过 POSTROUTING 后发送出网卡。
Lvs是软件负载均衡,LVS 是基于 netfilter 框架,主要工做于 INPUT 链上,在 INPUT 上注册 ip_vs_in HOOK 函数,进行 IPVS 主流程,大概原理如图所示:
当用户访问网站时,用户数据经过层层网络,最后经过交换机进入 LVS 服务器网卡,并进入内核网络层。进入 PREROUTING 后通过路由查找,肯定访问的目的 VIP 是本机 IP 地址,因此数据包进入到 INPUT 链上,IPVS 是工做在 INPUT 链上,会根据访问的 vip+port 判断请求是否 IPVS 服务,若是是则调用注册的 IPVS HOOK 函数,进行 IPVS 相关主流程,强行修改数据包的相关数据,并将数据包发往 POSTROUTING 链上。POSTROUTING 上收到数据包后,根据目标 IP 地址(后端服务器),经过路由选路,将数据包最终发日后端的服务器上。
LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案;
开源 LVS 版本有 3 种工做模式,每种模式工做原理大相径庭,说各类模式都有本身的优缺点,分别适合不一样的应用场景,不过最终本质的功能都是能实现均衡的流量调度和良好的扩展性。主要包括如下三种模式
DR 模式
NAT 模式
Tunnel 模式
相关术语介绍
CIP:Client IP,表示的是客户端 IP 地址。
VIP:Virtual IP,表示负载均衡对外提供访问的 IP 地址,通常负载均衡 IP 都会经过 Virtual IP 实现高可用。
RIP:RealServer IP,表示负载均衡后端的真实服务器 IP 地址。
DIP:Director IP,表示负载均衡与后端服务器通讯的 IP 地址。
CMAC:客户端的 MAC 地址,准确的应该是 LVS 链接的路由器的 MAC 地址。
VMAC:负载均衡 LVS 的 VIP 对应的 MAC 地址。
DMAC:负载均衡 LVS 的 DIP 对应的 MAC 地址。
RMAC:后端真实服务器的 RIP 地址对应的 MAC 地址。
其实 DR 是最经常使用的工做模式,由于它的强大的性能。下边以一次请求和响应数据流的过程来描述 DR 模式的具体原理:
第一步:
当客户端请求网站主页,通过 DNS 解析到 IP 后,向网站服务器发送请求数据,数据包通过层层网络到达网站负载均衡 LVS 服务器,到达 LVS 网卡时的数据包:源 IP 是客户端 IP 地址 CIP,目的 IP 是新浪对外的服务器 IP 地址,也就是 VIP;此时源 MAC 地址是 CMAC,实际上是 LVS 链接的路由器的 MAC 地址(为了容易理解记为 CMAC),目标 MAC 地址是 VIP 对应的 MAC,记为 VMAC。
第二步:
数据包到达网卡后,通过链路层到达 PREROUTING 位置(刚进入网络层),查找路由发现目的 IP 是 LVS 的 VIP,就会递送到 INPUT 链上,此时数据包 MAC、IP、Port 都没有修改。
第三步:
数据包到达 INPUT 链,INPUT 是 LVS 主要工做的位置。此时 LVS 会根据目的 IP 和 Port 来确认是不是 LVS 定义的服务,若是是定义过的 VIP 服务,就会根据配置的 Service 信息,从 RealServer 中选择一个做为后端服务器 RS1,而后以 RS1 做为目标查找 Out 方向的路由,肯定下一跳信息以及数据包要经过哪一个网卡发出。最后将数据包经过 INET_HOOK 到 OUTPUT 链上(Out 方向刚进入网络层)。
第四步:
数据包经过 POSTROUTING 链后,从网络层转到链路层,将目的 MAC 地址修改成 RealServer 服务器 MAC 地址,记为 RMAC;而源 MAC 地址修改成 LVS 与 RS 同网段的 selfIP 对应的 MAC 地址,记为 DMAC。此时,数据包经过交换机转发给了 RealServer 服务器
第五步:
请求数据包到达 RealServer 服务器后,链路层检查目的 MAC 是本身网卡地址。到了网络层,查找路由,目的 IP 是 VIP(lo 上配置了 VIP),断定是本地主机的数据包,通过协议栈后拷贝至应用程序(好比这里是 nginx 服务器),nginx 响应请求后,产生响应数据包。以目的 VIP 为 dst 查找 Out 路由,肯定下一跳信息和发送网卡设备信息,发送数据包。此时数据包源、目的 IP 分别是 VIP、CIP,而源 MAC 地址是 RS1 的 RMAC,目的 MAC 是下一跳(路由器)的 MAC 地址,记为 CMAC(为了容易理解,记为 CMAC)。而后数据包经过 RS 相连的路由器转发给真正客户端。
DR模式的优缺点:
DR 模式的优势
a. 响应数据不通过 lvs,性能高
b. 对数据包修改小,信息保存完整(携带客户端源 IP)
DR 模式的缺点
a. lvs 与 rs 必须在同一个物理网络(不支持跨机房)
b. rs 上必须配置 lo 和其它内核参数
c. 不支持端口映射
DR 模式的使用场景
若是对性能要求很是高,能够首选 DR 模式,并且能够透传客户端源 IP 地址
第一步:
用户请求数据包通过层层网络,到达 lvs 网卡,此时数据包源 IP 是 CIP,目的 IP 是 VIP。
通过网卡进入网络层 prerouting 位置,根据目的 IP 查找路由,确认是本机 IP,将数据包转发到 INPUT 上,此时源、目的 IP 都未发生变化。
第二步:
到达 lvs 后,经过目的 IP 和目的 port 查找是否为 IPVS 服务。如果 IPVS 服务,则会选择一个 RS 做为后端服务器,将数据包目的 IP 修改成 RIP,并以 RIP 为目的 IP 查找路由信息,肯定下一跳和出口信息,将数据包转发至 output 上。
第三步:
修改后的数据包通过 postrouting 和链路层处理后,到达 RS 服务器,此时的数据包源 IP 是 CIP,目的 IP 是 RIP。
第四步:
到达 RS 服务器的数据包通过链路层和网络层检查后,被送往用户空间 nginx 程序。nginx 程序处理完毕,发送响应数据包,因为 RS 上默认网关配置为 lvs 设备 IP,因此 nginx 服务器会将数据包转发至下一跳,也就是 lvs 服务器。此时数据包源 IP 是 RIP,目的 IP 是 CIP。
第五步:
lvs 服务器收到 RS 响应数据包后,根据路由查找,发现目的 IP 不是本机 IP,且 lvs 服务器开启了转发模式,因此将数据包转发给 forward 链,此时数据包未做修改。
第六步:
lvs 收到响应数据包后,根据目的 IP 和目的 port 查找服务和链接表,将源 IP 改成 VIP,经过路由查找,肯定下一跳和出口信息,将数据包发送至网关,通过复杂的网络到达用户客户端,最终完成了一次请求和响应的交互。
NAT模式的优缺点:
NAT 模式优势
a. 可以支持 windows 操做系统
b. 支持端口映射。若是 rs 端口与 vport 不一致,lvs 除了修改目的 IP,也会修改 dport 以支持端口映射。
NAT 模式缺点
a. 后端 RS 须要配置网关
b. 双向流量对 lvs 负载压力比较大
NAT 模式的使用场景
若是你是 windows 系统,使用 lvs 的话,则必须选择 NAT 模式了。
第一步:
用户请求数据包通过多层网络,到达 lvs 网卡,此时数据包源 IP 是 cip,目的 ip 是 vip。
第二步:
通过网卡进入网络层 prerouting 位置,根据目的 ip 查找路由,确认是本机 ip,将数据包转发到 input 链上,到达 lvs,此时源、目的 ip 都未发生变化。
第三步:
到达 lvs 后,经过目的 ip 和目的 port 查找是否为 IPVS 服务。如果 IPVS 服务,则会选择一个 rs 做为后端服务器,以 rip 为目的 ip 查找路由信息,肯定下一跳、dev 等信息,而后 IP 头部前边额外增长了一个 IP 头(以 dip 为源,rip 为目的 ip),将数据包转发至 output 上。
第四步:
数据包根据路由信息经最终通过 lvs 网卡,发送至路由器网关,经过网络到达后端服务器。
第五步:
后端服务器收到数据包后,ipip 模块将 Tunnel 头部卸载,正常看到的源 ip 是 cip,目的 ip 是 vip,因为在 tunl0 上配置 vip,路由查找后断定为本机 ip,送往应用程序。应用程序 nginx 正常响应数据后以 vip 为源 ip,cip 为目的 ip 数据包发送出网卡,最终到达客户端。
Tunnel 模式的优势
a. 单臂模式,对 lvs 负载压力小
b. 对数据包修改较小,信息保存完整
c. 可跨机房(不过在国内实现有难度)
Tunnel 模式的缺点
a. 须要在后端服务器安装配置 ipip 模块
b. 须要在后端服务器 tunl0 配置 vip
c. 隧道头部的加入可能致使分片,影响服务器性能
d. 隧道头部 IP 地址固定,后端服务器网卡 hash 可能不均
e. 不支持端口映射
Tunnel 模式的使用场景
理论上,若是对转发性能要求较高,且有跨机房需求,Tunnel 多是较好的选择。
轮询调度(Round Robin 简称'RR')算法就是按依次循环的方式将请求调度到不一样的服务器上,该算法最大的特色就是实现简单。轮询算法假设全部的服务器处理请求的能力都同样的,调度器会将全部的请求平均分配给每一个真实服务器。
加权轮询(Weight Round Robin 简称'WRR')算法主要是对轮询算法的一种优化与补充,LVS会考虑每台服务器的性能,并给每台服务器添加一个权值,若是服务器A的权值为1,服务器B的权值为2,则调度器调度到服务器B的请求会是服务器A的两倍。权值越高的服务器,处理的请求越多。
最小链接调度(Least Connections 简称'LC')算法是把新的链接请求分配到当前链接数最小的服务器。最小链接调度是一种动态的调度算法,它经过服务器当前活跃的链接数来估计服务器的状况。调度器须要记录各个服务器已创建链接的数目,当一个请求被调度到某台服务器,其链接数加1;当链接中断或者超时,其链接数减1。
(集群系统的真实服务器具备相近的系统性能,采用最小链接调度算法能够比较好地均衡负载。)
加权最少链接(Weight Least Connections 简称'WLC')算法是最小链接调度的超集,各个服务器相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员能够动态地设置服务器的权值。加权最小链接调度在调度新链接时尽量使服务器的已创建链接数和其权值成比例。调度器能够自动问询真实服务器的负载状况,并动态地调整其权值。
基于局部的最少链接调度(Locality-Based Least Connections 简称'LBLC')算法是针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,由于在Cache集群客户请求报文的目标IP地址是变化的。这里假设任何后端服务器均可以处理任一请求,算法的设计目标是在服务器的负载基本平衡状况下,将相同目标IP地址的请求调度到同一台服务器,来提升各台服务器的访问局部性和Cache命中率,从而提高整个集群系统的处理能力。LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工做负载,则使用'最少链接'的原则选出一个可用的服务器,将请求发送到服务器。
带复制的基于局部性的最少链接(Locality-Based Least Connections with Replication 简称'LBLCR')算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统,它与LBLC算法不一样之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。按'最小链接'原则从该服务器组中选出一一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按'最小链接'原则从整个集群中选出一台服务器,将该服务器加入到这个服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以下降复制的程度。
目标地址散列调度(Destination Hashing 简称'DH')算法先根据请求的目标IP地址,做为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且并未超载,将请求发送到该服务器,不然返回空。
源地址散列调度(Source Hashing 简称'SH')算法先根据请求的源IP地址,做为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且并未超载,将请求发送到该服务器,不然返回空。它采用的散列函数与目标地址散列调度算法的相同,它的算法流程与目标地址散列调度算法的基本类似。
最短的指望的延迟调度(Shortest Expected Delay 简称'SED')算法基于WLC算法。举个例子吧,ABC三台服务器的权重分别为1、2、3 。那么若是使用WLC算法的话一个新请求进入时它可能会分给ABC中的任意一个。使用SED算法后会进行一个运算
A:(1+1)/1=2 B:(1+2)/2=3/2 C:(1+3)/3=4/3 就把请求交给得出运算结果最小的服务器。
最少队列调度(Never Queue 简称'NQ')算法,无需队列。若是有realserver的链接数等于0就直接分配过去,不须要在进行SED运算。
在业务初期,咱们通常会先使用单台服务器对外提供服务。随着业务流量愈来愈大,单台服务器不管如何优化,不管采用多好的硬件,总会有性能天花板,当单服务器的性能没法知足业务需求时,就须要把多台服务器组成集群系统提升总体的处理性能。不过咱们要使用统一的入口方式对外提供服务,因此须要一个流量调度器经过均衡的算法,将用户大量的请求均衡地分发到后端集群不一样的服务器上。这就是咱们后边要说的 负载均衡。
提升了服务的总体性能
提升了服务的扩展性
提升了服务的高可用性
广义上的负载均衡器大概能够分为 3 类,包括:DNS 方式实现负载均衡、硬件负载均衡、软件负载均衡。
DNS 实现负载均衡是最基础简单的方式。一个域名经过 DNS 解析到多个 IP,每一个 IP 对应不一样的服务器实例,这样就完成了流量的调度,虽然没有使用常规的负载均衡器,但也的确完成了简单负载均衡的功能。
经过 DNS 实现负载均衡的方式的优势:
实现简单,成本低,无需本身开发或维护负载均衡设备,
经过 DNS 实现负载均衡的方式的缺点:
服务器故障切换延迟大
服务器升级不方便。咱们知道 DNS 与用户之间是层层的缓存,即使是在故障发生时及时经过 DNS 修改或摘除故障服务器,但中间因为通过运营商的 DNS 缓存,且缓存颇有可能不遵循 TTL 规则,致使 DNS 生效时间变得很是缓慢,有时候一天后还会有些许的请求流量。
流量调度不均衡,粒度太粗
DNS 调度的均衡性,受地区运营商 LocalDNS 返回 IP 列表的策略有关系,有的运营商并不会轮询返回多个不一样的 IP 地址。另外,某个运营商 LocalDNS 背后服务了多少用户,这也会构成流量调度不均的重要因素。
流量分配策略比较简单,支持的算法较少。DNS 通常只支持 RR 的轮询方式,流量分配策略比较简单,不支持权重、Hash 等调度算法。
DNS 支持的 IP 列表有限制
咱们知道 DNS 使用 UDP 报文进行信息传递,每一个 UDP 报文大小受链路的 MTU 限制,因此报文中存储的 IP 地址数量也是很是有限的,阿里 DNS 系统针对同一个域名支持配置 10 个不一样的 IP 地址。
注:实际上生产环境中不多使用这种方式来实现负载均衡,毕竟缺点很明显。文中之因此描述 DNS 负载均衡方式,是为了可以更清楚地解释负载均衡的概念。一些大公司通常也会利用 DNS 来实现地理级别的负载均衡,实现就近访问,提升访问速度,这种方式通常是入口流量的基础负载均衡,下层会有更专业的负载均衡设备实现的负载架构。
硬件负载均衡是经过专门的硬件设备来实现负载均衡功能,相似于交换机、路由器,是一个负载均衡专用的网络设备。目前业界典型的硬件负载均衡设备有两款:F5 和 A10。这类设备性能强劲、功能强大,但价格很是昂贵,通常只有 “土豪” 公司才会使用此类设备,普通业务量级的公司通常负担不起,二是业务量没那么大,用这些设备也是浪费。
硬件负载均衡的优势:
功能强大:全面支持各层级的负载均衡,支持全面的负载均衡算法。
性能强大:性能远超常见的软件负载均衡器。
稳定性高:商用硬件负载均衡,通过了良好的严格测试,通过大规模使用,稳定性高。
安全防御:除了具有负载均衡外,还具有防火墙、防 DDoS 攻击等安全功能,貌似还支持 SNAT 功能。
硬件负载均衡的缺点:
价格昂贵,就是贵。
扩展性差,没法进行扩展和定制。
调试和维护比较麻烦,须要专业人员。
软件负载均衡,能够在普通的服务器上运行负载均衡软件,实现负载均衡功能。目前常见的有 Nginx、HAproxy、LVS,了解到不少大公司使用的 LVS 都是定制版的,作过不少性能方面的优化,比开源版本性能会高出不少,
目前较为熟悉的负载均衡软件是 LVS,且大部分中小型公司使用开源的 LVS 足够知足业务需求;
软件负载均衡的优势:
简单:不管是部署仍是维护都比较简单。
便宜:买个 Linux 服务器,装上软件便可。
灵活:4 层和 7 层负载均衡能够根据业务进行选择;也能够根据业务特色,比较方便进行扩展和定制功能。
LVS 是基于 Linux 内核中 netfilter 框架实现的负载均衡系统,因此要学习 LVS 以前必需要先简单了解 netfilter 基本工做原理。netfilter 其实很复杂也很重要,平时咱们说的 Linux 防火墙就是 netfilter,不过咱们平时操做的都是 iptables,iptables 只是用户空间编写和传递规则的工具而已,真正工做的是 netfilter。经过下图能够简单了解下 netfilter 的工做机制:
netfilter 是内核态的 Linux 防火墙机制,做为一个通用、抽象的框架,提供了一整套的 hook 函数管理机制,提供诸如数据包过滤、网络地址转换、基于协议类型的链接跟踪的功能。
通俗点讲,就是 netfilter 提供一种机制,能够在数据包流通过程中,根据规则设置若干个关卡(hook 函数)来执行相关的操做。netfilter 总共设置了 5 个点,包括:PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
PREROUTING :刚刚进入网络层,还未进行路由查找的包,经过此处
INPUT :经过路由查找,肯定发往本机的包,经过此处
FORWARD :经路由查找后,要转发的包,在POST_ROUTING以前
OUTPUT :从本机进程刚发出的包,经过此处
POSTROUTING :进入网络层已经通过路由查找,肯定转发,将要离开本设备的包,经过此处
数据包大体流经路径:
当一个数据包进入网卡,通过链路层以后进入网络层就会到达 PREROUTING,接着根据目标 IP 地址进行路由查找,若是目标 IP 是本机,数据包继续传递到 INPUT 上,通过协议栈后根据端口将数据送到相应的应用程序;应用程序处理请求后将响应数据包发送到 OUTPUT 上,最终经过 POSTROUTING 后发送出网卡。若是目标 IP 不是本机,并且服务器开启了 forward 参数,就会将数据包递送给 FORWARD 上,最后经过 POSTROUTING 后发送出网卡。
Lvs是软件负载均衡,LVS 是基于 netfilter 框架,主要工做于 INPUT 链上,在 INPUT 上注册 ip_vs_in HOOK 函数,进行 IPVS 主流程,大概原理如图所示:
当用户访问网站时,用户数据经过层层网络,最后经过交换机进入 LVS 服务器网卡,并进入内核网络层。进入 PREROUTING 后通过路由查找,肯定访问的目的 VIP 是本机 IP 地址,因此数据包进入到 INPUT 链上,IPVS 是工做在 INPUT 链上,会根据访问的 vip+port 判断请求是否 IPVS 服务,若是是则调用注册的 IPVS HOOK 函数,进行 IPVS 相关主流程,强行修改数据包的相关数据,并将数据包发往 POSTROUTING 链上。POSTROUTING 上收到数据包后,根据目标 IP 地址(后端服务器),经过路由选路,将数据包最终发日后端的服务器上。
LVS(Linux Virtual Server)即Linux虚拟服务器,是由章文嵩博士主导的开源负载均衡项目,目前LVS已经被集成到Linux内核模块中。该项目在Linux内核中实现了基于IP的数据请求负载均衡调度方案;
开源 LVS 版本有 3 种工做模式,每种模式工做原理大相径庭,说各类模式都有本身的优缺点,分别适合不一样的应用场景,不过最终本质的功能都是能实现均衡的流量调度和良好的扩展性。主要包括如下三种模式
DR 模式
NAT 模式
Tunnel 模式
相关术语介绍
CIP:Client IP,表示的是客户端 IP 地址。
VIP:Virtual IP,表示负载均衡对外提供访问的 IP 地址,通常负载均衡 IP 都会经过 Virtual IP 实现高可用。
RIP:RealServer IP,表示负载均衡后端的真实服务器 IP 地址。
DIP:Director IP,表示负载均衡与后端服务器通讯的 IP 地址。
CMAC:客户端的 MAC 地址,准确的应该是 LVS 链接的路由器的 MAC 地址。
VMAC:负载均衡 LVS 的 VIP 对应的 MAC 地址。
DMAC:负载均衡 LVS 的 DIP 对应的 MAC 地址。
RMAC:后端真实服务器的 RIP 地址对应的 MAC 地址。
其实 DR 是最经常使用的工做模式,由于它的强大的性能。下边以一次请求和响应数据流的过程来描述 DR 模式的具体原理:
第一步:
当客户端请求网站主页,通过 DNS 解析到 IP 后,向网站服务器发送请求数据,数据包通过层层网络到达网站负载均衡 LVS 服务器,到达 LVS 网卡时的数据包:源 IP 是客户端 IP 地址 CIP,目的 IP 是新浪对外的服务器 IP 地址,也就是 VIP;此时源 MAC 地址是 CMAC,实际上是 LVS 链接的路由器的 MAC 地址(为了容易理解记为 CMAC),目标 MAC 地址是 VIP 对应的 MAC,记为 VMAC。
第二步:
数据包到达网卡后,通过链路层到达 PREROUTING 位置(刚进入网络层),查找路由发现目的 IP 是 LVS 的 VIP,就会递送到 INPUT 链上,此时数据包 MAC、IP、Port 都没有修改。
第三步:
数据包到达 INPUT 链,INPUT 是 LVS 主要工做的位置。此时 LVS 会根据目的 IP 和 Port 来确认是不是 LVS 定义的服务,若是是定义过的 VIP 服务,就会根据配置的 Service 信息,从 RealServer 中选择一个做为后端服务器 RS1,而后以 RS1 做为目标查找 Out 方向的路由,肯定下一跳信息以及数据包要经过哪一个网卡发出。最后将数据包经过 INET_HOOK 到 OUTPUT 链上(Out 方向刚进入网络层)。
第四步:
数据包经过 POSTROUTING 链后,从网络层转到链路层,将目的 MAC 地址修改成 RealServer 服务器 MAC 地址,记为 RMAC;而源 MAC 地址修改成 LVS 与 RS 同网段的 selfIP 对应的 MAC 地址,记为 DMAC。此时,数据包经过交换机转发给了 RealServer 服务器
第五步:
请求数据包到达 RealServer 服务器后,链路层检查目的 MAC 是本身网卡地址。到了网络层,查找路由,目的 IP 是 VIP(lo 上配置了 VIP),断定是本地主机的数据包,通过协议栈后拷贝至应用程序(好比这里是 nginx 服务器),nginx 响应请求后,产生响应数据包。以目的 VIP 为 dst 查找 Out 路由,肯定下一跳信息和发送网卡设备信息,发送数据包。此时数据包源、目的 IP 分别是 VIP、CIP,而源 MAC 地址是 RS1 的 RMAC,目的 MAC 是下一跳(路由器)的 MAC 地址,记为 CMAC(为了容易理解,记为 CMAC)。而后数据包经过 RS 相连的路由器转发给真正客户端。
DR模式的优缺点:
DR 模式的优势
a. 响应数据不通过 lvs,性能高
b. 对数据包修改小,信息保存完整(携带客户端源 IP)
DR 模式的缺点
a. lvs 与 rs 必须在同一个物理网络(不支持跨机房)
b. rs 上必须配置 lo 和其它内核参数
c. 不支持端口映射
DR 模式的使用场景
若是对性能要求很是高,能够首选 DR 模式,并且能够透传客户端源 IP 地址
第一步:
用户请求数据包通过层层网络,到达 lvs 网卡,此时数据包源 IP 是 CIP,目的 IP 是 VIP。
通过网卡进入网络层 prerouting 位置,根据目的 IP 查找路由,确认是本机 IP,将数据包转发到 INPUT 上,此时源、目的 IP 都未发生变化。
第二步:
到达 lvs 后,经过目的 IP 和目的 port 查找是否为 IPVS 服务。如果 IPVS 服务,则会选择一个 RS 做为后端服务器,将数据包目的 IP 修改成 RIP,并以 RIP 为目的 IP 查找路由信息,肯定下一跳和出口信息,将数据包转发至 output 上。
第三步:
修改后的数据包通过 postrouting 和链路层处理后,到达 RS 服务器,此时的数据包源 IP 是 CIP,目的 IP 是 RIP。
第四步:
到达 RS 服务器的数据包通过链路层和网络层检查后,被送往用户空间 nginx 程序。nginx 程序处理完毕,发送响应数据包,因为 RS 上默认网关配置为 lvs 设备 IP,因此 nginx 服务器会将数据包转发至下一跳,也就是 lvs 服务器。此时数据包源 IP 是 RIP,目的 IP 是 CIP。
第五步:
lvs 服务器收到 RS 响应数据包后,根据路由查找,发现目的 IP 不是本机 IP,且 lvs 服务器开启了转发模式,因此将数据包转发给 forward 链,此时数据包未做修改。
第六步:
lvs 收到响应数据包后,根据目的 IP 和目的 port 查找服务和链接表,将源 IP 改成 VIP,经过路由查找,肯定下一跳和出口信息,将数据包发送至网关,通过复杂的网络到达用户客户端,最终完成了一次请求和响应的交互。
NAT模式的优缺点:
NAT 模式优势
a. 可以支持 windows 操做系统
b. 支持端口映射。若是 rs 端口与 vport 不一致,lvs 除了修改目的 IP,也会修改 dport 以支持端口映射。
NAT 模式缺点
a. 后端 RS 须要配置网关
b. 双向流量对 lvs 负载压力比较大
NAT 模式的使用场景
若是你是 windows 系统,使用 lvs 的话,则必须选择 NAT 模式了。
第一步:
用户请求数据包通过多层网络,到达 lvs 网卡,此时数据包源 IP 是 cip,目的 ip 是 vip。
第二步:
通过网卡进入网络层 prerouting 位置,根据目的 ip 查找路由,确认是本机 ip,将数据包转发到 input 链上,到达 lvs,此时源、目的 ip 都未发生变化。
第三步:
到达 lvs 后,经过目的 ip 和目的 port 查找是否为 IPVS 服务。如果 IPVS 服务,则会选择一个 rs 做为后端服务器,以 rip 为目的 ip 查找路由信息,肯定下一跳、dev 等信息,而后 IP 头部前边额外增长了一个 IP 头(以 dip 为源,rip 为目的 ip),将数据包转发至 output 上。
第四步:
数据包根据路由信息经最终通过 lvs 网卡,发送至路由器网关,经过网络到达后端服务器。
第五步:
后端服务器收到数据包后,ipip 模块将 Tunnel 头部卸载,正常看到的源 ip 是 cip,目的 ip 是 vip,因为在 tunl0 上配置 vip,路由查找后断定为本机 ip,送往应用程序。应用程序 nginx 正常响应数据后以 vip 为源 ip,cip 为目的 ip 数据包发送出网卡,最终到达客户端。
Tunnel 模式的优势
a. 单臂模式,对 lvs 负载压力小
b. 对数据包修改较小,信息保存完整
c. 可跨机房(不过在国内实现有难度)
Tunnel 模式的缺点
a. 须要在后端服务器安装配置 ipip 模块
b. 须要在后端服务器 tunl0 配置 vip
c. 隧道头部的加入可能致使分片,影响服务器性能
d. 隧道头部 IP 地址固定,后端服务器网卡 hash 可能不均
e. 不支持端口映射
Tunnel 模式的使用场景
理论上,若是对转发性能要求较高,且有跨机房需求,Tunnel 多是较好的选择。
轮询调度(Round Robin 简称'RR')算法就是按依次循环的方式将请求调度到不一样的服务器上,该算法最大的特色就是实现简单。轮询算法假设全部的服务器处理请求的能力都同样的,调度器会将全部的请求平均分配给每一个真实服务器。
加权轮询(Weight Round Robin 简称'WRR')算法主要是对轮询算法的一种优化与补充,LVS会考虑每台服务器的性能,并给每台服务器添加一个权值,若是服务器A的权值为1,服务器B的权值为2,则调度器调度到服务器B的请求会是服务器A的两倍。权值越高的服务器,处理的请求越多。
最小链接调度(Least Connections 简称'LC')算法是把新的链接请求分配到当前链接数最小的服务器。最小链接调度是一种动态的调度算法,它经过服务器当前活跃的链接数来估计服务器的状况。调度器须要记录各个服务器已创建链接的数目,当一个请求被调度到某台服务器,其链接数加1;当链接中断或者超时,其链接数减1。
(集群系统的真实服务器具备相近的系统性能,采用最小链接调度算法能够比较好地均衡负载。)
加权最少链接(Weight Least Connections 简称'WLC')算法是最小链接调度的超集,各个服务器相应的权值表示其处理性能。服务器的缺省权值为1,系统管理员能够动态地设置服务器的权值。加权最小链接调度在调度新链接时尽量使服务器的已创建链接数和其权值成比例。调度器能够自动问询真实服务器的负载状况,并动态地调整其权值。
基于局部的最少链接调度(Locality-Based Least Connections 简称'LBLC')算法是针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,由于在Cache集群客户请求报文的目标IP地址是变化的。这里假设任何后端服务器均可以处理任一请求,算法的设计目标是在服务器的负载基本平衡状况下,将相同目标IP地址的请求调度到同一台服务器,来提升各台服务器的访问局部性和Cache命中率,从而提高整个集群系统的处理能力。LBLC调度算法先根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工做负载,则使用'最少链接'的原则选出一个可用的服务器,将请求发送到服务器。
带复制的基于局部性的最少链接(Locality-Based Least Connections with Replication 简称'LBLCR')算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统,它与LBLC算法不一样之处是它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。按'最小链接'原则从该服务器组中选出一一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按'最小链接'原则从整个集群中选出一台服务器,将该服务器加入到这个服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以下降复制的程度。
目标地址散列调度(Destination Hashing 简称'DH')算法先根据请求的目标IP地址,做为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且并未超载,将请求发送到该服务器,不然返回空。
源地址散列调度(Source Hashing 简称'SH')算法先根据请求的源IP地址,做为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且并未超载,将请求发送到该服务器,不然返回空。它采用的散列函数与目标地址散列调度算法的相同,它的算法流程与目标地址散列调度算法的基本类似。
最短的指望的延迟调度(Shortest Expected Delay 简称'SED')算法基于WLC算法。举个例子吧,ABC三台服务器的权重分别为1、2、3 。那么若是使用WLC算法的话一个新请求进入时它可能会分给ABC中的任意一个。使用SED算法后会进行一个运算
A:(1+1)/1=2 B:(1+2)/2=3/2 C:(1+3)/3=4/3 就把请求交给得出运算结果最小的服务器。
最少队列调度(Never Queue 简称'NQ')算法,无需队列。若是有realserver的链接数等于0就直接分配过去,不须要在进行SED运算。