大多数抓取系统最终收敛到的架构是:云服务商中的容器,按队列深度扩缩容,无状态且可随时丢弃。这对计算而言是正确的设计。但对出口流量而言,这是最糟糕的设计,因为这些容器获得的地址正是受保护站点首先检查的东西。
云服务商的地址段是公开的。任何人都可以枚举它们,大多数反爬供应商也确实这么做。来自这些地址的流量并非因为其行为而被拦截,而是在第一个请求完成之前,就已经因来源而被打分。解决方法不是增加更多的工作节点或改进请求头,而是把代码运行的地方和流量出口的地方分离开来。
出口层是一个独立的关切点
一个有用的思维模型是:你的工作节点是计算,你的地址是身份,两者应当独立扩缩容。
短生命周期的工作节点是好事:启动五十个,处理完队列,然后停止。短生命周期的身份通常是坏事:每个从新的云地址接入的新工作节点,都是一股陌生的流量。你真正想要的,是一组在工作节点更迭之间保持稳定的出口地址,这样你的目标站点看到的身份,不会因为自动扩缩容器的每次反应而不断变动。
ISP 代理,也称为静态住宅代理,恰好适合这个角色。每个代理在整个计费周期内都保持在你选择的城市和ISP上,注册在真实的 ISP 名下而非云服务商的地址段,即使IP刷新,也会保持在那个城市和ISP上。你的工作节点来来去去,代理却留在你设定的位置。
身份验证随处可用
每个代理都有自己的用户名,它们都通过同一个主机 isp.shifter.io,端口 443 进行连接,因此你的工作节点无需固定的出站地址:
isp.shifter.io:443:USERNAME:PASSWORD
当工作节点确实是跨越不断变化的地址的短生命周期节点,或分布在多个区域,或运行在你无法控制出站地址的环境中时,这正是你需要的方式。无服务器函数和多区域部署的工作方式与单台服务器相同。
在工作节点间分配地址
你有 N 个地址和数量可变的工作节点,所以必须有某种机制把二者对应起来。
行之有效的做法是,把地址列表当作一种共享资源,通过显式租约来管理,而不是让每个工作节点自行挑选。一个工作节点从协调层取得一个地址,在其任务期间持有它,然后归还。有两点很关键:不能让两个工作节点同时使用同一个地址,从而使其表观请求速率翻倍;工作节点崩溃也不应永久地将某个地址从流通中移除。
那种朴素的替代做法,即把工作节点标识哈希映射到索引,一旦你的工作节点数量发生变化就会失效,而对于自动扩缩容的部署来说,这种变化是持续不断的。你会在扩容时遇到冲突,在缩容时出现闲置地址。
单个地址的请求速率才是这里真正的预算所在。ISP 套餐的带宽是不限量的,所以约束条件不是流量的 GB 数,而是一个代理能够合理产生多少流量。这个数字决定了你的部署需要多少个地址,这也是为什么按吞吐量而非数据量来定规模才是正确做法的原因。
健康检查应内置于地址池中
地址不会以统一的方式失效。某一个地址可能开始在某个特定目标上频繁触发验证挑战,而其他一切都正常,此时接收到该地址的工作节点会持续产生垃圾数据,直到有人注意到为止。
按地址而非按整体来追踪结果。如果你从多个目标采集数据,那么按目标区分的、滚动窗口内的单地址成功率,能让你隔离单个地址,而不必拉下整个地址池。聚合指标只会显示百分之五的下降,却掩盖了其实是某一个地址完全失效的事实。
隔离应当是临时且自动的,并配合一个探测机制,在地址恢复后将其放回。关于最初如何确立”正常”基准的方法,参见测试代理速度、成功率和位置准确性。
在购买前先规划好地理分布
有一个细节对云端团队很有帮助:使用 Shifter 的 ISP 代理,你可以在购买后为每个代理选择城市和ISP,覆盖120个国家。
每个代理随后会在整个计费周期内保持在该城市和ISP上,因此请根据你实际采集的目标来决定分布比例,而不是在每次部署时都去更改它。
ISP 不适用的场景
静态住宅代理并不能全面取代轮换,而云基础设施容易让人误以为可以,因为这样操作模型要简单得多。
如果你的工作负载是针对众多目标的高流量采集,单地址请求速率会远早于成本之前变得不现实,其症状表现为数据质量下降而非报错。这类工作应当交给轮换式的住宅代理,因为在设计上每个请求都可以来自不同的地址。相关权衡在ISP 代理与数据中心及住宅代理的比较中有详细说明。
真正适合稳定出口层的工作负载包括:长期会话、任何需要认证的场景,以及一致性比数据量更重要的稳定采集。混合架构很常见也很合理,用 ISP 地址处理持久性工作,用轮换网关处理批量工作。
运维要点
将地址列表保存在配置中,而非镜像里。 为了改变地址池而重建容器是可以避免的。在启动时从你的密钥存储或配置服务中读取它。
不要记录带凭证的 URL。 这是代理凭证泄露到日志聚合系统中最常见的方式,因为最自然的调试日志行往往就是整个连接字符串。
按地址限制并发,而不仅仅是全局限制。 一个在小地址池中分布不均的全局限制,会把负载集中到你的分配逻辑偏爱的那些地址上。相关机制详见速率限制与请求节流。
在部署内部进行测试。 从笔记本电脑发起的连通性检查只能证明你的凭证有效。它无法证明你的任务定义是否正确地传递了环境变量,而这才是大多数时候真正的故障原因。
常见问题
我可以在无服务器函数中使用 ISP 代理吗?
是的。凭证认证可以在任何地方使用,因此函数不断变化的出站地址不会成为问题。
自动扩缩容的部署需要多少个地址?
按峰值并发任务数和保守的单地址请求速率来定规模,而不是按工作节点数量。工作节点可以闲置,但地址不应成为峰值时用尽的那个瓶颈。
代理层会成为瓶颈吗?
ISP 代理运行在具有无限流量的托管基础设施上,所以单个代理的吞吐量很少成为限制因素。并发策略通常才是首先起约束作用的因素。
每个服务都应该拥有自己的地址吗?
如果它们的流量模式差异很大,那么是的。把一个稳定的低速率服务和一个突发性服务混用同一个地址,意味着突发性服务会决定两者受到的对待方式。
总结
云端抓取基础设施被封锁的原因,与代码质量毫无关系:这些地址被公开标记为云地址。在短生命周期的工作节点前面部署一层稳定的 ISP 出口,能够把身份与计算分离开来,而这正是这种架构本来就需要的分离方式。
显式地租用地址,按地址追踪健康状况,按请求速率而非带宽来定规模,并针对你实际采集的目标,有意识地决定地理位置。相关套餐请见 ISP 代理定价页面。