我正在尝试解决以下问题:
- 我有一系列想要执行的“任务”
- 我有固定数量的工作人员来执行这些工作人员(因为它们使用 urlfetch 调用外部 API,并且对此 API 的并行调用数量有限)
- 我希望这些“任务”能够“尽快”执行(即最小延迟)
- 这些任务是较大任务的一部分,可以根据原始任务的大小进行分类(即,小型原始任务可能生成 1 到 100 个任务,中型任务可能生成 100 到 1000 个任务,大型任务可能生成超过 1000 个任务)。
棘手的部分:我想高效地完成所有这些(即最小延迟并使用尽可能多的并行 API 调用 - 不超过限制),但同时尝试防止从“生成大量任务” “大”原始任务延迟“小”原始任务生成的任务。
换句话说:我希望为每个任务分配一个“优先级”,其中“小”任务具有更高的优先级,从而防止“大”任务导致饥饿。
一些搜索似乎并没有表明任何预制的东西可用,所以我想出了以下内容:
- 创建三个推送队列:
tasks-small
, tasks-medium
, tasks-large
- 为每个请求设置最大并发请求数,使总数达到并发 API 调用的最大数量(例如,如果并发 API 调用的最大数量为 200,我可以设置
tasks-small
有一个max_concurrent_requests
of 30, tasks-medium
60 and tasks-large
100)
- 排队任务时,检查编号。每个队列中待处理的任务(使用类似 QueueStatistics 类的东西),并且,如果其他队列未 100% 使用,则将任务排入其中,否则只需将任务排入具有相应大小的队列中。
例如,如果我们有任务T1
这是一个小任务的一部分,首先检查是否tasks-small
有空闲的“槽”并将其排在那里。否则检查tasks-medium
and tasks-large
。如果它们都没有空闲插槽,则将其排队tasks-small
无论如何,它将在处理之前添加的任务之后进行处理(注意:这不是最佳选择,因为如果“槽”在其他队列上释放,它们仍然不会处理来自tasks-small
queue)
另一种选择是使用 PULL 队列,并让一个中央“协调器”根据优先级从该队列中拉取并分派它们,但这似乎会增加一点延迟。
然而,这似乎有点黑客,我想知道是否有更好的替代方案。
编辑:经过一些想法和反馈后,我正在考虑通过以下方式使用 PULL 队列:
- 有两个 PULL 队列(
medium-tasks
and large-tasks
)
- have a dispatcher (PUSH) queue with a concurrency of 1 (so that only one dispatch task runs at any time). Dispatch tasks are created in multiple ways:
- 通过每分钟一次的 cron 作业
- 将中型/大型任务添加到推送队列后
- 工作任务完成后
- 有一个并发量等于工作人员数量的工作人员(PUSH)队列
以及工作流程:
- 小任务直接添加到工作队列中
- the dispatcher task, whenever it is triggered, does the following:
- 估计空闲工作人员的数量(通过查看工作人员队列中正在运行的任务数量)
- 对于任何“空闲”槽,它会从中/大型任务 PULL 队列中获取一个任务,并将其放入工作线程中(或者更准确地说:将其添加到工作线程 PUSH 队列中,这将导致它最终在工作线程上执行) 。
一旦实施并至少经过适度测试,我会报告。
小/中/大原始任务队列本身不会有太大帮助 - 一旦原始任务排队,它们将继续生成工作任务,甚至可能突破工作任务队列大小限制。因此,您需要调整/控制原始任务的排队速度。
我会跟踪数据存储/GCS 中的“todo”原始任务并将这些原始任务排入队列仅当相应的队列大小足够低时(1 个或可能 2 个待处理作业),来自循环任务、cron 作业或延迟任务(取决于您需要执行原始任务排队的速率),这将像推送队列调度程序一样实现所需的节奏和优先级逻辑,但无需额外的你提到的延迟。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)