负载均衡是个啥?

Posted 大柱子和你聊编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了负载均衡是个啥?相关的知识,希望对你有一定的参考价值。

这回咱们聊一聊后端服务的负载均衡(Load Balancer)。负载均衡作为后端服务架构里一种网络设施,弄清楚它如何工作能使我们对网络OSI模型,会话保持等问题有一个更深刻的理解。


我们现在就开始吧!


负载均衡是什么?



负载均衡就像交警一样,在集群中间指挥,向各个服务器分配请求,保证每台服务器资源都能被最大程度的利用,同时,也能确保不会有服务器负载过高,导致响应变慢。如果有一台服务器宕机了,负载均衡就将这台从备选的服务器组里剔除掉,不再向其转发请求。


总结一下,负载均衡的作用有两点:


  1. 在多台服务器中间转发请求,提升后端服务整体的响应速度。


  2. 检测后端服务状态,如果异常则从备选中剔除,确保服务稳定。


在现代的后端服务架构中,负载均衡是必不可少的一个组件。


负载均衡的实现方式


主流的负载均衡分为两种,分别是L4 和 L7 负载均衡。为什么叫做 L4 和 L7 呢?我们知道 OSI 模型将网络抽象为七层,L4 和 L7 表示负载均衡作用在 OSI 模型的第四和第七层。我们来依次说明这两种方式是如何实现的?



L4 负载均衡



1

TCP/UDP termination load balancers


在这种实现方式下,负载均衡会与客户端以及后端分别建立一个 TCP/UDP 连接。举个例子,就拿 TCP 协议来说,当你的客户端向负载均衡发送 SYN 进行握手时,负载均衡会返回 SYN+ACK 报文,从而和客户端建立连接。与此同时,负载均衡也会和后端服务器建立 TCP 连接,转发后续收到的来自客户端的数据。



这种方式的优势在于,在客户端是弱网的情况下,如果我们部署一个距离用户比较近的负载均衡,那么可以加快超时重传的速度。


2

TCP/UDP passthrough load balancers


和上一种方式不同,在这种方式下,负载均衡不会返回 SYN+ACK 报文,也就是说负载均衡不会和客户端进行握手操作。取而代之的是,负载均衡选择一个后端服务器,通过一个 NAT 转换,将对应的报文发送到这台服务器上。



负载均衡是个啥?



这种方法的优势在于:


  1. 很好的性能:

    这种方式下,负载均衡无需维护 TCP 连接,像发送窗口,拥塞窗口这些缓存结构。只需要通过 HashMap ,保存源和目标之间的映射关系。显而易见,这种实现方式的资源占用少,速度快。


  2. 后端服务器可以采用自定义的拥塞控制策略:

    这种方式下, TCP 连接是客户端和后端服务器之间建立的。显然,后端服务器就可以采取一些自定义的拥塞控制策略,比方说 Google 的 TCP BBR 。能够增加网络单位时间内的吞吐量。


像 linux 下的命令行工具 iptables,就能够实现这类 NAT 转换。iptables 中用到的库 libiptc ,也被常见的 L4 负载均衡软件,比如 LVS,nginx 所采用。libiptc 让我们可以通过编程形式对 linux 中的网络规则进行编辑,从而实现 NAT 转换 。



L7 负载均衡


L7 负载均衡,工作在 OSI 网络模型的第七层,也就是我们熟悉的 http/https 协议上。L7 负载均衡可以获取到 http 请求里的具体内容,比方说域名或者路径或者Cookie等等 Header 信息,基于这些信息选择一个后端服务器转发请求。


举个例子,如果一个请求访问的的域名是 api.example.com, 那么负载均衡就将它转发到后端提供某个接口功能的服务器上,如果是 static.example.com, 就转发到静态资源服务器上。


同 L4 负载均衡的第一种方案一样,L7 负载均衡需要维护两个连接,同时还需要解析请求的内容。因此相比之下,L7 负载均衡的开销大,性能弱。但是现如今的服务器配置都相当豪华,一定程度上能够克服掉这个问题。


软件不够硬件来凑。


负载均衡的路由策略


请求的合理分配需要有一些策略。采用不一样的策略,会有不一样的效果。常见的策略有:


1

轮询策略


这种策略最为简单,负载均衡按照服务器的顺序,依次的向服务器们转发请求。这种情况下,每台服务器的压力很平均。


2

最少连接数策略


在这种策略下,负载均衡会选择当前TCP连接数最少的服务器,进行请求转发。在这种情况下,一般处理能力较强的服务器,接收到的请求就会多一些,相比于第一种方式,能够变相的加快请求处理速度。


3

加权策略


我们也可以人为设定每台服务器的权重,让负载均衡更大概率的选择权重高的服务器。


这些策略在 Nginx 里都有实现,按场景不同,任君选择。


负载均衡的会话一致性


我们知道,在上述的路由策略下,请求分配到哪台服务器是随机的,这就会带来一个严重的问题:会话不一致。我们来举个例子。


比方说有这样一个应用场景,我们有一个购物类 web 应用,其中有两个接口分别是添加到购物车和结算,后端的服务会维护一个HashMap,用户ID作为key,用户ID对应的购物车内物品数组作为value。用户ID保存在 cookie 里,附带请求发送。


浏览器调用购物车接口时,我们在HashMap中,通过 ID 获取到购物车数组,添加一项物品。调用结算接口时,累加数组每一项物品的价格,计算总金额。


负载均衡是个啥?


如果第一次购物车接口请求的是服务器A,第二次结算接口请求的是服务器B,那么问题就出现了。计算金额的时候,在HashMap里找不到用户ID对应的购物车信息了。


当然,可以通过数据库将每个ID对应的购物车信息持久化,保证请求不同服务器时信息也不会丢失。但是这么做显然非常笨重,如果有一种方法能保持会话一致,也就是第一次的接口请求和第二次落在同一台服务器上,问题就能解决。


幸运的是负载均衡提供了这样几种方法:


1



2

Sticky Cookie


第二种方式,当负载均衡选择了一台后端服务器之后,将这台服务器的 ip 和端口进行一次哈希运算并保存映射关系。将计算好的值放到 Cookie 里返回给客户端。当收到后续请求后,取出该 Cookie,通过这个值,找到对应的后端服务器,转发请求。因为我们得处理 Cookie,所以这种方案只适合于 L7 负载均衡。和第一种方法一样,Nginx 也提供了这种配置。这个方式还有一类变种:基于某个自定义的字段进行哈希运算,通过该值选择一个对应的后端服务器。比如说根据 Cookie 中用户标识 UID 的哈希值,选择一个后端。


通过以上两种办法,我们就能够解决好会话不一致的问题。当然了,极端情况下,比如用户切换了 VPN,又或者用户删掉 Cookie,使用隐身模式等等,这类方法还是会失效。所以,在极端苛刻的业务场景下,确保数据的一致性还是采用持久化的方式。


负载均衡的实现方案


负载均衡有硬件和软件两种实现方案。


硬件负载均衡,利用专门定制的硬件和操作系统实现,这类设备有特殊的网卡和系统,相比普通服务器能够更快的处理请求。像 F5,思科Cisco这类公司,都有提供类似硬件。


至于软件负载均衡,说的就是转发代理软件。市面上有非常多的产品可供使用,像鼎鼎大名,既可以工作在 L7 ,又能在 L4 层的 Nginx 与 HAProxy。再比如工作在 L4 的 LVS。还有时下比较时髦,在容器环境下十分流行的 Istio 等等。这些工具的用法,各自官网上都有非常详细的介绍。想了解的彭于晏们,肯定一看就懂,一学就会,这里就不做更多介绍了。在实际业务场景里,L4 和 L7 负载均衡一定是搭配使用的,这样既可以兼顾性能,又可以灵活的配置路由策略满足业务需求。


好了,以上就是文章全部内容,咱们下期再见!


编辑:大柱子

参考:  

1.

https://medium.com/martinomburajr/distributed-computing-tcp-vs-http-s-load-balancing-7b3e9efc6167

2.

https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236

3.

https://scalingo.com/blog/iptables



以上是关于负载均衡是个啥?的主要内容,如果未能解决你的问题,请参考以下文章

负载均衡设计的正确姿势 实战FD.io VPP

公司架构师常常提起的DNS负载均衡是个什么鬼?

公司架构师常常提起的DNS负载均衡是个什么鬼?

LinuxNginx配置负载均衡

图解 DNS 域名解析与负载均衡

AzureSLB设置出站规则