问题
最近,我一直在考虑如何抓取某一大型跨国网站的内容,以获得该公司提供销售的产品的具体细节。该网站没有API,但是可以通过向特定URL发送带有产品ID的GET请求来下载每个产品的XML。所以至少这是有意义的。
问题是,可能存在数亿个潜在的产品ID(比如000000001到500000000之间),但实际上只有几十万个产品存在。而且不可能知道哪个产品的ID是有效的。
方便地,向产品URL发送HEAD请求会产生不同的响应,这取决于产品ID是否有效(即产品实际上存在)。一旦我们知道该产品确实存在,我们就可以下载完整的XML并对其进行刮取以获取所需的数据。
显然,如果只在一台服务器上运行,发送数以亿计的头请求将花费大量的时间来完成,所以我想借此机会学习如何开发某种分布式应用程序(对我来说完全是全新的领域)。在这一点上,我应该提到,这个特定的网站可以轻松地处理大量的每秒传入的请求,而无需冒DOS的风险。我不想说这个网站的名字,但它每天很容易获得数百万的点击量。这个刮刀对网站性能的影响微乎其微。不过,如果公司投诉,我会立即制止的。
设计
我不知道这是否是正确的方法,但我目前的想法是启动一个“协调服务器”,以及一些节点与该服务器通信并执行抓取,所有这些都以EC2实例的形式运行。
每个节点将启动一定数量的进程,每个进程将由协调服务器指定作业,其中包含要刮掉的潜在产品ID的不同范围(例如产品ID 00001至10000)。这些作业将存储在协调服务器上的数据库表中。每一项工作都将包含以下信息:
当节点启动时,将向协调服务器发送查询,请求提供一些配置数据,并要求作业进行工作。当节点完成作业时,将发送一个查询,更新刚刚完成的作业的状态,并发送另一个查询,请求处理一个新作业。每个作业都有一个过期时间,因此如果进程崩溃,或者某个节点因任何原因失败,则另一个节点可以接管过期的作业再试一次。
为了最大限度地提高系统的性能,我需要计算出应该同时启动多少个节点,每个节点有多少进程,发送的HTTP请求的速率,以及哪种EC2实例类型将提供最高性价比(我猜高网络性能、高CPU性能和高磁盘I/O将是关键因素)。
目前,计划是用Python编写刮刀器,运行在可能在Docker容器中启动的Ubuntu EC2实例上,以及某种类型的键值存储数据库,以保存协调服务器(MongoDB?)上的作业。关系数据库也应该工作,因为作业表应该是相当低的I/O。
我很想从更有经验的工程师那里知道这是否是正确的方法,还是我完全忽略了一个更好的方法来完成这个任务?
非常感谢,谢谢!
发布于 2016-01-31 13:44:47
您正在尝试设计一个分布式工作流系统,这实际上是一个已解决的问题。与其重新发明轮子,我建议您看一下AWS的SWF,它可以轻松地为您完成所有的状态管理,让您可以只担心编写业务逻辑。
这就是使用SWF设计的系统的样子(在这里,我将使用SWF的标准术语--您可能需要阅读文档才能准确地理解这些术语):
productID启动一个工作流。productID是否有效,就像你提到的那样,提出一个头请求。您可以很容易地将上面的设计更改为有一个工作流过程,一个批产品ID。
还有几点我建议你记住:
https://stackoverflow.com/questions/35114101
复制相似问题