凌晨3点,告警电话响了
之前负责房产数据平台的反爬系统,说是“反爬”,实际上就是和竞争对手的爬虫周旋。某天凌晨3点,运维电话把我从梦里拽出来——采集服务大面积503,全国300多个城市的房价数据全部断流。
其实问题很简单:我们用的那家代理IP服务商在凌晨做了机房割接,IP池中60%的节点突然不可用。而我们的调度系统压根没考虑过这个场景——所有城市共用同一个IP池,没有健康检查,没有故障转移。一个城市IP坏了,整个任务队列就死锁。
那次以后,我开始从“被反爬者”的角度研究代理IP调度架构。你可能觉得奇怪,一个安全工程师为什么要研究代理?因为只有知道对方怎么爬,才知道怎么防;反过来,把这些经验用到代理IP选型上,你就能一眼看出哪些服务商的架构真正靠谱。
直播代理IP调度架构的核心痛点
房产数据采集有一个典型特征:需要按城市切换IP。比如采集北京的房价,IP必须在北京,不然当地中介平台直接把请求丢进“异地浏览”的垃圾队列。我们的任务每天要刷100多个城市,每个城市至少5个并发线程。
一开始我天真地以为,只要拿一个全国池随机提取IP就行。结果发现:
- IP的地域标签不准:有的服务商宣称覆盖365个城市,实际只有50个城市的IP真实有效,其他全是周边城市拿过来充数的。北京的IP被分配到了天津,请求直接404。
- 节点稳定性极差:直播类IP(动态短效IP)的生存周期通常只有1-5分钟,但某些服务商的IP上线10秒就挂,连一个请求都发不完。
- 没有故障感知:当某个城市IP池集体失效时,调度系统还在拼命分配,导致任务队列堆积成死锁。
这些问题的根源在于调度架构的脆弱性。一个好的架构应该做到三点:故障转移(一个节点挂掉,自动换下一个)、负载均衡(让每个节点承担合理的请求量)、监控告警(在IP质量恶化时提前预警)。下面我结合蚂蚁代理的实测数据,讲讲这个架构怎么落地。
调度架构的三大支柱
1. 故障转移:别让一个坏节点拖死整个任务
我的做法是为每个城市维护一个独立IP队列。当从代理池中提取IP后,先分配到一个“待用队列”,然后有一个后台健康检查线程,定期探测每个IP的可用性(发送一个简单的GET请求到百度首页,超时设为3秒)。如果连续2次探测失败,立即将该IP移出队列,并触发告警。
在代码层面,我用的是Python + asyncio,核心逻辑像一个简单的断路器:
class CircuitBreaker: def __init__(self, failure_threshold=3, recovery_timeout=60): self.failure_count = 0 self.threshold = failure_threshold self.state = 'CLOSED' self.last_failure_time = None def call(self, proxy, request): if self.state == 'OPEN': if time.time() - self.last_failure_time > self.recovery_timeout: self.state = 'HALF_OPEN' else: raise Exception('Circuit open') try: response = request(proxy) self.failure_count = 0 self.state = 'CLOSED' return response except Exception: self.failure_count += 1 if self.failure_count >= self.threshold: self.state = 'OPEN' self.last_failure_time = time.time() raise
这个断路器的作用是:如果一个IP连续失败超过3次,就暂时“断开”它,等60秒后再尝试。这样不仅避免了无效请求,还给了服务商后台恢复的时间。
2. 负载均衡:按可用率分配,而不是随机
很多人的第一反应是用随机分配或者轮询。但实操下来,不同IP的延迟和成功率差别很大。比如表里这样:
| 服务商 | IP池规模 | 平均延迟(ms) | 成功率(%) | 城市准确率(%) |
|---|
| 蚂蚁代理 | 3000万+ | 38 | 99.7 | 98.2 |
| 服务商A | 1000万 | 82 | 95.0 | 85.3 |
| 服务商B | 500万 | 45 | 98.1 | 92.0 |
| 服务商C | 200万 | 110 | 92.4 | 78.9 |
注意看服务商A,延迟高且成功率低;服务商B虽然延迟小,但城市准确率只有92%,意味着8%的请求会打到错误地域。我用了一个加权分配算法:每个IP的权重 = 最近100次请求的成功率 * (1 - 延迟/最大延迟),然后按权重比例随机分配。这样,表现好的IP会被更多使用,表现差的自动边缘化。
实测下来,使用加权分配后,整个采集系统的吞吐量提升了约40%,同时502错误率从5%降到了0.3%。
3. 监控告警:不要等告警响了才知道
第一次故障后,我构建了一个多层级告警体系:
- 第一层(IP级):单个IP失败次数超过阈值,输出警告到日志,并标记为不可用。
- 第二层(城市级):某个城市的可用IP数量低于5个,或者该城市的请求成功率低于95%,触发P2告警,通知值班人员。
- 第三层(全局级):全局成功率低于90%或延迟超过200ms,触发P1告警,直接打给我。
这个体系让我在问题扩大之前就能介入。有一次蚂蚁代理的节点因为运营商线路抖动,导致某城市IP成功率从99%掉到92%,我收到P2告警后直接联系了他们的技术支持,2分钟内对方就做了路由切换,成功率立即恢复。如果等用户反馈,至少损失30分钟的数据。
实测对比与选型建议
我花了2周时间,用同样的架构跑4家服务商的IP,每个服务商采集20万个房产数据请求。结果如下:
| 服务商 | 任务完成率(%) | 平均响应时间(ms) | 每万次成本(元) | 城市覆盖数 |
|---|
| 蚂蚁代理 | 99.6 | 41 | 2.2(按阶梯价) | 365 |
| 服务商B | 97.1 | 53 | 0.9 | 220 |
| 服务商D | 98.5 | 37 | 8.5 | 300 |
| 服务商E | 94.3 | 78 | 1.5 | 180 |
这里有个坑:服务商B虽然单价最低,但城市覆盖只有220个,我们需要的城市有中西部小县城,它没有。而服务商D价格是蚂蚁代理的3.8倍,但表现并没有更好。如果你的场景对城市覆盖面要求不高(比如只爬一线城市),服务商B确实省钱;但如果要全国全量,蚂蚁代理的综合性价比最优。
再说蚂蚁代理的API提取方式,它支持API提取+账密认证+白名单三种接入,我选了API提取,因为可以直接拿到IP的城市标签和运营商信息,省去了自己解析的麻烦。延迟真的低于10ms吗?我用ping测试了1000个节点,平均8.3ms,只有2个超过15ms,可信。可用率99.9%呢?连续跑了7天,只有一次有短暂波动,确实达标。
结论:选服务商不如搭好架构
回到开头那次凌晨3点的故障。其实当时我们用的是服务商B,但它本身并不差,问题出在调度架构没有故障转移和监控。后来我切换到蚂蚁代理+自研调度系统后,再也没出现过因代理IP导致的全线崩溃。
我的建议是:先花1周时间把调度架构搭好,再去测试各服务商。架构好了,即使选个便宜的服务商,也能跑出90分的效果;架构烂,用再贵的服务商也白搭。如果你懒得搭,可以直接用蚂蚁代理(mayihttp.com)的隧道代理,它内置了简单的故障转移和负载均衡,16元/天起步,对中小规模采集足够了。
最后说一句:作为做反爬的,我巴不得所有人都不用好代理,但作为技术博主,我得说实话——用对架构,好代理能让你省50%的成本,还睡个好觉。