架构高性能网站秘笈(七)——负载均衡

什么是负载均衡?

当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能。那么,在服务器集群中,需要有一台服务器充当调度者的角色,用户的所有请求都会首先由它接收,调度者再根据每台服务器的负载情况将请求分配给某一台后端服务器去处理。

那么在这个过程中,调度者如何合理分配任务,保证所有后端服务器都将性能充分发挥,从而保持服务器集群的整体性能最优,这就是负载均衡问题。

下面详细介绍负载均衡的四种实现方式。

HTTP重定向实现负载均衡

过程描述

当用户向服务器发起请求时,请求首先被集群调度者截获;调度者根据某种分配策略,选择一台服务器,并将选中的服务器的IP地址封装在HTTP响应消息头部的Location字段中,并将响应消息的状态码设为302,最后将这个响应消息返回给浏览器。

当浏览器收到响应消息后,解析Location字段,并向该URL发起请求,然后指定的服务器处理该用户的请求,最后将结果返回给用户。

在使用HTTP重定向来实现服务器集群负载均衡的过程中,需要一台服务器作为请求调度者。用户的一项操作需要发起两次HTTP请求,一次向调度服务器发送请求,获取后端服务器的IP,第二次向后端服务器发送请求,获取处理结果。

调度策略

调度服务器收到用户的请求后,究竟选择哪台后端服务器处理请求,这由调度服务器所使用的调度策略决定。

  1. 随机分配策略 当调度服务器收到用户请求后,可以随机决定使用哪台后端服务器,然后将该服务器的IP封装在HTTP响应消息的Location属性中,返回给浏览器即可。
  2. 轮询策略(RR) 调度服务器需要维护一个值,用于记录上次分配的后端服务器的IP。那么当新的请求到来时,调度者将请求依次分配给下一台服务器。

由于轮询策略需要调度者维护一个值用于记录上次分配的服务器IP,因此需要额外的开销;此外,由于这个值属于互斥资源,那么当多个请求同时到来时,为了避免线程的安全问题,因此需要锁定互斥资源,从而降低了性能。而随机分配策略不需要维护额外的值,也就不存在线程安全问题,因此性能比轮询要高。

优缺点分析

采用HTTP重定向来实现服务器集群的负载均衡实现起来较为容易,逻辑比较简单,但缺点也较为明显。

在HTTP重定向方法中,调度服务器只在客户端第一次向网站发起请求的时候起作用。当调度服务器向浏览器返回响应信息后,客户端此后的操作都基于新的URL进行的(也就是后端服务器),此后浏览器就不会与调度服务器产生关系,进而会产生如下几个问题:

  • 由于不同用户的访问时间、访问页面深度有所不同,从而每个用户对各自的后端服务器所造成的压力也不同。而调度服务器在调度时,无法知道当前用户将会对服务器造成多大的压力,因此这种方式无法实现真正意义上的负载均衡,只不过是把请求次数平均分配给每台服务器罢了。
  • 若分配给该用户的后端服务器出现故障,并且如果页面被浏览器缓存,那么当用户再次访问网站时,请求都会发给出现故障的服务器,从而导致访问失败。

DNS负载均衡

DNS是什么?

在了解DNS负载均衡之前,我们首先需要了解DNS域名解析的过程。

我们知道,数据包采用IP地址在网络中传播,而为了方便用户记忆,我们使用域名来访问网站。那么,我们通过域名访问网站之前,首先需要将域名解析成IP地址,这个工作是由DNS完成的。也就是域名服务器。

我们提交的请求不会直接发送给想要访问的网站,而是首先发给域名服务器,它会帮我们把域名解析成IP地址并返回给我们。我们收到IP之后才会向该IP发起请求。

那么,DNS服务器有一个天然的优势,如果一个域名指向了多个IP地址,那么每次进行域名解析时,DNS只要选一个IP返回给用户,就能够实现服务器集群的负载均衡。

具体做法

首先需要将我们的域名指向多个后端服务器(将一个域名解析到多个IP上),再设置一下调度策略,那么我们的准备工作就完成了,接下来的负载均衡就完全由DNS服务器来实现。

当用户向我们的域名发起请求时,DNS服务器会自动地根据我们事先设定好的调度策略选一个合适的IP返回给用户,用户再向该IP发起请求。

调度策略

一般DNS提供商会提供一些调度策略供我们选择,如随机分配、轮询、根据请求者的地域分配离他最近的服务器。

优缺点分析

DNS负载均衡最大的优点就是配置简单。服务器集群的调度工作完全由DNS服务器承担,那么我们就可以把精力放在后端服务器上,保证他们的稳定性与吞吐量。而且完全不用担心DNS服务器的性能,即便是使用了轮询策略,它的吞吐率依然卓越。

此外,DNS负载均衡具有较强了扩展性,你完全可以为一个域名解析较多的IP,而且不用担心性能问题。

但是,由于把集群调度权交给了DNS服务器,从而我们没办法随心所欲地控制调度者,没办法定制调度策略。

DNS服务器也没办法了解每台服务器的负载情况,因此没办法实现真正意义上的负载均衡。它和HTTP重定向一样,只不过把所有请求平均分配给后端服务器罢了。

此外,当我们发现某一台后端服务器发生故障时,即使我们立即将该服务器从域名解析中去除,但由于DNS服务器会有缓存,该IP仍然会在DNS中保留一段时间,那么就会导致一部分用户无法正常访问网站。这是一个致命的问题!好在这个问题可以用动态DNS来解决。

动态DNS

动态DNS能够让我们通过程序动态修改DNS服务器中的域名解析。从而当我们的监控程序发现某台服务器挂了之后,能立即通知DNS将其删掉。

综上所述

DNS负载均衡是一种粗犷的负载均衡方法,这里只做介绍,不推荐使用。

反向代理负载均衡

什么是反向代理负载均衡?

反向代理服务器是一个位于实际服务器之前的服务器,所有向我们网站发来的请求都首先要经过反向代理服务器,服务器根据用户的请求要么直接将结果返回给用户,要么将请求交给后端服务器处理,再返回给用户。

之前我们介绍了用反向代理服务器实现静态页面和常用的动态页面的缓存。接下来我们介绍反向代理服务器更常用的功能——实现负载均衡。

我们知道,所有发送给我们网站的请求都首先经过反向代理服务器。那么,反向代理服务器就可以充当服务器集群的调度者,它可以根据当前后端服务器的负载情况,将请求转发给一台合适的服务器,并将处理结果返回给用户。

优点

  1. 隐藏后端服务器。 与HTTP重定向相比,反向代理能够隐藏后端服务器,所有浏览器都不会与后端服务器直接交互,从而能够确保调度者的控制权,提升集群的整体性能。
  2. 故障转移 与DNS负载均衡相比,反向代理能够更快速地移除故障结点。当监控程序发现某一后端服务器出现故障时,能够及时通知反向代理服务器,并立即将其删除。
  3. 合理分配任务 HTTP重定向和DNS负载均衡都无法实现真正意义上的负载均衡,也就是调度服务器无法根据后端服务器的实际负载情况分配任务。但反向代理服务器支持手动设定每台后端服务器的权重。我们可以根据服务器的配置设置不同的权重,权重的不同会导致被调度者选中的概率的不同。

缺点

  1. 调度者压力过大 由于所有的请求都先由反向代理服务器处理,那么当请求量超过调度服务器的最大负载时,调度服务器的吞吐率降低会直接降低集群的整体性能。
  2. 制约扩展 当后端服务器也无法满足巨大的吞吐量时,就需要增加后端服务器的数量,可没办法无限量地增加,因为会受到调度服务器的最大吞吐量的制约。

粘滞会话

反向代理服务器会引起一个问题。若某台后端服务器处理了用户的请求,并保存了该用户的session或存储了缓存,那么当该用户再次发送请求时,无法保证该请求仍然由保存了其Session或缓存的服务器处理,若由其他服务器处理,先前的Session或缓存就找不到了。

解决办法1: 可以修改反向代理服务器的任务分配策略,以用户IP作为标识较为合适。相同的用户IP会交由同一台后端服务器处理,从而就避免了粘滞会话的问题。

解决办法2: 可以在Cookie中标注请求的服务器ID,当再次提交请求时,调度者将该请求分配给Cookie中标注的服务器处理即可。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏运维小白

1-3 CCNA

IP地址 是逻辑地址 用来确定一个网络中的一个节点,或者一个设备 两台主机通信,必须要有IP地址,32位二进制数,为了便于记忆,转换成10进制数,如 192....

34415
来自专栏猿人谷

长连接和短连接分析

1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接 时...

2858
来自专栏彭湖湾的编程世界

【计算机网络】TCP通信的细节及TCP连接对HTTP事务处理性能影响

从三次握手的细节说起 刚开始尝试使用java等后端语言写IO流,或用套接字(socket)实现简单C/S通信的同学们,常常会接触到的一个概念:就是所谓的“三次握...

1936
来自专栏xcywt

网络编程的一些理论

参考自《VC++深入详解》   这是我在看书时记录下来的东西。  注:下面的Socket其实都应该是socket 第14章网络编程 Socket是连接应用程序与...

2015
来自专栏JetpropelledSnake

Python Web学习笔记之面试TCP的15个问题

网络协议那么多,为什么面试喜欢问TCP?原因无外乎两个:1、TCP协议直接与进程打交道,写网络程序要用;2、TCP协议设计十分精巧,在一个不可靠的IP网络上实现...

4209
来自专栏xingoo, 一个梦想做发明家的程序员

简单的客户机服务器投射模拟

下面模拟了,简单的客户机服务器投射模拟的过程。客户机像服务器发送数据,服务器接受到数据后,发送回给客户机。再由客户机打印出来。 需要的函数: 网络方面 服务器 ...

1725
来自专栏smy

chrome浏览器Timing内各字段解析

Queueing 请求文件顺序的的排序 ? Stalled 是浏览器得到要发出这个请求的指令到请求可以发出的等待时间,一般是代理协商、以及等待可复用的TCP连接...

2835
来自专栏java 成神之路

网络传输 相关概念

3185
来自专栏木子昭的博客

简单易懂的udp实现简单的udp请求服务模式

实现简单的udp请求服务模式 udp 是一种简单传输协议,实现简单,占用系统资源少 ---- 运行结果 ? 客户端 ? 服务端 服务端代码 # _*_ c...

2716
来自专栏xingoo, 一个梦想做发明家的程序员

TCPServer TCPClient三次握手模拟编程

套接字创建和关闭: SOCKET socket(int af,int type,int protocal); 套接字类型: SOCK_STREAM 流套接字...

19610

扫码关注云+社区