互联网通信中,服务为了能同时应对多个客户的并发请求,一般都会部署在多台机器上作为一个集群对外,而为了使请求按照一定的规则转发到多台服务器,需要在链路前端增加一个分发请求的设备,这类设备统称为负载均衡器。
负载均衡器可以分为IP级别的和应用级别的,也就是通常的四层负载均衡和七层负载均衡。四层的只能做到流量的转发,不能理解应用层协议,是基于IP+端口的负载均衡,具体就是通过一个虚拟的IP+端口接收请求然后分发到真实的服务器;而七层除了支持四层的功能外,可以理解应用层协议,用一个虚拟的URL或者主机名接收请求,根据应用层的信息比如URL、语言等转发到真实的服务器,也是也因为如此,七层的在处理和答复HTTP请求时开销大,系统伸缩性有限,对CPU和内存消耗也大,可能会成为瓶颈。(当然还有基于MAC的二层负载和基于IP的三层负载,在此不细说)
四层和七层负载均衡很大的一个区别点是什么?由于四层负载均衡器是直接根据IP+端口和分发的算法选择后端服务器,无需理解报文内容,所以在建立TCP连接时实际上是客户跟真实服务器进行的三次握手,负载均衡更像是一个路由转发的动作,具体就是在负载均衡器接收到客户端第一个SYN数据报时,就选择一个服务器改写目的IP地址,直接转发给该服务器;而七层负载则因为要理解消息内容进行转发,必须先要建立TCP连接才可以接收,所以是客户端跟负载以及负载跟后端服务器分别进行的三次握手。
那常见的几种负载均衡有LVS,nginx和F5。LVS属于软件的负载均衡器(一般还需用nginx来承接),nginx也是属于软件类的,可以工作在四层也可以工作在七层,而F5则是硬件,同样四层和七层兼顾。下面简单介绍下各自的原理。
LVS(Linux Virtual Server)linux虚拟服务器,属于开源软件,在linux 2.4版本后已经集成进linux内核,使用方便;最大的优点是工作逻辑简单速度快,负载能力高,稳定性强,对CPU和内存的资源消耗较低。但是对网络依赖性强,仅请求流量经过lvs,响应流量由后端服务直接返回。
LVS架构分为三层:负载调度器(director)、后端服务集群(real server)和共享存储(shared storage)。负载调度器是服务集群的唯一入口点,可以采用IP负载均衡技术和基于内容请求分发技术。在IP负载均衡技术中,服务器池提供相同的服务。由于LVS工作在第四层,所有的操作都是在Linux操作系统协议栈中完成,调度开销很小,所以吞吐率很高。共享存储主要给服务器集群提供一块共享的数据库或者说文件系统以便提供相同的服务。这三层结构通过高速网络相连,为避免系统扩大时网络成为瓶颈。
目前LVS有三种工作模式:DR、NAT以及Tunnel,简诉一下具体原理:
1、VS/DR(direct route)通过直接路由实现虚拟服务器。体系结构如下图所示,从下图可见,director跟real server必须在物理上连接在一个局域网内。
工作流程:假设用户请求的报文中源IP为CIP,目标IP为VIP,源MAC为CMAC,目标MAC为VMAC。请求到达director后,按照调度算法找到最佳一台RS,把目标MAC改为对应RS的RMAC,其他信息不变,然后转发到RS上;RS收到目标IP为VIP的网络包,发现自己的网卡就是VIP,于是接收并进行处理;处理完请求后将一个源地址为VIP目标地址为CIP的数据包发出去,此时响应不会经过director(因为director的网卡是VIP),直接响应客户。从这个工作流程可见,director和RS均有网卡配置了VIP,而为了使请求必须到达director,则RS的服务器VIP要配置在non-arp的网卡上,即不响应对应的arp请求,对外不可见。这样只有请求经过director,响应不经过,所以吞吐率相对高,这种方式用得也是比较多的。
注意:在该模式下,如果前端调用的端口有改动,需要同步修改LVS的RS的端口成一致的。
2、VS/TUN(tunnel)利用IP隧道技术实现虚拟服务器。IP隧道是指将y一个IP报文封装在另一个IP报文,目标IP地址为A的一个报文可以转发到另一个B地址。主要用于虚拟私有网络。体系结构如下:
TUN的工作机制跟DR类似,只不过在转发时需要重新包装IP报文,此时director跟RS不在一个网络上,但是RS也必须配置VIP地址。它在IP数据包外再加一个IP头部,源地址为DIP,目的地址为RIP,这样RS接收到数据包分析后就能知道是隧道。响应也是由RS直接返回给客户。
3、VS/NAT 通过网络地址转换来实现虚拟服务器。其体系结构如下图:
三种方式优缺点比较如下,其中DR和TUN模式的吞吐率都比NAT的高,但TUN模式实现复杂,所以一般都使用的DR模式。
Nginx是一个高性能的HTTP服务器和反代理服务器,同时是工作在第七层的负载均衡器,通过配置upstream上游服务集群调用proxy_pass负载到后端服务器。相比于四层负载,可以根据http的uri、请求头等内容来决定转发到哪个服务器,采用的是多进程+异步非阻塞的IO事件模型来处理请求。
同步转发和异步转发的区别其实上面有讲过了,像LVS,客户端真正建立连接是RS而非director,请求到达director后立即转发到了RS,响应由服务直接返回给客户,这种就属于同步转发;而异步转发就是像nginx,客户端跟ng以及ng跟后端服务均需要建立连接,ng接收到客户端请求后需要保持连接,再生成一个新的请求发送到后端服务,返回结果由ng返回给客户端,这种就是异步转发。当后端服务器请求失败了,ng可以立即切换到其他服务器直到请求成功,这样可以最大程度的提高请求成功率。但是LVS默认没有监听后端服务的健康状态,如果后端服务器出了问题,那么请求就失败了。(不过一般LVS都会搭配keepalived一起使用)
在平时工作中一般也是LVS+Nginx搭着用,一方面可以利用LVS的高吞吐率,另一方面也可以给后端的并发请求做一个缓存,同时提高请求成功率。
nginx常用的调度算法有IP hash,least conn和轮询,不细说。
F5
www.linuxvirtualserver.org