负载均衡在分布式架构中是一个老生常谈的问题,经常会遇到,也经常会需要学习。无论是AWS的ELB,还是阿里的SLB;负载均衡在各大云厂商的产品中都有着举足轻重的地位。今天再来总结下负载均衡的几个重要方面:
负载均衡主要的目的
- 顾名思义,首先就是要平衡负载。请求来的时候,可以转发的对应到后端服务器去执行。
- 实现真正的弹性可伸缩,后端服务器可以根据业务负载来进行弹性伸缩。而对于客户端是完全透明的
DNS 流量调度
这是一种特殊的实现负载均衡的方式。主要原理是通过一个DNS服务器,将域名解析到不同IP,每个IP对应不同的服务端实例。例如:苹果官网,可以根据客户端的访问来源IP,将访问定位到对应国家的web目录之下。
例如 AWS Route53 服务就实现了 DNS 流量调度。
限制:
- 后端调度实例升级不方便
- DNS缓存的存在,会导致流量调度不均匀
优势:
- 可以根据地域调度流量到不同的Load Banlace实例上,实现跨地域的负载均衡
四层负载均衡
四层负载均衡主要实现方式是 LVS (Linux Virtual Server)。也叫网络负载均衡,通过 IP+端口 的方式进行流量转发;主要有以下三种调度模式:
- NAT 模式
- NAT 模式下负载均衡服务器双网卡,具有对外部用户的 VIP 和对内的 DIP
- NAT 模式由于负载均衡服务器和后端服务器的 IP 不一样,所有数据包的交付都依赖负载均衡服务器进行 IP 转换(由负载均衡服务器到真实服务器时 DNAT;由负载均衡服务器到外部用户时 SNAT),负载均衡服务器的网卡带宽容易称为瓶颈;
- 通过 NAT 技术做调度,请求和响应都经过调度器中转,相同配置下性能最差
- TUN 模式
- 请求报文通过 IP tunnel (将一个 IP 数据报文封装在另一个 IP 数据报文中)转发至目的真实服务器,真实服务器直接将响应返回给客户(解包后源 IP 为 VIP,目的 IP 为客户端IP)
- 调度器只处理请求报文
- DR模式
- 调度器写请求的 MAC 地址,将请求直接发送给后端 server,后端 server 处理请求后直接给客户。性能最好
七层层负载均衡
七层负载均衡主要实现方式是 Nginx 反向代理( Nginx 先使用负载均衡模块找到一台主机,再使用upstream模块实现与这台主机的交互)。七层负载均衡也叫服务端负载均衡;云厂商一般会在这个基础上做一些优化,例如阿里云七层负载均衡叫 Tengine (淘宝发起的Web服务器项目),就是在反向代理基础上做了很多优化。
七层就是在四层的基础上,再考虑应用层的特征,比如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡。应用层负载均衡和前端的客户端以及后端的服务器会分别建立TCP连接,所以性能大大不如四层负载均衡。
负载均衡调度算法
负载均衡为了实现流量的均衡调度,同时需要考虑后端服务器增加减少的情况。需要使用一些特殊的算法来实现这个目标,特别是在后端服务器增加减少的时候,如何保证会话尽可能保持,这个就需要用到一致性哈希(Consistent Hash)算法。
一致性哈希特性
- 单调性(Monotonicity),单调性是指如果已经有一些请求通过哈希分派到了相应的服务器进行处理,又有新的服务器加入到系统中时候,应保证原有的请求可以被映射到原有的或者新的服务器中去,而不会被映射到原来的其它服务器上去。
- 分散性(Spread):分布式环境中,客户端请求时候可能不知道所有服务器的存在,可能只知道其中一部分服务器,在客户端看来他看到的部分服务器会形成一个完整的hash环。如果多个客户端都把部分服务器作为一个完整hash环,那么可能会导致,同一个用户的请求被路由到不同的服务器进行处理。这种情况显然是应该避免的,因为它不能保证同一个用户的请求落到同一个服务器。所谓分散性是指上述情况发生的严重程度。好的哈希算法应尽量避免尽量降低分散性。 一致性hash具有很低的分散性
- 平衡性(Balance):平衡性也就是说负载均衡,是指客户端hash后的请求应该能够分散到不同的服务器上去。一致性hash可以做到每个服务器都进行处理请求,但是不能保证每个服务器处理的请求的数量大致相同
- 除此之外,如果出现 hash 倾斜的情况,又不想多加机器。就可以使用虚拟节点的方案来实现。