短链接服务通常把长网址映射成短域名或短路径,用户访问短链接时由服务器返回重定向响应。在这种模式下,每一次点击短链接都会产生一次HTTP请求,服务器必须在线处理查询并返回301或302跳转。对于日活千万级的短链接平台来说,重定向服务器的QPS可能非常高,而且跳转响应本身也增加了用户感知延迟。如果把跳转目标提前放进DNS响应,让客户端在解析域名阶段就拿到目标URL,就能省去中间那一跳。DNS查询本身是分布式、强缓存的,这种思路在特定场景下可以显著降低短链接服务的在线压力。本文结合DNS记录类型和工作流程,分析如何用TXT记录实现短链接跳转,并给出最小可用的代码示例。

一、短链接服务的传统HTTP重定向流程
短链接生成时,服务端会为长URL生成一个唯一短码,例如aB3x9K,并存储映射关系。短域名例如s.ippipp.com,用户访问https://s.ippipp.com/aB3x9K,请求到达服务器后,服务器根据路径查询数据库,找到原始URL,返回HTTP 301响应,并在Location头中设置目标地址。浏览器收到响应后自动跳转。这个过程至少包含一次TCP/TLS握手、一次HTTP请求和响应。如果短链服务器物理距离用户较远,延迟会明显叠加。高并发下,数据库和缓存系统承受巨大压力。虽然可以通过CDN缓存301响应来减轻回源压力,但首次访问仍需经过应用服务器。
为了优化性能,常见做法包括使用内存数据库如Redis存储映射、在CDN边缘节点执行重定向、或使用302临时重定向以便修改。但这些方案仍然依赖HTTP层,客户端必须与短链服务器通信。能否把映射信息提前分发到DNS系统,让客户端通过DNS查询获取目标地址?DNS是全球最成功的分布式数据库之一,天然具备缓存和负载均衡能力,借助DNS实现短链接跳转成为一种值得探索的替代方案。
二、利用DNS记录承载跳转目标
DNS标准中,A/AAAA记录用于解析IP地址,CNAME用于别名,TXT记录可以存储任意文本,长度上限通常为255字节(单个字符串),但实际可以存储多条字符串拼接,总长度可达约4KB。RFC 7553定义了URI记录类型,专门用于存放URI,但主流DNS服务器和客户端支持有限。相比之下,TXT记录几乎被所有DNS软件支持,是实现短链接跳转最直接的载体。我们可以把目标URL直接写入TXT记录,客户端查询该记录即可获得长地址。
以短域名s.ippipp.com为例,如果短码是abc,我们可以在DNS区域中添加一条TXT记录:abc.s.ippipp.com. IN TXT "https://www.ippipp.com/very/long/path"。客户端查询abc.s.ippipp.com的TXT记录,得到这个URL,然后直接访问目标。这种方式下,短链接服务在生成短码后,只需要通过DNS API动态创建一条TXT记录即可,在线请求完全由DNS系统承担。
下面是一个DNS区域文件的示例,展示了如何为短码abc配置TXT记录。
$ORIGIN s.ippipp.com.
@ 3600 IN SOA ns1.ippipp.com. admin.ippipp.com. (
2024010101 ; serial
7200 ; refresh
3600 ; retry
1209600 ; expire
3600 ) ; minimum
IN NS ns1.ippipp.com.
IN NS ns2.ippipp.com.
abc IN TXT "https://www.ippipp.com/very/long/path?param=value"
TXT记录可以存储完整的URL,但要注意长度限制。超过255字节时,DNS服务器会将其拆分成多个字符串,客户端需要按顺序拼接。下一节给出客户端实现。
三、客户端查询与跳转实现
客户端要实现DNS短链接跳转,通常需要嵌入一个DNS解析库。在浏览器环境中,JavaScript无法直接发起DNS查询(除非使用DoH服务),因此DNS短链接更适合原生应用、命令行工具或服务端程序。Python的dnspython库提供了完整的DNS查询能力。以下是一个查询TXT记录并拼接多个字符串的函数。
import dns.resolver
def get_target_url(short_domain: str) -> str:
try:
answers = dns.resolver.resolve(short_domain, 'TXT')
# TXT记录的strings属性是一个列表,依次拼接即可
target = ''.join([s.decode('utf-8') for s in answers[0].strings])
return target
except dns.resolver.NXDOMAIN:
print('短码不存在')
except dns.resolver.NoAnswer:
print('没有TXT记录')
return None
拿到目标URL后,可以直接使用系统浏览器打开,或者在应用内发起HTTP请求。以下是一个简单的跳转调用示例:
import webbrowser
short_domain = 'abc.s.ippipp.com'
url = get_target_url(short_domain)
if url and url.startswith('https://'):
webbrowser.open(url)
如果需要在浏览器中使用DNS短链接,可以借助DoH(DNS over HTTPS)服务,例如Cloudflare或Google的公共DoH接口。前端通过fetch请求DoH接口查询TXT记录,然后使用window.location.href进行跳转。下面是一个基于Cloudflare DoH的JavaScript示例:
async function resolveTxt(domain) {
const url = `https://cloudflare-dns.com/dns-query?name=${domain}&type=TXT`;
const resp = await fetch(url, { headers: { accept: 'application/dns-json' } });
const data = await resp.json();
if (data.Answer && data.Answer.length > 0) {
// 拼接TXT记录中的多个字符串
return data.Answer.map(item => item.data.replace(/"/g, '')).join('');
}
return null;
}
const target = await resolveTxt('abc.s.ippipp.com');
if (target) {
window.location.href = target;
}
四、DNS短链接与HTTP重定向的对比
虽然DNS短链接减少了HTTP跳转,但它并非适用于所有场景。这里从延迟、缓存、更新、安全等维度进行对比。DNS查询通常比HTTP请求更快,尤其是当结果被本地DNS缓存命中时,延迟可能只有几毫秒。而HTTP重定向需要经过TCP握手、TLS协商,即使使用HTTP/2或3,也至少需要一次RTT。不过,DNS查询也可能因为递归解析和缓存未命中而变慢,通常首次查询在50-200毫秒之间。
在缓存方面,DNS记录通过TTL控制缓存时间,客户端和中间DNS服务器都会缓存结果。