负载均衡我们有多个处理器,却没有操作系统分配请求
采用纵向扩展时,无需担心如何处理用户请求——这些请求都将汇集到单个服务器的网络接口卡上,并且得到处理,对它们的回复 也是通过网络接口卡发送的。而在不同处理器之间分配负载的具体任务,就交给操作系统调度程序来完成了。由于Apache是多进程的,可以给每个处理器分配 一个子进程,然后同时处理很多请求。
开始横向扩展时,新问题就出现了。我们有多个处理器,却没有操作系统分配请求。我们将在同一IP地址收到多个请求,而且希望在多台机器上服务这些请求。这些问题有多种解决方法,但它们全都从属于术语“负载平衡”。
最简单的,在多台Web服务器之间负载平衡的办法,负载均衡是在DNS区域(zone)中为应用程序的域创建不止“一条”记录。 DNS服务器打乱这些记录,并且随机发送给每个发出请求的主机。当用户在浏览器中输入地址时,浏览器询问DNS服务器(使用迭代查询),以返回对该域的一 个记录列表。DNS会返回一列地址,客户端从这个列表中的第一个开始尝试。在不考虑冗余和故障转移的情况下,基于DNS的负载平衡是目前最简单的在多个地 理区域均衡用户请求的方法。
这种负载平衡由于一些原因被称为“穷人的负载平衡”负载均衡。向池中添加和移除机器是个缓慢的过程。根据所在区域(zone)的 TTL和DNS服务器的缓存时间,要使对区域的更改对所有用户可见可能需要数天。在这段时间内,有些用户会看到老的区域,而有些会看到新的。很难做到快速 移除一台机器。如果一台机器死机了,得先找到它,更改区域,并且等待更改散播到各地的缓存中。在这台机器死机期间,对它的任何访问都可能被抑或不被重定向 到第二个IP地址,要看用户浏览器的具体行为。整个移除过程很难自动化。因为我们不希望它自动从DNS区域中删除自己,任何检查过程中的错误都会导致所有 服务器从IP列表中被删除,需要等待一段时间,让区域重建缓存和修复错误,在这段时间内,站点会完全处于下线状态。
DNS负载平衡的另一个问题是,它无法实现精确的控制,也不能定制均衡方式(至少不容易)。由于DNS缓存,一个用户可能在一台机器上阻塞达一个小时,甚至更长时间。如果很多用户共享一个DNS缓存,比如大型ISP的情况,大量的用户会阻塞在一台服务器
上。总的来说,DNS负载平衡并不是一个很实用的解决方案。
在寻求更好的负载平衡解决方案前,应该谈谈两种基本的负载平衡模式和它们的区别。对于PHP的“毫不共享”的应用程序模 型,来自客户端的每个请求都可以发送给池中的任何机器。这种无状态模式对负载平衡器的要求不多,因为它分别处理每个请求,并且不需要存放状态。对于带有共 享的本地数据和状态的应用程序,就需要确保在一次会话(不管“会话”具体如何定义)中,同一用户的每个请求都访问同一台服务器。这种粘滞会话 (sticky session)需要负载平衡器提供更多的逻辑和资源,而有些负载平衡的解决方案不提供这些。
Sticky Sessions粘滞会话
大多数4层的负载平衡器支持某种粘滞会话,在 其中负载均衡客户端的每个请求都被路由到同一台后端服务器。用来实现这种负载平衡的方案各有不同,但往往用到比较高的层次,要在客户端设置cookie或者对它 的HTTP请求细节应用Hash算法来创建客户端签名。在粘滞会话这个话题上,我们不会展开讨论,因为在REST模型下,它们不是必须的,这是相当幸运 的,因为可以绕开粘滞会话环境中的故障转移方面的问题。
和现代计算机的其他领域一样,你至少得熟悉一个三字母缩写——VIP。负载均衡也就是虚拟IP,一个VIP是由负载平衡器提供的一个IP地址,背后其实有多个“实际的”IP地址在处理请求。负载平衡器也被称作“虚拟服务器”,而池中的节点就是“实际服务器”。
硬件方式的负载平衡
要在池中多台机器间实现请求负载平衡,最直接的方式是使用硬件设备。只要接上硬件,打开它,完成一些基本的(或更常见的, 非常复杂的)配置,就可以开始分担流量。但使用硬件设备有一些缺点。它在可配置性方面很差,尤其是管理大型的VIP(带有很多实际服务器)时,因为配置界 面往往是复杂的基于telnet的命令行,或者20世纪90年代初期的Web界面。任何对配置的改动或检查都是手工的过程,或者是编写一套脚本,通过调用 底层自身接口,进行远程操的过程。具体要看程序的规模,这一点有可能不是什么大问题,尤其是在你打算配置好设备之后就很长时间不去管它,让它自己运作的情 况下。
相关信息