20张图让你彻底掌握负载均衡的秘密!(一)
前言
今天我们来深度揭秘一下负载均衡器 LVS 的秘密,相信大家看了你管这破玩意儿叫负载均衡?这篇文章后,还是有不少疑问,比如 LVS 看起来只有类似路由器的转发功能,为啥说它是四层(传输层)负载均衡器呢,今天我们就来逐渐揭开 LVS 的迷雾,本文将会用图解的方式浅入深地探讨 LVS 的工作机制
最好大家对网络是如何连接的,数据包的收发机制有所了解,这样会很容易理解本文的知识点,如果对此没概念,强烈建议大家看看我之前写的这篇文章,把网络是如何连接的给你安排得明明白白
没看过也没关系,本文会对一些必要的知识点做些铺垫,争取让大家都能看懂
负载均衡器的诞生
在很长一段时间内小章公司的 DAU(日活)不超过 10,所以他只部署了一台机器,毕竟多一台机器要加钱,而且就算挂了也影响不了几个用户
但无意间小章的业务踩中了风口,业务量暴涨,dau 达到了好几万,眼看就要突破十万,小章慌了,赶紧全面升级了这台机器的内存,CPU 等配置,暂时扛过去了,但小章明白,单机性能无论怎么升都会遇到瓶颈,所以小章想了个办法,多部署几台机器,将流量平均分配到这几台机器上
怎么分配呢,最简单的方式,当然是用 DNS 负载均衡,在域名解析服务器上设置负载均衡策略,让流量随机打到其中某台机器上
但这个方案有以下两个明显的问题:
- 占用过多公网 IP,要知道现在租一个公网 IP 可是要好几千
- DNS 缓存可能会引起致命故障
第一个问题加钱就能解决,但第二个问题可不是加钱就能解决的了,因为众所周知 DNS 解析是迭代或递归查询,需要经过 根 DNS 服务器 ->顶级DNS服务器->权威DNS服务器这三步查找才能解析到域名对应的 ip,可想可知这个解析是有多么耗时,所以一般会有 DNS 缓存,DNS 缓存主要有「浏览器缓存」,「操作系统缓存」,「路由器缓存」,「ISP 缓存」四种
每次发起一个域名解析请求,都会依次在以上四个缓存里查找,如果命中缓存,则直接返回此域名对应的 IP,其中像 Chrome 缓存 1 分钟, ISP 缓存可能高达 1~2 个小时,于是问题就来了,如果某台机器宕机,但由于以上四个缓存中依然可能会有此域名的 IP 缓存,对请求方而言,是感知不到的,那么只要缓存未过期请求方就会持续地将将流量打到这台挂掉的机器,引起线上故障,这当然是不能容忍的。
那该怎么办呢,小章突然想起了计算机界的一个经典名言:「没有什么是加一层解决不了的问题,如果有,那就再多加一层」,何不在 DNS 与 server 间多加一层,负载均衡的工作让这个中间层来做,小章想了下脑海中浮现出了以下架构图
可以看到这个负载均衡器(以下简称 LB)有以下特点
- 对外用公网 ip(以下我们简称 VIP) 承接所有流量,对内则与真实的服务器(即 Real Server,以下简称 RS)通信,与 RS 在同一个内网里
- LB 只负载转发请求的工作,实际的处理逻辑交由其背后的 RS,RS 处理完后将响应包发给 LB,然后 LB 再返回给 client
于是网络拓扑图改进如下
NAT
接下来的重点就是 LB 是如何工作的了,首先要明白,当我们说收到一个请求时,实际上收到的是一个数据包,那么这个数据包长啥样呢
源IP,目的IP,源端口,目的端口,简称 TCP 四元组,四元组唯一确定一条链接,在传输过程中四元组是不会变的,现在 LB 收到这个数据包之后,想将其转发给其背后的服务器,就要把目的 IP 改成服务器的 IP(假设为第二台机器,其 IP 地址为 192.168.0.3),那么修改后的数据包如下
当 RS 处理好后,由于这个数据包还要经过 LB 再转发给客户端,所以服务器的网关要设置为 LB 的内网 IP(即 192.168.0.1)再将数据包出去,LB 就能收到所有的响应数据包了。
此时的数据包如下
为什么 RS 的响应包要经过 LB 呢,因为为了保证四元组不变,LB 收到数据包后要将源 IP 改为 VIP,客户端才会识别到这是对之前请求的正确响应
画外音:客户端请求与响应包的四元组不能变
修改后的数据包
所以总结一下 LB 的主要工作机制:主要是修改了进出数据包的 IP,首先修改目的 IP 为其 RS 的 IP,将包传给 RS 处理,RS 处理完后再将包发给网关(LB),LB 再修改源 IP 为其出口的 VIP,只要四元组不变,那么客户端就能正常地收到其请求的响应,为了让大家更直观地感受负载均衡的对 IP 的修改,我做了一张动图,相信大家看了理解会更深刻
从客户端的角度来看,它以为其与 LB 背后的 RS 通信,但实际上它只是与 LB 通信,LB 只是起到了一个虚拟服务器的作用,所以我们给它命名为 LVS(Linux Virtual Server),LVS 只是起到了修改 IP 地址并且转发数据包的功能而已,由于它在数据包的进出过程中都修改了 IP 地址,我们称这模式为 NAT(Network Address Translation,网络地址转换) 模式,可以看到这种工作模式下,网络请求包和网络响应包都要经过 LVS
看到这问题似乎已经完美解决了,但是我们忽略了一个问题:每个网络数据包都是有大小限制的。如下图示,在每个数据包中,每个 payload(一般为应用层数据)大小一般不能超过 1460 byte
也就是说如果在客户端的请求数据(比如 HTTP 请求过大)超过了 1460 个字节,就要分包传,服务端收到所有分包后再组装成完整的应用层数据,那么显然,LVS 应该把同一个请求(即四元组相同)的分包转发给同一个 RS,不然把分包传给不同的 RS,数据就不完整了。所以 LVS 要根据四元组来记录包应该转发给哪一个 RS,四元组一样的数据包都转发给同一个 RS。
四元组的 IP 是在 IP Header 中,而端口号在 TCP Header 中,这意味着 LVS 需要卸下 TCP Header 拿到端口号,然后根据四元组是否相同再决定是否转发到同一台 RS 上,四元组对应一个 TCP 连接,也就是说 LVS 具有记录连接的功能,而连接是传输层的概念。至此相信你明白开头的一个问题:「LVS 起到了转发包的功能,为什么说它是四层负载均衡」
文章转自公众号:码海