我正在研究一个系统,在这个系统中,我们有几个预定的长时间运行操作。
在我们的例子中,这是我们为客户执行的网站爬行。当前的设置是实用的,我们有一个服务正在运行,它负责将工作分发给四个不同的“爬行器”,它们作为线程在同一个应用程序中运行。
所有这些都是使用数据库中的队列进行协调的。每个“爬行”计划在给定的时间开始,协调器/协调器从db获取爬行并分配给爬虫。每个爬虫报告都是实时返回到协调器的进度,后者向希望查看每个爬虫进度的其他进程发送消息。每个爬虫还保存一个内部“状态”,这个状态是持久化的,这样它就可以在重新启动之后恢复。
我正在寻找方法,使这个更可伸缩,以便我们可以添加更多的爬虫,通过旋转新机器在高负荷等。
我们仍然需要某种程度的协调,这样我们就可以在任何时间点(“如果现在发生了怎么办”)对系统进行概述,但是我们希望爬虫的数量能够更动态、更可伸缩。
我从来没有遇到过类似的挑战,但我一直在想,每台新机器都可以以某种方式“报到”,让协调员意识到,然后开始接受工作。我也觉得这里的整体模式肯定是“解决”过的。
有人有什么建议、想法和建议吗?也许有一些框架或模式可以帮助我朝着正确的方向发展?
我们的解决方案建立在.NET 6堆栈上。
发布于 2023-05-22 03:05:29
我正在寻找方法来使这个更可伸缩,这样我们就可以通过旋转新机器来增加更多的爬虫
听起来你已经掌握了这个问题,并且已经实现了一个合理的解决方案。
从零开始,卡夫卡是满足需求的合理方法,但是还有很多其他的发布子解决方案,比如0mq。
一种以数据库为中心的方法甚至可以工作,在这里,使用SELECT查询代替事件驱动的调度工作人员轮询任务。只要您注意索引任何时间戳列,那么最近需要关注的URL上的“廉价”查询应该是简单明了的。
闲置的员工(超过第一位)应该退出,因此您只需要为云计算付费。给定数量的积压爬行目标意味着估计爬行完成时间。每分钟检查一次这个统计数据,然后继续生产另一名员工,直到估计值下降到企业可以接受的程度为止。
对于爬行器来说,这是一个有点棘手的问题:探针之间的时间问题。在一千毫秒内敲击一些可怜的GETs服务器是反社会的。
假设您有6个站点要爬行,URL主机名为A、B、…、F。每个站点都有1000个URL。为了成为一个好邻居,我们坚持在GET请求之间延迟至少2秒,即30次查询/分钟。
一种天真的方法会要求一个工人做所有的A urls,然后是B,.,最后是F urls。所以我们敲击A,或者花很长时间在睡眠()上,通过A urls来工作。对于那个工作人员来说,按顺序访问这些站点更好一些F被A认为是“睡眠”延迟。
现在假设我们有两个工人。如何协调?(用最少的沟通!)取每个url的SHA1散列,让worker-0处理偶数,worker-1处理奇数。对于四个工作人员,我们查看两个低阶哈希位,通常mod N允许我们字段N个工作人员。
我们很少需要在每个站点上爬行相同数量的urls,但是上面的草图仍然可以指导我们。剥离“足够大”的urls批次,这样爬虫器和原始web服务器所做的工作将被适当地分散开来,没有影响生产用户所看到的延迟的热点。按urls的数量订购站点,并确保将前几个站点合并到早期批中。
发布于 2023-05-23 00:49:19
正如其他人所提到的,可以使用队列来分配工作负载。这个响应是不同的,因为它按页面粒度分配工作负载。
这里的队列应该类似于SQS,其中每个消息都是代理的,而不是一个(Kafka)流。队列由调度程序播种,并由网站(S)进行爬行。爬虫(工作人员)侦听队列上的消息。( worker实例可以让多个线程侦听同一个队列。)抓取器,作为爬行网页的一部分,如果遇到需要爬行的链接,就会在相同的队列中添加一条消息。爬行页面后,消息将从队列中删除。
这创建了一个健壮的体系结构,可以根据需要添加或移除工作人员。此外,如果工作人员停机,消息将重新出现在队列中,并由另一个工作人员处理。可以使用DB跟踪爬行的进度,并跟踪页面是否已经被爬行,以避免重新爬行。
https://softwareengineering.stackexchange.com/questions/445649
复制相似问题