侧边栏壁纸
  • 累计撰写 185 篇文章
  • 累计收到 2 条评论

网站配了智能 DNS 分线路解析搜索收录却断崖暴跌?排查搜索引擎专线悬空、ECS 递归识别失效与 TTL 缓存陷阱我踩过的几个坑

2026-10-11 / 0 评论 / 5 阅读
AI 摘要由 AI 生成

文章探讨了网站优化后搜索引擎抓取量骤降的问题,分析了智能DNS配置错误导致的搜索引擎专线失效、ECS递归识别失效和TTL缓存陷阱等几个关键坑点,并提供了相应的排查和验证方法。

前阵子我给站点的接入层做了一次优化。当时算了一笔账:全站图片和静态文件虽然上了 CDN,但动态页面和文章页每天被各大搜索引擎爬虫扫来扫去,产生了不少边缘带宽和回源费用;更头疼的是 CDN 节点自带的高防 WAF 偶尔还会把爬虫误判拦截,导致抓取诊断里隔三差五冒出几个 403。

为了省下这笔流量费,也为了让爬虫抓取更直接,我当时在域名解析后台(用的 DNSPod)开了「智能解析」。

配置看起来逻辑很清晰:

  • 「默认线路」解析到 CDN 边缘节点的 CNAME 域名,供全国普通访客访问。
  • 「搜索引擎线路」单独特配,直接指向源站服务器的公网 IP,让百度、谷歌、必应的蜘蛛直连源站。

刚切完那天,我在本地改 hosts 测了接口,又用拨测工具查了各省节点,普通访问走 CDN,爬虫走源站,看起来一切正常。

结果两周后的周一早上一看百度搜索资源平台,抓取频次曲线直接走出了一条垂直跳水线——从平常每天上万次抓取,断崖跌到两位数,新发的一批文章完全不见收录,老页面的展现量也在阴跌。

登录源站翻了 Nginx 的 access 日志,我才发现这半个月里几乎找不到几条正常的 Baiduspider 抓取记录。

顺着 DNS 解析链条、递归服务器行为和源站安全策略逐层排查下去,我挖出了好几个平时极其容易被忽略的隐形深坑。


坑点一:源站服务器换 IP,只改了默认线路,搜索引擎专线悬空成了死节点

这是最容易发生也最致命的运维疏忽。

平时排查线上问题或做服务器扩缩容,我们习惯了在控制台主面板里点进域名解析,找到那条 @ 或者 www 的 A 记录直接改掉。问题恰恰出在智能解析的多线路折叠上。

很多 DNS 控制台在列表展示时,如果一个主机头下面挂了多条不同线路的记录(比如「默认」、「电信」、「联通」、「搜索引擎」),它会默认收起或者分页显示。

上个月因为机房网络维护,我给源站切了一次弹性公网 IP。当时顺手把主解析改到了新 IP,却把藏在下方的「搜索引擎」线路忘得一干二净。

结果可想而知:

  1. 普通访客访问时,Local DNS 命中「默认」线路,拿到 CDN 节点 IP,访问流畅。
  2. 搜索引擎爬虫发起解析时,权威 DNS 精准匹配到了「搜索引擎」线路,返回给蜘蛛一个已经注销的旧 IP。

爬虫拿着旧 IP 去建连,TCP 三次握手直接卡死在 SYN_SENT,直到几十秒后连接超时。对于百度爬虫这种具备抓取健康度自适应机制的系统,一旦目标站点的抓取失败率连续几天超过警戒阈值,调度算法就会判定该站机器宕机或不可达,立刻启动指数退避,抓取配额直接被削减到冰点。

排查与验证命令

普通 dig example.com 只能查到当前网络出口命中的默认线路。要验证搜索引擎专线到底返回什么,必须向权威 DNS 显式指定查询,甚至模拟解析出口:

# 1. 先查出域名的权威 DNS 服务器
dig +short NS example.com

# 2. 直接向权威 DNS 查询,观察返回的 A 记录
dig @f1g1ns1.dnspod.net example.com A +noall +answer

# 3. 如果你的 DNS 服务商支持 EDNS 客户端子网(ECS),可以通过 client 参数指定爬虫网段发起探测
dig @f1g1ns1.dnspod.net example.com A +subnet=116.179.32.0/24 +noall +answer

上面这个 +subnet 参数很管用,后面我会专门说到。只要用百度官方公布的爬虫网段作为子网参数去查权威 DNS,如果吐出来的 IP 还是老机器或者根本连不上,那就是专线悬空了。


坑点二:ECS 识别失效,权威 DNS 把爬虫当成普通访客抛进了未知路由

很多人对智能 DNS 的工作原理有个误解,以为智能 DNS 是根据「谁在发 HTTP 请求」来分流的。

其实权威 DNS 在接收解析请求时,它看到的客户端是发起递归查询的 Local DNS 服务器,根本不是爬虫服务器本身。

这就牵扯到了 RFC 7871 定义的 EDNS Client Subnet(ECS)协议:

  • 如果爬虫使用的 Local DNS 支持 ECS,它在向权威 DNS 递归查询时,会在请求包里附带爬虫自身的 IP 前缀(通常是 /24)。
  • 权威 DNS 看到这个前缀,识别出属于百度爬虫或谷歌蜘蛛的 IP 段,才会返回「搜索引擎线路」的 A 记录。

现实情况是:不少自建递归 DNS、部分公网公共 DNS,以及某些爬虫调度集群内部的 DNS 代理,根本不开启 ECS 支持,甚至会主动丢弃 ECS 扩展头。

一旦没有 ECS 头部,权威 DNS 只能依据 Local DNS 本身的出口 IP 来做判断:

爬虫节点 (116.179.x.x 百度蜘蛛)
     │ 
     ▼ (查询 www.example.com,没有带 ECS 头部)
某公共递归 DNS (出节点 IP 位于江苏联通)
     │
     ▼ (权威 DNS 只能看到江苏联通 IP)
权威 DNS 服务器 (DNSPod / 阿里云 DNS)
     │
     └─► 匹配不到「搜索引擎线路」,直接回退到「联通线路」或「默认线路」

这会导致两个严重后果:

第一,如果你的智能解析规则没有配置「默认线路(兜底)」,只写了「搜索引擎」和「电信」,那么不支持 ECS 的爬虫查询直接返回空记录或 REFUSED,爬虫瞬间域名解析失败。

第二,即使回退到了「默认线路」(CDN),如果 CDN 的 WAF 对爬虫有限制,或者 CDN 回源没有做好配置,爬虫就又回到了原本被拦截的老路上。


坑点三:蜘蛛直连源站,源站防火墙与限流规则把它当 CC 攻击一网打尽

在没配搜索引擎专线之前,爬虫流量是打在全国各地的 CDN 节点上的。CDN 动辄几十个节点分摊并发,源站感受不到短时间内的突发压力。

一旦把搜索引擎线路单独切到源站 IP,全国数十个爬虫抓取集群会直接跨过 CDN,全部把流量倾泻在源站这一台单机上。

我的源站 Nginx 里配过一段很常规的防 CC 规则:

# 限制单个 IP 的每秒请求速率
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

server {
    listen 443 ssl http2;
    server_name example.com;

    location / {
        limit_req zone=req_limit_per_ip burst=10 nodelay;
        proxy_pass http://backend_pool;
    }
}

平时普通用户看网页,这个阈值绰绰有余。可是百度蜘蛛抓取新目录时,经常是多线程突发扫链,一秒钟能甩出 20 到 30 个 HTTP 请求。

直接命中了 limit_req 的突发上限。Nginx 毫不留情地给蜘蛛返回了海量 503 Service Temporarily Unavailable。

更糟的是,服务器后台还跑着 fail2ban。它的过滤规则看到同一个 IP 在一分钟内触发了超过 10 次 503,立刻通过 iptables 把这个 IP 直接 DROP 掉了一小时:

# 查 fail2ban 拦截记录时看到的惨状
fail2ban-client status nginx-req-limit
# 里面躺着好几个 220.181.x.x 和 116.179.x.x 的百度蜘蛛出口 IP

普通用户走 CDN 看网站一切正常,监控大盘上的 HTTP 状态码也全是 200,但源站的防火墙深处已经把真蜘蛛全干掉了。

源站正确放行真蜘蛛的 Nginx 配置

不能简单粗暴地按 User-Agent 放行,因为假蜘蛛脚本伪造 User-Agent 太容易了。在 Nginx 层面,可以通过 map 指令对搜索引擎白名单 IP 段进行旁路分流,跳过限流模块:

# 根据真实 IP 判定是否属于白名单爬虫(示例截取部分网段)
geo $is_search_spider {
    default 0;
    116.179.32.0/24 1; # 百度常用抓取段
    220.181.108.0/24 1; # 百度常用抓取段
    66.249.64.0/19 1;   # Googlebot 网段
    40.77.167.0/24 1;   # Bingbot 网段
}

# 爬虫请求将 key 置为空字符串,Nginx 对空 key 不计入限流统计
map $is_search_spider $limit_key {
    0 $binary_remote_addr;
    1 "";
}

limit_req_zone $limit_key zone=anti_cc_zone:10m rate=10r/s;

同时一定要在 fail2ban 的 ignoreip 参数里,把搜索引擎官方公示的重点网段加进去,避免系统层防火墙直接落锁。


坑点四:TTL 设成一天,故障切换时爬虫整整 24 小时都在撞死墙

很多人配 DNS 时为了所谓的「解析性能」,把 TTL 随手填成 86400(一天),甚至觉得 TTL 越长越好。

对于单线路稳定站点,TTL 设长一点确实能稍微减少递归查询。但对于上了智能分流、多源站或者随时可能切线路的架构来说,超长 TTL 就是一枚定时炸弹。

当源站 IP 变动或者发现专线配置出错时,即使你在控制台把 A 记录改对了,各省运营商的 Local DNS 缓存依然会坚守 86400 秒。爬虫的递归解析器在这 24 小时里,拿到的全是旧缓存。

那 24 小时里,每次爬虫来调度抓取,都是一水儿的握手超时与连接重置。搜索引擎的爬虫预算调整非常敏锐,一旦发现抓取异常率持续居高不下,会立刻压缩当天的抓取额度。

生产环境 TTL 的合理配置

对于包含智能线路、多机房灾备的动态业务,建议把 TTL 控制在 300 到 600 秒(5 到 10 分钟):

  • 300 秒足以应对日常绝大多数递归 DNS 的平滑更新。
  • 突发故障需要摘除源站或把搜索引擎线路紧急切回 CDN 时,最迟 10 分钟内全球大部分主流递归节点就能完成收敛。
  • 现代 DNS 解析的延时开销在毫秒级,短 TTL 带来的性能损耗在网页加载里微乎其微,但换来的容灾灵活性是实打实的。

坑点五:双栈 IPv6 漏配搜索引擎线路,触发 AAAA 记录解析黑洞

很多站长给域名开启了 IPv6 双栈支持,配置了 AAAA 记录。

如果在配智能解析时,只在「默认线路」配了 AAAA(指向 CDN 的 IPv6 Anycast 节点),而在「搜索引擎线路」只配了 IPv4 的 A 记录,就容易触发 Happy Eyeballs 算法的深水坑。

目前各大搜索引擎的抓取节点(尤其是海外 Googlebot 和国内部分大型云厂商节点)已经全面支持 IPv6。当爬虫节点向 Local DNS 查询域名时,通常是 A 记录和 AAAA 记录并发请求。

此时会发生什么?

  • 查询 A 记录:权威 DNS 识别为搜索引擎,返回了源站 IPv4。
  • 查询 AAAA 记录:因为「搜索引擎线路」没有配置 AAAA 记录,权威 DNS 的处理逻辑各家不同——有的服务商会直接回退到「默认线路」的 AAAA 记录(返回了 CDN 的 IPv6 地址),有的服务商则返回空的 NODATA 响应。

如果返回了 CDN 的 IPv6 地址,爬虫会优先使用 IPv6 建连,结果流量又打进了未放行爬虫的 CDN WAF;如果返回异常,甚至可能导致双栈握手竞态逻辑卡顿数秒,大幅拉高抓取延迟。

在智能解析下配置多线路时,A 记录与 AAAA 记录必须保持线路维度的严格对齐。如果不打算给搜索引擎走 IPv6,宁可在搜索引擎线路显式不要添加任何 AAAA,并确保权威 DNS 的 NODATA 处理符合 RFC 规范,或者给搜索引擎线路同样配齐源站可达的 IPv6 地址。


避坑操作清单

经过这次折腾,我整理了一套针对智能 DNS 分线路解析的日常运维自查准则:

  1. 必须保留全局默认线路:永远不要只建细分线路。任何未命中规则或剥离了 ECS 头部的递归查询,都必须有一条高可用的默认线路接盘。
  2. 每次改 IP 必须检查线路展开列表:服务器换 IP 或做迁移时,在控制台务必展开所有线路分组,核对「搜索引擎」、「海外」、「境外」等隐藏专线是否同步更新。
  3. 动态分流的 TTL 严格压到 300-600 秒:不要贪图超长缓存,把灾备与切换的主动权留在自己手里。
  4. 源站必须旁路放行真爬虫:直连源站意味着源站直接承受并发,Nginx 限流与 fail2ban 防火墙必须通过网段白名单或 rdns 双向验证予以放行。
  5. 定期用带有 subnet 参数的 dig 脚本做自动化拨测:用百度和谷歌的官方 IP 段模拟 ECS 查询,一旦返回的 IP 与预期不符立刻告警。

智能分流确实能在带宽和响应上带来收益,但多了一条线路,就多了一倍的排错面。把解析链路摸透了,才能保证省下费用的同时,不把爬虫和收录给丢了。

评论一下?

OωO
取消