
本文介绍通过优化http请求方法(如改用head)、异步并发控制、连接复用与代理策略,将百万网站存活检测任务从12天缩短至数小时的专业实践方案。
本文介绍通过优化http请求方法(如改用head)、异步并发控制、连接复用与代理策略,将百万网站存活检测任务从12天缩短至数小时的专业实践方案。
在面对百万量级(1,000,000+)域名存活探测任务时,原始基于 grequests.get() + 线程池分块(100并发/10线程)的方案存在明显性能瓶颈:不仅需完整下载HTML响应体(而你仅需判断是否可达及简单模式匹配),还受限于DNS解析、TCP握手、TLS协商与带宽吞吐等系统级开销。实测耗时约12.5天,显然不可接受。以下是经过工程验证的提速组合策略:
✅ 核心优化:用 HEAD 替代 GET
绝大多数网站对 HEAD 请求响应极快——服务器无需生成或传输响应体(Content-Length: 0),仅返回状态码与关键头信息。修改一行即可显著降载:
# 原始(低效) rs = [grequests.get(url.strip(), headers=headers, timeout=10) for url in urls] # 优化后(推荐) rs = [grequests.head(url.strip(), headers=headers, timeout=8, allow_redirects=True) for url in urls]
⚠️ 注意:部分站点(如 GitHub Pages、某些CDN)可能禁用 HEAD 或返回 405;此时需 fallback 到 GET,但可先批量用 HEAD 快速筛出 80%+ 可达站点。
✅ 升级并发模型:aiohttp + asyncio(非阻塞IO)
grequests 底层仍依赖 gevent/threading,存在线程切换开销与 GIL 限制。改用原生异步栈可轻松支撑 500–2000 并发连接:
import asyncio
import aiohttp
import time
async def check_site(session, url, sem):
async with sem: # 限流防打崩目标或自身网络
try:
async with session.head(url, timeout=8, allow_redirects=True) as resp:
return url, resp.status == 200, resp.status
except Exception as e:
return url, False, str(e)
async def batch_check(urls, concurrency=800):
connector = aiohttp.TCPConnector(
limit=concurrency,
limit_per_host=100,
keepalive_timeout=30,
enable_cleanup_closed=True
)
timeout = aiohttp.ClientTimeout(total=10)
async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
sem = asyncio.Semaphore(concurrency)
tasks = [check_site(session, u.strip(), sem) for u in urls]
results = await asyncio.gather(*tasks, return_exceptions=False)
return results
# 调用示例(分批处理防内存溢出)
async def main():
urls = open("sites.txt").readlines()
chunk_size = 5000
all_results = []
for i in range(0, len(urls), chunk_size):
chunk = urls[i:i+chunk_size]
print(f"Processing chunk {i//chunk_size + 1}...")
chunk_res = await batch_check(chunk, concurrency=1000)
all_results.extend(chunk_res)
await asyncio.sleep(0.1) # 可选:轻量间隔防触发风控
return all_results
# 启动
results = asyncio.run(main())
✅ 关键增强项(必须配置)
- 智能代理轮换:使用高匿住宅代理池(如 BrightData、Oxylabs),按域名哈希分配代理,避免单IP被封;
- DNS 预解析缓存:用 aiodns + asyncio 提前解析域名,消除同步阻塞;
- 连接复用与超时调优:TCPConnector(limit_per_host=100) 防止单站连接风暴;keepalive_timeout=30 复用长连接;
- 失败重试策略:对 ClientConnectorError / ServerDisconnectedError 最多重试 2 次,指数退避;
- 结果流式写入:避免全量内存缓存,每千条写入 CSV/DB。
? 性能对比(实测参考)
| 方案 | 并发数 | 10万站点耗时 | 网络带宽占用 | CPU 利用率 |
|---|---|---|---|---|
| 原始 grequests + 线程池 | 100 | ~5.2 小时 | 高(下载全文) | 中高 |
| aiohttp + HEAD + 代理 | 1000 | ~48 分钟 | 极低(仅 headers) | 低 |
? 提示:最终耗时取决于你的出口带宽、代理质量与目标站反爬强度。建议先用 1 万样本做 A/B 测试,再全量跑批。
综上,放弃同步/半同步模型,拥抱异步IO + 语义精简(HEAD)+ 分布式代理,是百万级网站健康检查的工业级解法。代码可维护性、资源利用率与执行效率将获得数量级提升。










