负载均衡入门教程:从 DNS 轮询到 NGINX 负载

Posted by 陈树义 on 2017-04-11

在互联网+不断渗透到生活中的今天,各种各样的网络服务存在在我们身边,他们的访问流量也是大得惊人。一个大型网站(百万PV以上)想要正常访问,单单靠一台服务器是不可能提供稳定服务的。这时候就需要用负载均衡技术将海量的接口请求平均分发到各个服务器上,以减少每台服务器的压力。

上面的流程图展示了从用户请求和响应的整个路程。用户按下一个按钮,一个请求通过网络转发到运营商网络,运营商对其进行DNS解析。如果请求所对应的域名配置了DNS轮询,那么运营商将会随机返回域名对应的一个服务器IP,之后将请求转发到该服务器上。

当请求到达服务器时,首先会达到LVS虚拟服务器,虚拟服务器再根据具体算法转发给后边的Nginx服务器。当Nginx接收到请求时,Nginx服务器会根据其配置将请求再次转发给其后端配置的应用服务器,应用服务器才是最终处理业务请求的地方。

在整个请求过程中,有三种负载均衡技术:第一次是DNS轮询,第二次是LVS负载均衡,第三次是Nginx负载均衡

DNS轮询

DNS轮询指的是服务提供者在运营商针对某一域名配置了多个提供服务的服务器IP,当用户请求改域名的接口时,运营商将随机挑选出一个服务器响应用户请求。下图的例子是:有3台联通服务器、3台电信服务器,要实现“联通用户流量分摊到3台联通服务器、其他用户流量分摊到电信服务器”这个效果的设置。

DNS由于成本较低,所以一般在小型的网站用的比较多。但是大型的网站一般也会将用它和其他负载均衡的方式结合起来一起使用,DNS轮询方式提供的IP地址,在大型网站中往往是一个集群的地址,可能是均衡交换机也可能是均衡服务器。我们可以通过nslookup命令来查询域名的DNS配置情况:

C:\Users\Administrator>nslookup www.baidu.com
服务器:  UnKnown
Address:  10.10.121.11

非权威应答:
名称:    www.a.shifen.com
Addresses:  58.217.200.113
          58.217.200.112
Aliases:  www.baidu.com

DNS轮询的优点是成本低、操作简单,但是其缺点也是明显的:

  • 服务不稳定。如果某台服务器宕机,DNS服务器是无法知晓的,仍旧会将访问分配到此服务器。修改DNS记录全部生效一般要1-3小时,甚至更久。这就可能会导致某些用户在服务器发生故障的时候完全无法访问。
  • DNS负载均衡采用的是简单的轮询算法,不能区分服务器的差异,不能反映服务器的当前运行状态,不能做到为性能较好的服务器多分配请求,甚至会出现客户请求集中在某一台服务器上的情况。
  • 登陆状态无法保存。如果是需要身份验证的网站,DNS解析无法将验证用户的访问持久分配到同一服务器。虽然有一定的本地DNS缓存,但是很难保证在用户访问期间,本地DNS不过期,而重新查询服务器并指向了新的服务器,那么原服务器保存的用户信息是无法被带到新服务器的,而且可能被要求重新认证身份,而且来回切换时间长了各台服务器都保存有用户不同的信息,对服务器资源也是一种浪费。

正是因为上述存在的缺点,所以DNS一般不会单独使用,而是配合其他负载均衡方式一起使用。

LVS负载均衡

LVS服务器接收到网络请求后,会根据配置的算法将请求转发给后边的服务器处理。为了实现高可用,一般情况下都会有至少两台LVS服务器,它们之间用KeepAlive定时通信。当备用LVS服务器无法接收到主LVS服务器的信息时,备用LVS服务器就认为主LVS已经宕机了,这时候备用LVS将自动切换为主LVS提供服务。

使用LVS架设的服务器集群系统有三个部分组成:最前端的负载均衡层(Loader Balancer),中间的服务器群组层,用Server Array表示,最底层的数据共享存储层,用Shared Storage表示。在用户看来所有的应用都是透明的,用户只是在使用一个虚拟服务器提供的高性能服务。LVS的体系架构如图:

LVS的各个层次的详细介绍:

  • Load Balancer层: 位于整个集群系统的最前端,有一台或者多台负载调度器(Director Server)组成,LVS模块就安装在Director Server上,而Director的主要作用类似于一个路由器,它含有完成LVS功能所设定的路由表,通过这些路由表把用户的请求分发给Server Array层的应用服务器(Real Server)上。同时,在Director Server上还要安装对Real Server服务的监控模块Ldirectord,此模块用于监测各个Real Server服务的健康状况。在Real Server不可用时把它从LVS路由表中剔除,恢复时重新加入。

  • Server Array层: 由一组实际运行应用服务的机器组成,Real Server可以是WEB服务器、MAIL服务器、FTP服务器、DNS服务器、视频服务器中的一个或者多个,每个Real Server之间通过高速的LAN或分布在各地的WAN相连接。在实际的应用中,Director Server也可以同时兼任Real Server的角色。

  • Shared Storage层: 是为所有Real Server提供共享存储空间和内容一致性的存储区域,在物理上,一般有磁盘阵列设备组成,为了提供内容的一致性,一般可以通过NFS网络文件系统共享数 据,但是NFS在繁忙的业务系统中,性能并不是很好,此时可以采用集群文件系统,例如Red hat的GFS文件系统,oracle提供的OCFS2文件系统等。
    从整个LVS结构可以看出,Director Server是整个LVS的核心,目前,用于Director Server的操作系统只能是Linux和FreeBSD,linux2.6内核不用任何设置就可以支持LVS功能,而FreeBSD作为 Director Server的应用还不是很多,性能也不是很好。对于Real Server,几乎可以是所有的系统平台,Linux、windows、Solaris、AIX、BSD系列都能很好的支持。

LVS 的IP负载均衡技术是通过IPVS模块来实现的,IPVS是LVS集群系统的核心软件,它的主要作用是:安装在Director Server上,同时在Director Server上虚拟出一个IP地址,用户必须通过这个虚拟的IP地址访问服务。这个虚拟IP一般称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达负载调度器,然后由负载调度器从Real Server列表中选取一个服务节点响应用户的请求。

当用户的请求到达负载调度器后,调度器如何将请求发送到提供服务的Real Server节点,而Real Server节点如何返回数据给用户,是IPVS实现的重点技术,IPVS实现负载均衡机制有三种:DR模式、NAT模式、Full-NAT模式、Tunnel模式,其中DR模式是使用最广泛的一种。

DR模式

特点:工作在数据链路层,由LVS修改请求报文的Mac地址,由RS服务器直接返回响应给客户端。

  • 用户按下按钮,发送接口请求,此时网络数据包关键信息为:【源IP:client_ip,目标IP:lvs_ip,Mac地址:lvs_mac_address】
  • 当用户请求到达LVS服务器的时候,LVS服务器直接将改网络数据包的Mac地址修改为RS服务器的Mac地址,之后将其转发到RS服务器。此时网络数据包关键信息为:【源IP:client_ip,目标IP:lvs_ip,Mac地址:rs_mac_address】
  • 当RS服务器接收到网络数据包时,RS服务器发现请求报文的Mac地址是自己的地址,就接收报文并进行处理。处理完成之后,将响应报文通过网卡向外发出。此时发出的响应报文数据包关键信息为:【源IP:lvs_ip,目标IP:client_ip,Mac地址:rs_mac_address】
  • 响应报文最终到达客户端

这种方式是三种负载调度机制中性能最高最好的,但是必须要求Director Server与Real Server都有一块网卡连在同一物理网段上。

NAT模式

特点:工作在网络层,由LVS修改请求报文的目标IP地址以及响应报文的源IP地址,必须经LVS返回给客户端。

  • 用户按下按钮,发送接口请求,此时网络数据包关键信息为:【源IP:client_ip,目标IP:lvs_ip,Mac地址:lvs_mac_address】
  • 当用户请求到达LVS服务器的时候,LVS服务器直接将改网络数据包的目标IP地址修改为RS服务器的IP地址(DNAT技术),之后将其转发到RS服务器。此时网络数据包关键信息为:【源IP:client_ip,目标IP:rs_ip,Mac地址:lvs_mac_address】(这里有一个问题,为什么Mac地址是lvs_mac_address,但数据包就能够到RS服务器呢?)
  • 当RS服务器接收到数据包后对比发现目标IP是自己的IP,于是构建响应报文发送给LVS服务器。此时网络数据包关键信息为:【源IP:rs_ip,目标IP:client_ip,Mac地址:client_mac_address】
  • LVS服务器接收到响应报文,修改响应报文的源IP地址为LVS的IP地址,然后响应给客户端。此时发出的响应报文数据包关键信息为:【源IP:lvs_ip,目标IP:client_ip,Mac地址:client_mac_address】
  • 响应报文最终到达客户端

NAT模式要求LVS和RS服务器必须在同一网段内,因此会导致运维上的困难。另外因为每次请求都需要经过LVS服务器,所以LVS服务器的压力会比较大。

Full-NAT模式

特点:工作在网络层,在LVS修改请求报文以及响应报文的源IP地址、目标IP地址,必须经LVS返回给客户端。

  • 用户按下按钮,发送接口请求。此时网络数据包关键信息为:【源IP:client_ip,目标IP:lvs_ip,Mac地址:lvs_mac_address】
  • 当用户请求到达LVS服务器的时候,LVS服务器直接将改网络数据包的源目标IP地址修改为LVS服务器的IP地址、目标IP地址修改为RS服务器的IP地址(SNAT技术、DNAT技术),之后将其转发到RS服务器。此时网络数据包关键信息为:【源IP:lvs_ip,目标IP:rs_ip,Mac地址:lvs_mac_address】
  • RS服务器接收到数据包,于是构建响应返回给LVS服务器。此时网络数据包关键信息为:【源IP:rs_ip,目标IP:lvs_ip】
  • 当LVS收到RS服务器的响应数据包后,LVS服务器直接将改网络数据包的源目标IP地址修改为LVS服务器的IP地址、目标IP地址修改为客户端的IP地址(SNAT技术、DNAT技术)。此时网络数据包关键信息为:【源IP:lvs_ip,目标IP:client_ip】
  • 响应报文最终到达客户端

Full-NAT模式是在NAT基础上为了解决跨子网问题而诞生的,其通过在网络层修改源IP地址和目标IP地址来达到不同子网的通信。

Tunnel模式

特点:工作在网络层,在原有IP报文外多封装一层IP报文,由RS服务器直接返回响应给客户端。

  • 用户按下按钮,发送接口请求。此时网络数据包关键信息为:【源IP:client_ip,目标IP:lvs_ip】
  • 当用户请求到达LVS服务器的时候,LVS服务器直接在原有报文外再次封装一层IP报文,封装的源IP地址为lvs_ip,目标IP地址为rs_ip,然后将其转发到RS服务器。此时网络数据包关键信息为:外部报文-->【源IP:lvs_ip,目标IP:rs_ip】,内部报文-->【源IP:client_ip,目标IP:lvs_ip】。
  • RS服务器接收到报文后发现时自己的IP地址,就将报文接收下来。拆除掉最外层的IP报文后,会发现里面还有一层IP报文,而且目标是lvs_ip,那么此时RS开始处理此请求,处理完成之后,直接将响应报文发送给客户端。此时网络数据包关键信息为:【源IP:lvs_ip,目标IP:client_ip】
  • 响应报文最终到达客户端。
工作模式所处OSI层级模式特点缺陷
DR模式数据链路层由LVS修改请求报文的Mac地址,由RS服务器直接返回响应给客户端LVS服务器和RS服务器必须要在同一级房
NAT模式网络层由LVS修改请求报文的目标IP地址以及响应报文的源IP地址,必须经LVS返回给客户端LVS和RS服务器必须在同一网段内
Full-NAT模式网络层在LVS修改请求报文以及响应报文的源IP地址、目标IP地址,必须经LVS返回给客户端-
Tunnel模式网络层在原有IP报文外多封装一层IP报文,由RS服务器直接返回响应给客户端-

其实与LVS相似的流量转发方案还有HAProxy。LVS与HAProxy都适合用来放在负载均衡的最前端,用于海量流量转发。在高可用支持上,他们都有对应的高可用方案,LVS与KeepAlive结合实现高可用,而HAProxy与heartbeat实现高可用。在配置难度上,LVS配置比较复杂,而HAProxy相对简单。在系统支持上,Linux系统对LVS有内核级别的支持,而HAProxy则没有。在性能上,LVS因为有系统内核级别的支持,所以其可以实现响应数据包不经过LVS,而HAProxy的响应数据包则必须经过HAProxy,这就导致了HAProxy的压力会比较大,也就是HAProxy性能没有LVS好。

Nginx负载均衡

当请求经过LVS服务器转发到达Nginx服务器后,Nginx会根据其负载配置文件将请求转发到具体的应用服务器进行处理。

与Nginx相似的软件还有apche、squid、lighttpd等负载均衡软件,但apache和squid属于同步模式的反向代理,在大文件的传输上会出现阻塞,导致后端服务器连接数过多,最终导致服务器压力过大。而Nginx和lighttpd则是使用异步模式的反向代理,代理在接受完数据之前不会与后端服务器建立连接,这样就避免了对后端服务器造成过大压力。

举个例子:当用户上传一个100M大的文件时,如果用户网速慢,需要半个小时才能上传完。如果采用apache、squid这种同步模式的反向代理,那么在接收过程中代理不仅会与客户端建立连接,还会有后台服务器建立连接。如果上传大文件的用户一多,那么后端服务器的压力就很大。而且因为广域网(WAN)和局域网(LAN)的传输速度差别很大,因此同步方式的反向代理会造成连接资源的浪费。而nginx和lighttpd异步模式的反向代理则是等代理完全接收完数据之后,才与后端服务器建立连接,这样就大大减少了后端的服务器的压力。

而nginx和lighttpd的异步模式也略有不同,lighttpd是先收完再转向客户浏览器,而nginx是边收数据边转向用户浏览器。因此nginx的异步代理模型可以更好地提供高性能的负载均衡,所以现在nginx也是许多企业级网站的首选。

软件名称代理特性工作细节
apache、squid同步模式在与客户端连接的同时,也与后端的服务器建立连接
lighttpd异步模式等待客户端传输完成才与后端服务器建立连接,同时不会返回数据给客户端
nginx异步模式等待客户端传输完成才与后端服务器建立连接,同时会返回数据给客户端

LVS 与 Nginx 的区别

既然LVS和Nginx都能实现负载均衡,那为什么要将Nginx作为LVS后端机器,而不是LVS作为Nginx的后端机器,他们之间到底有什么区别呢?

LVS设计就是用来进行流量转发的,功能比较单一,所以其在流量转发上性能更高、更稳定。LVS在流量转发的性能基本达到了F5硬件设备的60%性能,其他几个10%都有点困难。但也正是因为其效率高、稳定,所以导致了其功能单一,在应用场景方面比较单一。而Nginx功能强大,支持对域名、目录的解析,这使得其应用场景广泛。

简单地说:lvs只做简单转发,能做的事情也就很少,nginx功能全面,能满足很多的业务场景。

所以我们才说LVS更加适合做最前端的流量转发,挡住海量流量。而Nginx则适合放在应用服务器的上层,用来针对不同的请求进行目录识别或域名识别,从而达到功能模块的垂直分割。

参考资料