在搭建或维护一个RSS订阅源时,有效期设置直接决定了客户端多久来抓取一次、源站承受多大压力,以及用户能否及时看到更新。RSS 2.0规范里专门提供了一个叫ttl的节点,用来告诉阅读器这个频道内容的最短存活时间,理解并正确配置它就是做好有效期管理的核心。

什么是RSS中的ttl有效期
ttl是Time To Live的缩写,在RSS 2.0中作为channel的子元素出现,取值为一个非负整数,代表分钟数。比如写法是<ttl>60</ttl>,含义是聚合器或阅读器在60分钟内不需要再次请求该源,可以放心使用本地缓存。
这个设计最早是为了减轻早期博客托管服务器的负担。如果没有ttl,不同的客户端可能每分钟都来拉取一次XML,源站流量会被无意义消耗。规范虽不强制客户端严格遵守,但主流阅读器如Feedly、Inoreader以及各类开源订阅程序都会把它当作重要参考。
如何在RSS源中配置ttl
配置方式非常简单,只需要在生成的RSS XML的channel块里加入ttl节点。下面是一段PHP生成RSS时写入有效期的示例:
<?php
// 假设频道内容平均一小时更新一次
$ttl = 60;
header('Content-Type: application/rss+xml; charset=utf-8');
echo '<?xml version="1.0" encoding="UTF-8"?>' . "n";
echo '<rss version="2.0">' . "n";
echo ' <channel>' . "n";
echo ' <title>我的技术博客</title>' . "n";
echo ' <link>https://ipipp.com/blog</link>' . "n";
echo ' <description>分享编程经验</description>' . "n";
echo ' <ttl>' . $ttl . '</ttl>' . "n";
echo ' </channel>' . "n";
echo '</rss>' . "n";
?>
上面的代码在channel中显式输出了ttl为60。这样订阅器拿到源之后,内部调度会至少等待一小时再发起下一次抓取。如果文章发布频率更高,可以把ttl调小,比如新闻类源设成15或30;如果是周更博客,设成1440也完全合理。
要注意的是,某些静态站点生成器会在模板里忽略ttl,导致最终文件里根本没有这个节点。此时客户端只能依赖HTTP层的Cache-Control或者自己的默认策略,可控性变差。因此建议在CI打包阶段用脚本校验产物中是否包含<ttl>标签。
ttl与HTTP缓存头的配合
只靠RSS里的ttl还不够稳妥,因为很多程序也会看HTTP响应头。推荐同时返回合适的Cache-Control和ETag。下面是用Nginx做反代时的一个配置片段思路:
location /feed.xml {
add_header Cache-Control "public, max-age=3600";
add_header ETag "$upstream_http_etag";
expires 1h;
}
这段配置让浏览器和中间代理也能缓存一小时,和ttl=60形成互补。当阅读器在一小时内再来,若带If-None-Match且ETag没变,源站直接返回304,不传输正文,进一步省流量。
有些开发者误以为只要HTTP头写了max-age,RSS里的ttl就可以不写。实际上部分离线阅读器只解析XML而不发HTTP条件请求,它们唯独认ttl。两套机制并行才是最保险的做法。
常见误区与调试方法
第一个误区是把ttl写成0或负数,以为代表实时。规范中0的含义在各客户端解释不一,有的当作不缓存,有的直接忽略。安全做法是给一个至少5到10的正值。
第二个误区是在动态接口里每次随机生成ttl,造成客户端调度抖动。应该根据真实更新周期固定或按日粒度调整。调试时可用curl命令直接看源文件和头:
curl -i https://ipipp.com/feed.xml grep -o '<ttl>[0-9]*</ttl>' feed.xml
通过观察响应头里的Cache-Control与body中的ttl数值,能快速确认两者是否一致。若发布系统有缓存层,还要确认它不会把ttl节点吞掉或改写。
合理设置RSS源中的有效期,既能保护服务器资源,也能让订阅用户体验到稳定且及时的更新。把ttl、HTTP缓存头与条件请求三者结合起来,是运维好一个公开订阅源的基本功。