DNS全局负载均衡(GSLB):原理与实践

说实话,刚开始接触多活架构那会儿,我一听“GSLB”三个字母就觉得特别高大上。后来踩了几个坑才明白——GSLB说白了就是DNS的“智能进化版”。它不再是傻傻地返回一个IP,而是根据你定好的策略,给用户“最合适”的那个入口。

我习惯把GSLB放在路由策略的最外层。你想想看,用户的第一个落点在哪?DNS啊。如果第一跳就选错了数据中心,后面再怎么做故障转移都慢半拍。所以这一章,我就把GSLB从原理到实战掰开揉碎讲清楚。

为什么需要GSLB?

传统DNS解析有个大问题:它不管后端是否活着。一台服务器挂了,用户依然会被解析到那个IP,然后干等超时。我在项目中遇到过不止一次:上海数据中心宕机了40分钟,第三方DNS缓存还没刷新,江苏用户还在拼命连那个挂掉的节点。老板急了,我也急了。从那之后,我深切体会到——

没有健康检查的DNS,就是盲人送快递。

GSLB要解决三个核心问题:

  • 多数据中心之间的流量调度——谁来接客?
  • 自动故障转移——挂了怎么办?
  • 就近接入——用户离谁近就找谁。

GSLB的工作原理

我习惯把它拆成四步走:

  1. 用户发起DNS查询——比如请求 www.yourapp.com。
  2. 本地DNS转发——最终落到GSLB专用的权威DNS服务器上。
  3. GSLB决策引擎——根据健康检查结果、地理位置、当前负载等,算出最佳IP。
  4. 返回IP并缓存——用户拿到IP后直连对应的数据中心。

你看,核心就藏在第三步。我自己的经验是:GSLB决策必须快,而且要跟后端健康检查实时联动。我曾经见过某家厂商的GSLB,健康检查周期设成60秒,结果故障后整整一分钟还在给用户发故障IP。嗯,这个坑得提前避开。

重要:GSLB的TTL不要设太长。我习惯把TTL控制在60~120秒。太长的话,故障切换后用户继续用旧缓存;太短的话,DNS查询压力激增。两难,但秒级TTL是主流。

健康检查:GSLB的命脉

没有健康检查的GSLB就是空中楼阁。基于我的实践,健康检查至少要覆盖三个层面:

  • ICMP Ping——机器活着吗?(最基础)
  • 端口探测——比如HTTP 80端口通不通。
  • 业务探针——模拟一次用户请求,看接口正确返回。

我推荐组合使用。有一次我单靠端口探测,结果WEB服务正常但后端数据库挂了,GSLB照样返回“健康”状态,用户点进去还是报错。后来我用业务探针,模拟一次登录请求,才真正把“假活”揪出来。

小技巧:健康检查的探测源最好分布在多个地域,避免单一探测点误判。我自己会至少放两个探针,一个在北京,一个在广州,交叉验证。

路由策略对比

GSLB支持多种调度策略,我把常用的几种放在一个表里,这样你一眼就能看清差异。

策略原理适用场景我的踩坑点
轮询(Round Robin) 按顺序返回不同数据中心的IP 各中心能力均等 没考虑真实负载,容易导致个别节点被打爆
地理就近(Geo) 根据用户IP所属区域返回最近节点 用户体验优先 曾因GeoIP数据库老旧,把上海用户调度到了重庆
响应时间 实时探测各节点响应,返回最快的 追求性能 探测开销大,且容易被瞬间抖动误导
权重(Weight) 按人工设定的比例分配流量 灰度发布或硬件差异 权重一设错,某个中心直接跑满

实际生产里,我往往不会只用一种。比如我会把“地理就近”作为主策略,再叠加一个“响应时间”兜底——如果最近节点响应太慢,自动切到次优节点。这个组合我跑了大半年,效果不错。

一个典型的GSLB流程(SVG图)

下面这张图梳理了从用户输入URL到最终返回IP的全流程。自己画完才发现,中间每一步都有可能出幺蛾子。

GSLB 工作流程图 客户端 本地DNS GSLB 权威DNS(决策引擎) 健康检查模块 数据中心A 数据中心B 说明:箭头方向表示数据流向。健康检查模块定期探测A/B状态,GSLB据此决策。

代码示例:用BIND 9实现简单GSLB

我在实验环境用过BIND 9的views配合加权轮询。核心思路是:给不同客户端区域返回不同的A记录。下面是个简化配置,我摘几句关键的:

// named.conf 的 GSLB 区域片段
zone "example.com" {
    type master;
    file "example.com.zone";
};

// example.com.zone 文件
$TTL 60
@ IN SOA ns1.example.com. admin.example.com. (
    20250301 ; serial
    3600 ; refresh
    900 ; retry
    864000 ; expire
    60 ; minimum
)

; 华南地区 -> 优先广州数据中心
view "south" {
    match-clients { 14.0.0.0/8; 58.0.0.0/8; };
    zone "example.com" {
        type master;
        file "example.com.south.zone";
    };
};

; 华东地区 -> 上海数据中心
view "east" {
    match-clients { 101.0.0.0/8; 115.0.0.0/8; };
    zone "example.com" {
        type master;
        file "example.com.east.zone";
    };
};

你看,这样就可以做到按地理区域返回不同IP。但注意:GSLB的配置一定要跟健康检查联动。我当初只是手动配置了静态view,结果上海挂了,华南用户依然傻等。后来我加了个外部脚本,一旦探测到某节点故障,自动切换该view指向备用IP。这才是真正的GSLB。

避坑指南

  • TTL陷阱: 我曾经把TTL设成3600秒,故障切换后用户一个小时都还走老路。现在低于120秒我都不舒服。
  • 健康检查误报: 只做ping不够。一定带上业务探针。
  • GeoIP精度: 别迷信GeoIP库。我遇到过一个运营商IP被识别成另一个省份,导致调度混乱。定期更新库,或加上人工白名单。
  • 权重计算: 权重总和不要超过100,也不要太接近(比如99:1),否则微小的健康变化会导致雪崩。

GSLB是多活路由的第一道闸门。它的配置看似简单,但坑都在细节里。我每次新项目上线前,都会做一次完整的“GSLB演练”:拔掉一条链路,看DNS切换耗时多少,用户侧感知如何。嗯,建议你也试试。