本节书摘来自异步社区《DNS与BIND(第5版)》一书中的第10章,第10.7节,作者: 【美】Joseph Davies 更多章节内容可以访问云栖社区“异步社区”公众号查看。
10.7 轮询调度(Round-Robin)负载分配
自BIND 4.9发布之后,名称服务器已经正式支持一些过去必须通过补丁才能实现的负载分配功能。Bryan Beecher曾给BIND 写过一个补丁,以实现他所谓的“轮转地址记录(shuffle address records)”。这是一组特殊类型的地址记录,名称服务器会在响应查询时轮转其中的地址。例如,域名foo.bar.baz有3个“可轮转”IP地址:192.168.1.1,192.168.1.2和192.168.1.3。一台打好补丁的名称服务器第一次响应查询时的顺序为:
第二次响应查询的顺序为:
![f26c15471171f610a4a68fd1d2c333d6e0b40d07](https://yqfile.alicdn.com/f26c15471171f610a4a68fd1d2c333d6e0b40d07.png?x-oss-process=image/resize,w_1400/format,webp)
第三次响应查询的顺序为:
然后再从第一次的顺序开始,并永无止境地重复轮转下去。
如果有许多等效的网络资源,例如镜像FTP服务器、web服务器或终端服务器,并且打算在它们之间分担负载,那么这个功能会非常有用。可以为这组资源建立一个域名,并且配置客户端访问该域名,名称服务器便会根据列出的IP地址来分配查询请求。
BIND 8和9不再把轮转地址记录作为一个单独的记录类型,因为那样需要特殊处理。取而代之的是,对拥有超过一条A记录的任意域名,现代的名称服务器都会进行地址轮转。(事实上,对于任意的记录类型,只要一个给定的域名拥有多条此类记录,名称服务器就会轮转它们1。)对于如下记录:
BIND 8或9名称服务器,就像打过补丁的版服务器一样,可以完成轮转地址记录。BIND文档将这一过程称之为轮询调度(round-robin)。
正如示例中所做的那样,降低这些记录的生存时间也是个好主意。如果这些地址被缓存在一个不支持轮询调度的中间名称服务器上,这样做确保它们很快会由于超时被移出缓存。当中间名称服务器再次查询该名称时,权威名称服务器就能再次轮询调度这些地址。
注意,实际上轮询调度提供的是负载分配,而非负载均衡,因为名称服务器并不考虑提供服务的服务器的实际负载和能力,它只是按照预定的方式给出这些IP地址。在示例中,IP地址为192.168.1.3的服务器可能是一台运行Linux的486DX33老爷机,而另外两台是HP 9000 Superdomes服务器,可是这台Linux老爷机仍然分到了三分之一的查询。就算多次列出高性能服务器的IP地址也于事无补,因为BIND会消除重复的记录。
10.7.1 多条CNAME记录
回到BIND 4名称服务器的全盛时期,有些人使用多条CNAME记录(而非多条地址记录)的方式设置轮询调度:
这样的设置看上去可能很奇怪,因为本书反复强调不要把任何东西和CNAME记录混淆。但是BIND 4名称服务器不认为这是配置错误,它只会简单地以轮询调度的方式返回foo.bar.baz的CNAME记录2。
另一方面,BIND 8名称服务器更加警觉并且能够发现这种错误。但是,可以明确配置是否允许单一域名拥有多条CNAME记录:
![a08289a0b4f6b6c09c230b0f8b3209c5ae289452](https://yqfile.alicdn.com/a08289a0b4f6b6c09c230b0f8b3209c5ae289452.png?x-oss-process=image/resize,w_1400/format,webp)
然而,本书并不认为应该这么做。
BIND 9名称服务器在版之前没有注意到多条CNAME的问题。从9.1.0版开始,BIND能够检测出问题,但是不支持用multiple-cnames语句允许多条CNAME记录。本书认为这是正确的做法:因为给单一域名指定多条CNAME记录违反了DNS标准(特别是RFC 2181),所以请不要这样做。
10.7.2 rrset-order子语句
有时可能不希望名称服务器使用轮询调度。例如,指定一台web服务器充当另一台的备机。这时,名称服务器在应答时,应该总是将备机地址排在主web服务器地址之后。但是使用轮询调度无法达到目的:因为每次响应查询后,名称服务器都会将地址顺序进行轮转。
BIND 8.2及其后续版本的名称服务器以及BIND 及其后续版本的名称服务器,允许关闭特定域名及记录类型的轮询调度功能。例如,可以使用rrset-order子语句,确保名称服务器总是以固定顺序返回www.movie.edu的地址记录:
![4f5e010af85cc46511572f3b6ab281f2bdbbe4e1](https://yqfile.alicdn.com/4f5e010af85cc46511572f3b6ab281f2bdbbe4e1.png?x-oss-process=image/resize,w_1400/format,webp)
还应该尽量降低www.movie.edu的地址记录的TTL值,以免这些未经轮询调度的记录在名称服务器上缓存过长时间。
class(类)、type(类别)及name(名称)设置,用来决定哪些记录会应用指定的顺序。class默认为IN,type默认为ANY,name默认为*(也就是任何记录)。所以下面的语句:
会在名称服务器应答的所有记录上使用随机的顺序。在name设置中,最左边的标签可能是一个通配符,如下所示:
![cb441f7fb5dfee5c7eef40fd3b806aab04f4c28d](https://yqfile.alicdn.com/cb441f7fb5dfee5c7eef40fd3b806aab04f4c28d.png?x-oss-process=image/resize,w_1400/format,webp)
虽然仅允许使用一个rrset-order子语句,但是其中可以包含多个顺序规则。与一组记录最先匹配的顺序规则将会应用到应答中。
rrset-order支持以下3种顺序。
fixed
总是以相同的顺序返回匹配的记录。
random
以随机的顺序返回匹配的记录。
cyclic
以循环(轮询调度)的顺序返回匹配的记录。
可惜,BIND 尚未完全支持fixed顺序3。
默认的配置是:
不幸的是,配置rrset-order并不是一个完整的解决方案,因为解析器和名称服务器的缓存会干扰其工作。一个更好的解决方案是SRV记录,本书将在第17章加以讨论。