《构建高性能的WEB站点》这本书在很多年很多年之前阅读过,但是阅读没那么深入,时间久了也就忘的差不多了,最近又阅读一遍,还是做一些笔记吧 好记性,不如烂笔头。
一些思考对于web站点的水平扩展,负债均衡是一种常见的手段,我们除了关注性能之外,高可用性也会有所涉及。
一.HTTP重定向 对于http重定向。你一定不陌生,他可以将http请求进行转移,在web开发中我们经常会用他来完成自动跳转,比如用户登录后跳转到相应的主页。 这种重定向完全由HTTP定义,并且由HTTP代理和web服务器共同实现,例如:当http代理(比如浏览器)向web服务器请求某个URL后,web服务器可以通过http响应头信息中的Location标记来返回一个新的URL,这意味http代理需要继续请求这个新的URL,这便完成了自动跳转。 正是http重定向具备了请求转移和自动跳转的本领,所以除了满足应用程序需要的各种自动跳转之外,他还可以实现负载均衡,以达到web扩展的目的。 镜像下载 在很多线上的站点都会有下载的功能,大部分都使用到http重定向,而镜像下载的目的便是实现负载均衡,
例如我们看这个链接:www.php.net/get/php-5.2.9.tar.gz/from/a/mirror
我们在浏览器中访问这个地址,并且监视http请求和响应,我们在请求头中看到了
Location:http//cn.php.net/get/php-5.2.9.tar.gz/from/a/mirror
并且http的状态码是302,我们刚才向php.net主站点发出的下载请求被转移到了cn.php.net站点,这样相当于主站点将一部分负载转移到了其他服务器上了。
+接下来我们再次请求主站点php.net的URL,查看请求头信息:
http状态码是302,
Location:http://cn2.php.net/get/php-5.2.9.tar.gz/from/a/mirror
+这里php.net,主站点负责进行地域来源判断以及选择镜像服务,值得一提的是。这里的重定向方案,在实现负载均衡的同时,也达到了就近访问的目的,加快了用户的下载速度。 重点向的性能和扩展能力 我们这里指的性能,实际上是针对主站点来说的,因为它负责转移请求到其他服务器,主站点决定着整个负载均衡系统的扩展能力,也意味着整个系统的最大承载能力。 重定向策略分析: 随机策略:
当每次请求访问到主站点的时候,程序会随机挑选其中一台服务器,然后返回重定向指令。(性能要优与轮询策略) 轮询策略(RR)
*1 . 主站点将所有的请求按照顺序依次转移给所有的服务器,实现绝对意义上的均衡,与此同时,性能上的代价也会不可避免降低。
*2 . Apache的mod_rewrite模块,它可以轻松支持RR重点向 优缺点对比 一般我们都是对站点首页做重定向,也就是站点入口,而站点内页的连接地址我们一般在首页上采用相对地址或者根相对地址,这样一来,一旦用户通过入口时被转移到某台实际服务器后,用户的一系列请求将直接进入这台实际服务器,不同用户对站点内页面的访问深度是不同的,这也是我们无法控制的,这样一来,多台实际服务器的负载时不可预料的,而主站点对此却一无所知。 更让人无赖的是,你无法保证用户始终从站点首页进入站点,也就是用户会跳过你精心设计的主站点调度程序。所以大多数情况下通过重定向来实现整个站点的负载均衡,并不那么让人满意。 虽然他有那么多缺点和和性能问题,但是在某些场景下还是能体现出它的优点,比如文件下载,广告展示等一次性的请求,主站点调度程序可以牢牢的把握控制权,这种一次性的请求,也比较容易让多台服务器保持均衡的负载 二. DNS负载均衡
DNS负责提供域名解析服务,当我们访问某个站点时,实际上首先需要通过该站点域名的DNS服务器来获取域名指向的IP地址,在这一过程中,我们的DNS服务器完成了域名到IP地址的映射,同样,这种映射也是可以一对多的,这个时候,DNS服务器便充当了负载均衡调度器(也称均衡器)
扩展能力和可管理性 和上面的重定向负载均衡相比,基于DNS的负载均衡完全节省了主站点,或者说DNS服务器充当了主站点的职能。 作为调度器,DNS服务器本身的性能我们几乎不担心,因为事实上,DNS记录可以被用户浏览器或者互联网接入服务商的各级DNS服务器缓存,只有当缓存过期后才会重新向该域名的DNS服务器请求解析,所以我们即便采用了RR调度策略,我们也几乎不会遇到DNS服务器成为性能瓶颈的问题。另一方面我们一般会配置两台以上的DNS服务器来提高可用性。 当我们不必考虑DNS服务器扩展和性能担忧的时候,另一方面的问题随之暴露,如何管理这么多服务器你?比如内容同步、数据共享、状态监控等问题都尤为重要,这些是我们使用DNS服务器需要考虑的问题。 智能解析 尽管基于HTTP重定向的负载均衡系统受到主站点的性能制约,但是不可否认这种方案中的调度策略具有非常好的灵活性,你完全可以通过web程序实现任何你想到的调度策略。 相比之下,DNS服务器服务器开发自定义的调度策略就不那么容易了,但幸运的是,类似bind这样的DNS服务器提供了丰富的调度策略供你选择,其中最常用的就是根据用户的IP来进行智能解析,这就意味着DNS服务器可以在所有可用的A记录中寻找离用户最近的一台服务器。 故障转移 当某台服务器出现故障,这个时候就需要我们立刻将他从调度策略中拿掉,也就是暂停指向该服务器的DNS记录,以免用户访问到发生故障的服务器而感到莫名其妙。 基于DNS服务器的负载均衡,要做到这一点的确让人非常头痛,因为一个现实问题是,我们一般不会将DNS记录的TTL设置为0,这使得所有对DNS记录的修改都需要一定时间才能生效,比如一个DNS记录的TTL为3600秒,那么对它的更新需要一个多小时才能生效。 以上的问题有一个比较好的解决办法,动态DNS,这其实是DNS协议的一个特性。它允许DNS服务器开发特定的服务,为我们自动化远程修改DNS。 动态解析域名,它做的事情很简单,就是每次IP地址变更时,及时的更新DNS服务器,当然,一定的延时仍然在所难免,同样是因为DNS记录的TTL。 一些不足 由于DNS记录的缓存带来的更新延迟,这导致我们对于调度器的控制总是跟不上节奏 相比HTTP重定向方式的调度器,DNS服务器更像魔术师,它可以在用户面前很好的隐藏实际服务器,但是与此同时,它也给服务器运维人员的调试带来了一些不便。 基于DNS负载均衡框架之下,负载均衡调度器工作在DNS层面,这导致它的灵活性被或多或少的消弱了,策略的开发性存在一定的局限性。 三.反向代理负载均衡反向代理服务器的核心工作是转发HTTP请求,因为他工作在HTTP层面,也就是TCP七层中应用层(第七层),所以基于反向代理的负载均衡也称为第七层负载均衡,实现它并不难,目前几乎所有主流的web服务器都热衷于支持基于反向代理的负载均衡,相比上面的HTTP重定向和DNS解析,作为负载均衡调度器的反向代理,对于HTTP请求的调度体现在-转发上,而前者则是转移
单纯的区分的这些概念并没有上面意义,你需要明白的是,这种机制的改变,使得调度器完全扮演用户和实际服务器的中间人,这意味着: 任何对于实际服务器的HTTP请求都必须经过调度器; 调度器必须等待实际服务器的HTTP响应,并将它反馈给用户。 按照权重分配任务刚才我们提到,在这种全新的调度模式下,任何对于实际服务器的HTTP请求都必须经过调度器,这使得我们一直以来苦恼的问题有望解决了,那就是可以将调度策略落实到每一个HTTP请求,从而实现更加可控的负载均衡。
本着能者多劳的原则,有些反向代理服务器可以非常精准的控制分配权重,比如我们经常用到的nginx服务器。
比如我们有两台服务器10.0.12.100 | 10.0.12.201,我们在另一台IP10.1.0.210的服务上运行nginx,作为反向代理服务器,也就是负载均衡调度器,并为它配置两个后端服务器,如下: upstream backend{ server 10.0.12.100:80 weight = 3; server 10.0.1.201:80 weight = 1; } # weight 是设置服务器的权重比例 这样我们可以根据服务器的配置来设置权重比 调度器的并发处理能力 反向代理服务器本身的并发处理能力显得尤为重要。 扩展的制约
前面我们说到了调度问题和负载权重问题,那我们还有一个最关心的问题就是负载均衡系统的扩展能力,反向代理服务器是工作在HTTP层面,对于HTTP请求都要亲自转发,你也许在怀疑它究竟有多大能耐,能支撑多少后端服务器,的确,这直接关系到整个服务器的扩展能力。
image.png 从图上分析 当num=100000时,内容处理开销最大,负载均衡系统的整体吞吐率几乎等于两台后端服务器的吞吐率之和,随后当num减少,整体吞吐率开始渐渐的落后于两台后端服务器的吞吐率之和,当num=1000的时候,整体吞吐率甚至还不如任意一个后端服务器的吞吐率高。 虽然我们只用了两台后端服务器,但已经暴露了负载均衡调度的瓶颈,这种瓶颈效应随着后端服务器处理时间的减少而逐渐明显,这不难理解,反向代理服务器进行转发操作本身是需要一定开销的,比如创建线程,与后端服务器建立TCP连接、接收后端服务器返回的处理结果、分析HTTP头信息、用户控件和内核空间的频繁切换等,通常这部分时间并不长,但是当后端服务器处理请求的时间非常短时,转发的开销就显得尤为突出。 健康探测
这里介绍一下Varnish的探测器。
粘滞会话负载均衡调度器最大程度的让用户不必关心后端服务器,我们知道,当采用RR调度策略时,即便是同一个用户对同一内容的多次请求,也有可能被转发到不同的后端服务器,这听起来似乎没什么大碍,但有时候,或许会带来一些问题:
当某台后端服务器启用了session来本地化保存用户的一些数据,下次用户的请求如果转发给了其他后端服务器,将导致之前的session数据无法访问: 后端服务器实现了一定的动态内容缓存,而毫无规律的转发使得这些缓存的利用率下降。如何来解决这些问题你?我们需要做的就是调整调度策略,让用户在一次会话周期内的所有请求始终转发到一台特定的后端服务器上,这种机制也称为粘滞会话,要实现它的关键在于如何设计持续性调度算法:
既然要让调度器可以识别用户,那么将用户的IP地址作为识别标志最为合适,一些反向服务器对此都有支持,比如nginx和HAProxy,他们可以将用户的IP地址进行Hash计算并散列到不同的后端服务器上。 还可以利用Cookies机制来设计持久性算法,比如调度器将某个后端服务器的编号追加到写给用户的Cookies中,这样调度器便可以在改用户随后的请求中知道应该转发给那台服务器。 我们希望将同一URL的请求始终转发到同一台特定的后端服务器,以充分利用后端服务器针对该URL进行的本地化缓存,要实现这一点,HAProxy也提供了支持,我们使用uri策略
版权申明:本站文章均来自网络,如有侵权,请联系01056159998 邮箱:itboby@foxmail.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有