系统规模达到一定程度,必然会引入对系统扩展性、系统性能、可用性方面的要求,几乎所有的解决方案中,都绕不开负载均衡的应用。
负载均衡实际是冗余技术的一种实现,对于典型的网站类应用系统,对应请求数据流的各个层面,有多种多样的负载均衡实现方案,后端的处理节点也同样如此。
要对网络请求进行负载均衡,首要的是服务无状态,请求可以在服务器组的任意节点处理,服务本身不保存状态数据,或集中管理状态数据,通过共享存储存取会话数据,典型场景如Tomcat集群 + redis。
手机APP可以采用客户端负载均衡,实现对后端服务器的负载轮询,这种方式是将后端服务器列表读取到客户端,客户端程序发起网络请求时,按既定策略对后端服务器组进行轮询,从而实现后端服务器组的负载均衡,这种方式较为少用,实现成本较高,不够灵活。
Web端可以通过DNS实现负载均衡,此种方式通过DNS服务器实现,一个域名绑定了多个IP地址,当浏览器/客户端发起HTTP请求时,首先要进行域名解析,DNS服务器可以将请求的域名解析为离客户端最近的IP地址,就近服务提升响应速度。此种方式缺陷较大,如DNS缓存时间较长,若后端服务崩溃,服务的状态变化无法及时通知DNS服务器,容易影响用户体验;这种方式一般应用于大型系统,如全国各地有多个机房/集群,且各个集群都具备相当高的可用性时,如下图:
Web静态资源可以通过CDN实现更大范围的负载均衡,CDN可以实现用户就近获取静态资源,提高响应速度。
接入层负载均衡常用解决方案包括F5硬件负载均衡、LVS/HAProxy四层负载均衡、Nginx七层反向代理实现的负载均衡等,或者基于以上几种方式的组合,如常见的F5+Nginx、或HAProxy+Nginx等四+七层负载均衡组合。
LVS NAT模式/HAProxy均为四层软负载均衡,即负载均衡器工作在TCP层,通过解析并修改TCP包,实现对TCP包的路由,进而按一定策略将TCP包投递到服务器节点,此种工作方式下未解析数据包,因此无法通过业务数据进行路由转发,因此,相对Nginx七层负载均衡来说,其负载均衡策略要单调很多,理论上说,能实现轮询、加权轮询、按连接数负载均衡等,同时由于这种特性,其性能也比七层负载要高出很多;
四层负载均衡通过修改IP地址和端口实现报文转发,进出流量都要经过负载均衡节点,性能相对二层负载均衡低,系统流量大时自身易成为整个系统的瓶颈,如下图:
LVS DR模式工作在二层模式,通过修改链路层MAC地址实现路由转发,此种模式下,响应报文不经过LVS节点,从而显著提升性能,一定程度上避免LVS成为单点瓶颈;此时Real Server在机房的中心交换机上也需要绑定一个外网映射。这样可以保证Real Server回发的响应报文能够被发送到外网,如下图:
- LVS节点接收到请求报文后,会改写报文的数据链路层格式。将Target Mac改写成Real Server的Mac,但是网络层和传输层报文不会改写,然后重新回发给交换机。这里就涉及一个问题,现在Target Mac和Destination IP的对应关系是错误的,这个数据报文到了交换机后,由于这种错位的关系,是不能进行三层交换的,只能进行二层交换(一旦进行IP交换,数据报文的验证就会出错,最终被丢弃)。所以LVS-DR方式要求Real Server和LVS节点必须在同一个局域网内。或者更确切的说法是:LVS节点需要找到一个二层链路,将改写了Mac地址的报文发送给Real Server,而不能进行三层交换的校验。
- 通过二层交换,数据被发送到Real Server节点。没有改写TCP/IP,传输层TCP/IP报文校验没有问题,然后是链路层的Mac地址能够被识别,这时就是回环IP的功劳了【使用DR模式时,需要Real Server设置LVS上的VIP为自己的一个回环IP】。对于Real Server节点来说,192.168.100.10这个VIP就是自己的回环IP,绑定的Mac也就是被LVS替换后的Target Mac。
- 被处理后生成的响应报文,被直接发送给网关,不再经过LVS节点,通过核心路由器NAT映射为外网地址。
LVS还有一种TUN模式,它是基于IP隧道技术实现的,通俗来说就是对TCP包再封装一层之后再行转发, 由目的节点依靠自己的计算能力和对IPIP隧道协议的支持,打开封装协议,取得原始协议;此种模式下,Real Server也要设置的回环IP,从而让Real Server认为原始的请求报文是从自己本地的某个应用程序发出的
七层负载均衡是根据端口号和应用层协议如HTTP协议的主机名、URL,转发报文到上游服务器(不同的IP地址+端口),一般采用Nginx实现,其支持如下几种负载均衡算法:
- round-robin:轮询,默认负载均衡算法,即以轮询的方式将请求转发到上游服务器,通过配合weight配置可以实现基于权重的轮询
- ip hash:根据客户IP进行负载均衡,即相同的IP将负载均衡到同一个upstream server
- hash key [consistent]:对某一个key进行哈希或者使用一致性哈希算法进行负载均衡。使用Hash算法存在的问题是,当添加/删除一台服务器时,将导致很多key被重新负载均衡到不同的服务器(从而导致后端可能出现问题);因此,建议考虑使用一致性哈希算法,这样当添加/删除一台服务器时,只有少数key将被重新负载均衡到不同的服务器
- 最少连接数负载均衡,按后端服务器当前连接数转发请求。
- 典型配置如下:
nginx还提供了较完善的健康检查机制,对上游服务器的健康检查默认采用的是惰性策略,Nginx商业版提供了health_check进行主动健康检查。免费版也可以集成nginx_upstream_check_module实现,典型配置如下图:
nginx现在也开始支持四层负载均衡,如我们可以利用它实现对后端mysql双写集群的负载均衡, 如下图:
上述nginx配置中,后端服务器都是直接在配置文件中写死的,当后端服务器发生变化时,须手动编辑,维护复杂,大型应用场景下难以实施;可结合Consul / Etcd等注册中心实现动态、服务节点动态注册等,如下图使用Openresty + consul实现动态配置:
当接入层流量巨大时,可结合多种负载均衡技术,实现多层次负载均衡,常见的如F5+Nginx、LVS+Nginx等。
应用层负载均衡主要基于各种应用中间件,常用的如MQ、JMS,通过消息队列实现请求缓冲、负载均衡功能,通过消息发布订阅机制,不但实现了生产者/消费者的解耦,也实现了同一消费者组内的动态负载均衡;
此外,数据库中间件Mycat、Redis集群网关Twemproxy等,某种程度上也实现了负载均衡功能,在此基础上实现读写分离、数据聚合等特性,属于应用层负载均衡方式之一。
来源:CSDN
作者:vos_land
链接:https://blog.csdn.net/vos_land/article/details/104540928