阿里云MVP乔帮主:五大类型负载均衡的原理场景详解(文末赠书)
Posted 中生代技术
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里云MVP乔帮主:五大类型负载均衡的原理场景详解(文末赠书)相关的知识,希望对你有一定的参考价值。
乔帮主
读完需要
速读仅需 5 分钟
导读:本文摘自于阿里云 MVP、“乔帮主”乔锐杰所撰写的《阿里云运维架构实践秘籍》一书,我们发现常见负载均衡 LVS、nginx、HAProxy、阿里云 SLB 及硬件负载均衡等,不同的负载均衡应用场景和功能上有很大区别,这取决于负载均衡底层的原理,原理不同导致了不同负载均衡应用场景、功能、性能的巨大差异。但万变不离其宗,这些常见负载均衡可以按照底层原理进行归类,相信通过本文内容会让你有很大收获。
作者简介
乔锐杰 阿里云 MVP,江湖人称“乔帮主”,阿里云资深架构师/技术专家。国内云端架构与运维实践开拓者,曾主导过电商、金融、政府、视频、游戏等领域千万级云端架构,在云端分布式集群架构、云端运维、云端安全等方面有着丰富的实战经验。担任黑客讲师/Java 高级讲师/Python 讲师/运维高级讲师/阿里云讲师,从事过安全、研发、高级运维、架构师等大半个互联网相关技术职位,现担任驻云科技运维总监兼阿里云架构师。
1
常见负载均衡的分类
说到常见负载均衡的分类,我们先来看看什么是 OSI 七层模型。我们常说的二层/三层/四层交换机,就是基于 OSI 七层模型所对应的层来命名的。我刚开始接触网络设备的时候,第一次听说二层交换机、三层交换机时,还以为交换机的硬件厚度有二层、有三层,后来才知道,其实是按照 OSI 七层模型来区别不同交换机的原理功能。OSI 七层模型主要作为一个通用模型来做理论分析,它是一个理论模型。而 TCP/IP 通信协议模型(四层)是互联网的实际通信协议,两者一般做映射对比及分析。
OSI 七层模型及对应的传输协议
而常见的负载均衡有很多,有出名的硬件负载均衡,如 F5、Netscaler;还有常见开源的负载均衡,比如 LVS、HAProxy、Nginx,甚至 Apache 也能做负载均衡(不推荐)。我们常说的七层负载均衡、四层负载均衡,也是基于 OSI 七层模型的。基于 OSI 七层模型的底层原理,我们把常见的负载均衡具体划分为以下几个类型:二层、三层、四层、七层。最后再加上一个除 OSI 七层模型以外的 DNS,通过 DNS 做负载均衡的场景也是非常常见的。
负载均衡的分类
当前二层、三层负载均衡的实现只有 LVS 能做到。而相比在四层、七层的负载均衡应用得要更为广泛,比如硬件负载均衡、Nginx、HAProxy 热门的中间件都支持四层、七层的负载均衡。
2
负载均衡开山鼻祖—LVS 的工作原理
前面已介绍了 LVS 的应用场景及特性,但在介绍二层/三层/四层/七层负载均衡对比之前,有必要说一下 LVS 的原理。在运维领域,相信大家对 LVS 并不陌生,几乎提到负载均衡,提到运维,都会提到 LVS。在实际负载均衡实践应用中,我看到了一些有意思的现象,接下来跟大家详细分享一下相关的技术实践。在此之前,先来看看负载均衡技术相关术语缩写。
负载均衡技术相关术语缩写
LVS 负载均衡技术的实现,主要由 IPVS 和 Ipvsadm 实现。
IPVS:是 LVS 集群系统的核心部分,是基于 Linux Netfilter 框架实现的一个内核模块,主要工作于内核空间的 INPUT 链上。其钩子函数分别 HOOK 在 LOCAL_IN 和 FORWARD 两个 HOOK 点。
需要特别注意的是,IPVS 是直接作用在内核空间进行数据包的修改及转发的。而 Nginx/HAProxy 作用在用户空间,这使得 LVS 的性能更为强悍(能够赶上硬件负载均衡的性能),而 Nginx/HAProxy 根本不是一个量级。并且现在 IPVS 已经是 Linux 内核标准的一部分,在早期的 Linux 系统版本中,安装 LVS 还需要重新编译内核,当然现在已经不需要了。
内核LVS数据包流向
Ipvsadm:而 Ipvsadm 是工作在用户空间,主要用于用户定义和管理集群服务的工具。所以实际在安装配置 LVS 时,主要是安装配置 Ipvsadm。比如在 Redhat 中安装一条简单命令来实现:
yum install ipvsadm
LVS 原理架构
具体数据包的走向如下:
访问请求首先经过 VIP 到达负载调度器的内核空间。
PREROUTING 链在接收到用户请求后,会判断目标 IP,确定是本机 IP,将数据包发往 INPUT 链。
当用户请求到达 INPUT 时,IPVS 会将用户请求和 Ipvsadm 定义好的规则进行对比。如果用户请求的就是定义的集群服务,那么此时 IPVS 会强行修改数据包,并将新的数据包发往 POSTROUTING 链。
LVS 三种模式
3
二层负载均衡
当前的负载均衡界,只有 LVS 实现了二层负载均衡。所以二层负载均衡实践主要为 LVS 的 DR 模式实践。
二层负载均衡数据包走向原理
以下是对二层负载均衡数据包走向原理的详细说明:
4
三层负载均衡
同样,在当前负载均衡界,只有 LVS 实现了三层负载均衡。所以三层负载均衡实践主要为 LVS 的 IP-TUN 模式实践。
三层负载均衡数据包走向原理
以下是对三层负载均衡数据包走向原理的详细说明:
云诀窍
TUNNEL 模式走的隧道模式,运维起来比较困难,在实际应用中不常用。
5
四层负载均衡
LVS 的 NAT 模式、阿里云的四层 SLB、Nginx/HAProxy 的四层,虽然都是四层负载均衡,但是它们的底层原理有很大差异,这就导致它们的功能特性也有很大区别。
5.2
LVS-NAT 下的四层负载均衡
四层负载均衡 LVS-NAT 数据包走向原理如下图所示。以下是对四层负载均衡 LVS-NAT 数据包走向原理的详细说明。
四层负载均衡 LVS-NAT 数据包走向原理
云诀窍
我们可以看到,目标服务器处理完数据包返回给客户端的时候,会经过 LVS,然后再把数据包回给客户端。由此可以看到,LVS NAT 模式存在很大的性能瓶颈(就是在于 LVS 这一端),而相比于 DR 及 IP-TUN 模式,数据包后端服务器直接返回给客户端就不存在这个问题。在实际运用中,我也遇到过这个真实的性能瓶颈案例。之前工作过的一家公司主要从事电商领域,在一年一度的双十一备战中,流量高峰期客户端出现严重的卡顿、丢包和延时。当时负载均衡采用的就是 LVS 的 NAT 模式,我们发现高并发高流量模式下,内网的流量可达到千兆。那时紧急切换到 LVS DR 模式,故障很快消除了。
5.3
阿里云 SLB 下的四层负载均衡
阿里云四层负载均衡针对 LVS 的一些问题进行了定制和优化,新增转发模式 FULLNAT。
阿里云四层负载均衡对 LVS 的优化
由此可见基于 LVS,阿里云四层负载均衡实现了跨 VLAN、具备防 DDoS 攻击的能力、采用集群方式部署。这 3 个方面相比原生态的 LVS,功能上做了很大的改进。
云诀窍
实践应用中,我们发现使用阿里云的四层负载均衡,数据包的走向跟后端的 ECS 有没有绑定公网 IP 有直接关系(仅限经典网络)。
当后端 ECS 不绑定公网的时候,负载均衡转发数据包给后端 ECS。后端 ECS 处理完将返回数据包给负载均衡,负载均衡再返回数据包给客户端。这种方式类似 LVS 的 NAT 模式。
当后端经典网络的 ECS 绑定公网的时候(只有经典网络的 ECS 绑定的公网 IP 会单独分配公网网卡 eth1),负载均衡转发数据包给后端 ECS。后端 ECS 处理完将数据包直接通过公网网卡返回给客户端。这种方式类似 LVS 的 DR 模式。在 ECS 的公网网卡监控中看不到这块的流量明细,这块流量内容直接归并到 SLB 中计算了。但我们通过 Zabbix 相关监控,可以看到 eth1 公网网卡流量,并能抓到相应明细。有时候实际公网网卡流量甚至远远超过公网带宽峰值,由此可以看到,这部分返回给客户端的数据包走公网网卡,不受后端 ECS 绑定的公网带宽限制,且不纳入 ECS 的流量计费,单独放在 SLB 流量计费中了。
如果 ECS 有公网 IP 和私网 IP,禁用公网网卡就会影响负载均衡服务,因为在有公网网卡的情况下,默认路由会走公网,如禁用就无法回包,因此负载均衡服务会受影响。建议不要禁止,如一定要这么做,需要修改默认路由为私网才会不影响服务。但需要考虑业务是否对公网有依赖,如通过公网访问 RDS 等。
7.1
Nginx/HAProxy 下的四层负载均衡
四层负载均衡 Nginx/HAProxy 数据包走向原理如下图所示。以下是对四层负载均衡 Nginx/HAProxy 数据包走向原理的详细说明。
四层负载均衡 Nginx/HAProxy 数据包走向原理
云诀窍
需要重点注意的是,这里已经跟 LVS 有本质的区别。LVS 的 NAT 模式对外是以虚拟 VIP 作为请求入口(IP 层为三层),然后在三层负载均衡的基础之上用 IP+PORT 接收请求,再转发到对应后端服务器,所以 LVS 的 NAT 模式是三层负载均衡+四层负载均衡。而 Nginx/HAProxy 的四层对外直接暴露的是 DIP+TCP/UDP IP 端口服务。
然后负载均衡将此数据包报文的响应内容进行重新打包并返回给客户端。
6
七层负载均衡
在常见负载均衡分类中,其实应用最为广泛的还是七层和四层负载均衡。而七层和四层负载均衡最主要的区别是,在七层负载均衡中能获取用户请求的 HTTP 头信息。具体什么是 HTTP 头信息,我们以 nginx.conf 配置中定义的 Nginx 日志文件的格式内容从侧面进行说明:
log_format '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';
然后我们在对应的日志文件中可以看到具体客户端的请求头内容信息,如下:
45.127.220.171 - - [02/Dec/2018:14:10:17 +0800] "GET https://qiaobangzhu.cn ( https://qiaobangzhu.cn ) HTTP/1.1" 301 184 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
七层负载均衡数据包走向原理
以下是对七层负载均衡数据包走向原理的详细说明。
报文送到后端服务器后,服务器响应该请求,并将响应数据包报文返还给负载均衡。跟 Nginx/HAProxy 一样,这里无须额外配置后端服务器的网关,即 SNAT 相关配置。
然后负载均衡将此数据包报文的响应内容进行重新打包并返回给客户端。
综上所述,因为七层中能获取应用层 HTTP 的请求内容,所以七层负载均衡有如下常见应用场景:
七层作用在 HTTP 应用层,所以七层的负载均衡只能跟 Tomcat、php 等 Web 服务做负载均衡。
可以根据请求的域名来做转发。比如请求者访问 A 域名,转发到后端 A 服务器;请求访问 B 域名,转发到后端 B 服务器。这个功能,在七层叫虚拟主机功能,是七层应用中最为热门的应用实践。
可以根据请求的 URL 来做转发。比如请求者访问的 URL 包含 A 目录,就转发到 A 服务器;请求访问的 URL 包含 B 目录,就转发到 B 服务器。
可以根据请求的浏览器类型来做转发。比如请求者使用的浏览器类型是 Chrome,就转发到 A 服务器;请求者使用的浏览器类型是 Firefox,就转发到 B 服务器。
对 mysql、LDAP、Redis、Memcache 等四层应用做负载均衡。
对七层 HTTP 的 Web 类应用做负载均衡,如 Tomcat、PHP。
对七层 Nginx、HAProxy 的负载均衡做负载均衡(具体在实践中,四层和七层怎么来搭配使用,详见第二篇中负载均衡的相关章节)。
但四层中没办法跟七层一样,做虚拟主机的应用。我曾经在面试中问过这个问题,就是 LVS 能不能识别域名来做转发。比如请求者访问 A 域名,转发到后端 A 服务器;请求访问 B 域名,转发到后端 B 服务器。有意思的是,有一些经验丰富的运维人员对这个问题还回答不出来,这就需要好好看一下底层原理和对应负载均衡的应用场景了。答案肯定是不行的,因为 LVS 在四层和二层,没办法识别封装在七层中的数据包内容。再举个七层负载均衡实践的例子,要访问我们驻云内部的某个系统,要求客户端必须使用 Chrome 浏览器,可参考以下核心配置:
location / {if ( $http_user_agent !~ ^.Chrome/5|6. ){rewrite ^(.)$ https://qiaobangzhu.cn/error.html ( https://qiaobangzhu.cn/error.html ) permanent;}proxy_pass http://192.168.2.2:81/ ( http://192.168.2.2:81/ );proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
实现的核心配置就是获取七层头信息里面的数据来做对比判断,如果符合,执行对应的操作即可。这个是四层/二层负载均衡无法实现的功能。
7
负载均衡的“一次连接”和“两次连接”核心总结
7.2
LVS 二层/四层的“一次连接”
LVS 的 DR 模式、NAT 模式对数据包的处理都仅做“一次连接”,即负载均衡对数据包仅做转发。
LVS 的三次握手数据包走向
LVS 能够做到“一次连接”的本质原因是 LVS 工作在内核空间。LVS3 种模式都是工作在内核空间,数据包的处理也仅在内核空间,这也是 LVS 轻量高效、高性能的最为本质的原因。
云诀窍
LVS 请求数据包走向
7.3
Nginx/HAProxy 四层的“二次连接”
相比于 LVS,Nginx/HAProxy 四层要建立“二次连接”。
Nginx/HAProxy 四层三次握手数据包走向
客户端在向负载均衡进行 TCP 三次握手后,负载均衡会马上发起新的 TCP 连接,即为“二次连接”。由于是负载均衡与后端建立新的 TCP 三次握手及转发客户端请求的数据,所以在后端服务器 netstat -n 查看到的请求通信的 IP 是负载均衡的 IP。而相比于 LVS,Nginx/HAProxy 四层工作在用户空间,对数据包的处理是在用户空间完成的,数据包的流转及处理过程增多,这也是 Nginx/HAProxy 的性能和达不到 LVS 这个量级的本质原因。
Nginx/HAProxy 请求数据包走向
Nginx/HAProxy 七层的“二次连接”
相比于 Nginx/HAProxy 四层的二次连接,而 Nginx/HAProxy 七层的二次连接有些不一样。Nginx/HAProxy 四层的二次连接,是客户端和负载均衡进行 TCP 三次握手后,负载均衡和后端服务器马上进行新的 TCP 三次握手。而 Nginx/HAProxy 七层的二次连接,在客户端和负载均衡进行 TCP 三次握手后,还需要等客户端 Pushdata 传输数据,之后负载均衡和后端服务器才会建立新的 TCP 三次握手。由此可见,Nginx/HAProxy 四层的二次连接转发效率会更高。加上 Nginx/HAProxy 七层会进行一些 Rewrite 规则的判断,会损耗一些 CPU 和内存的性能。所以相较而言,Nginx/HAProxy 四层的性能要高许多。同样,由于是负载均衡跟后端建立新的 TCP 三次握手及转发客户端请求的数据,所以在后端服务器 netstat -n 查看到的请求通信的 IP 是负载均衡的 IP。所以在后端服务器中,HTTP 头的 remote_addr 虽然代表客户端的 IP,但实际值是负载均衡的 IP。为了避免这个情况,七层负载均衡通常会增加一个叫作 x_forwarded_for 的头信息,把连接它的客户端 IP(上网机器 IP)加到这个头信息里,这样就能保障后端服务器可以获取到客户端真实的 IP。但实际上,我们会遇到后端服务器再把请求转发给到下一个目标服务器的情况,即:“客户端请求>>> Nginx >>> Nginx1 >>> Nginx2”的结构,我们在 Nginx1 服务器上通过 x_forwarded_for 的头信息获取到了客户端的真实源 IP,那如何在 Nginx2 上进一步获取客户端的源 IP 呢?在 Nginx1 上的转发规则中,配置如下代码:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
这样会让 Nginx1 转发给后端 HTTP 头中的 x_forwarded_for 信息中保存客户的真实源 IP。
Nginx/HAProxy 七层三次握手数据包走向
云诀窍
8
DNS 负载均衡
从 OSI 七层模型来看,DNS 的域名解析其实作用在第七层应用层。
DNS 请求流向
DNS 的负载均衡,一般在超大规模的应用中,特别是跨地域的分布式应用中运用得非常广泛,常规的中小型、中大型应用,不是特别推荐尝试 DNS 的负载均衡。DNS 作为负载均衡的应用场景将会在第二篇中详细介绍。
9
总结
不同负载均衡的类型的功能特性汇总。
本文摘自于《阿里云运维架构实践秘籍》,经出版方授权发布。
10
福利时间
以上是关于阿里云MVP乔帮主:五大类型负载均衡的原理场景详解(文末赠书)的主要内容,如果未能解决你的问题,请参考以下文章