使用requests库为HTTP请求设置DNS超时以缩短死链检测时长
问题原因说明
requests 库本身没有暴露 DNS 超时的配置接口,其内置的 timeout 参数仅覆盖 TCP 连接建立和读取响应的阶段。你遇到的5-10秒超时是操作系统底层默认 DNS 解析的超时重试逻辑导致的,该逻辑不受 requests 配置影响。
可选解决方案
方案1:改用异步HTTP库aiohttp(推荐)
适配你提到的协程异步处理思路,aiohttp 原生支持自定义 DNS 超时参数,同时异步并发可以大幅提升批量链接的检测效率,兼容 Windows 10 与 Ubuntu 下的 Python 3.8 环境。
依赖安装
pip install aiohttp
代码示例
import asyncio from aiohttp import ClientSession, ClientTimeout from aiohttp.resolver import AsyncResolver # 配置DNS解析超时1秒,重试次数为0 resolver = AsyncResolver(timeout=1, attempts=1) # 全局请求总超时2秒,覆盖连接、读取全流程 timeout = ClientTimeout(total=2, connect=1, sock_read=1) async def check_redirect(sent_url: str): async with ClientSession(timeout=timeout, resolver=resolver) as session: try: async with session.head(sent_url, allow_redirects=False) as resp: if resp.status in (301, 302, 303, 307, 308): return resp.headers.get("location", sent_url) return sent_url except Exception: return sent_url # 批量检测调用示例 async def batch_check(urls: list): tasks = [check_redirect(url) for url in urls] return await asyncio.gather(*tasks) if __name__ == "__main__": test_urls = ["https://example.com", "https://invalid-test-url-xxx.com"] results = asyncio.run(batch_check(test_urls)) print(results)
方案2:保留requests栈,单独控制DNS解析流程
如果不想修改原有 requests 业务逻辑,可以单独抽离 DNS 解析步骤,用 dnspython 库自行控制解析超时,解析成功后再发起 HTTP 请求。
依赖安装
pip install dnspython requests
代码示例
import requests import dns.resolver from urllib.parse import urlparse from requests.adapters import HTTPAdapter # 初始化DNS解析器,配置超时1秒 dns_resolver = dns.resolver.Resolver() dns_resolver.timeout = 1 dns_resolver.lifetime = 1 # 复用requests会话提升性能 http_session = requests.Session() http_adapter = HTTPAdapter(max_retries=0) http_session.mount("http://", http_adapter) http_session.mount("https://", http_adapter) def check_redirect(sent_url: str): try: parsed = urlparse(sent_url) if not parsed.hostname: return sent_url # 先做DNS解析,超时直接返回 dns_resolver.resolve(parsed.hostname, 'A') # 解析成功后发起HEAD请求 response = http_session.head(sent_url, timeout=(1, 1), allow_redirects=False) if response.is_redirect: return response.headers["location"] return sent_url except (dns.exception.Timeout, dns.resolver.NXDOMAIN, requests.exceptions.Timeout): return sent_url
方案3:修改Ubuntu服务器全局DNS配置
如果无需修改代码,可直接调整部署环境的系统DNS参数,编辑 /etc/resolv.conf 添加如下配置:
options timeout:1 attempts:1
该配置会将系统全局DNS解析超时改为1秒,仅重试1次,即可避免5-10秒的长等待,但该配置对服务器所有程序生效,适合专属部署的服务器使用。
内容的提问来源于stack exchange,提问作者Paul Hübner
相关产品推荐
相关产品推荐

