每小时调用外部 API 并分别执行约 10000 行任务的作业

Job to call external API every hour and perform tasks for ~10000 rows individually

我目前正在考虑设计一个系统,该系统基本上需要每小时 运行 一项工作,但大约需要 10,000 行。然后,这些行中的每一行都需要调用外部 api 并在分析方面做一些其他工作。

我目前正在努力找出实现此目标的最佳方法,但我以前从未做过类似的事情,因此非常感谢任何人提供的建议或指导。我主要习惯于 GCP,所以我将我的想法集中在可用的工具上(这也很可能在 JS/Node 环境中完成)。

我初步的设计思路如下。

我让第一个函数将项目添加到队列的原因显然是云函数受执行时间和内存的限制,所以我认为让一个函数尝试自己处理所有行是不明智的。我假设 pub/sub 每次都会触发函数的新实例而不是覆盖第一个?

我想理论上我可以批处理一些外部 API 调用,一次最多可以处理 20 个左右,所以我不知道 would/should 是否对上述有影响设计.

我显然也希望它的成本尽可能低,所以我不知道让应用引擎实例执行此操作是否会更好?但是我也不知道我是否会 运行 进入内存和那里的超时问题。

我在写这篇文章时想到的一个想法是,我是否可以按原样对这些批次进行批处理。来自 JS 背景,我可以创建所有批处理 API 调用并在 Promise.all() 调用中执行它们。再次不确定这对内存和性能的影响,所以我想我需要测试它。

有没有人注意到上面的 gaping 漏洞,或者有更好的解决方案吗?

谢谢

您设计的第一部分是正确的(Cloud Scheduler -> CLoud Functions -> PubSub 中的消息)。

此处,对每条消息调用 Cloud Functions。 IMO,这不是最佳选择,因为您一次只能在 Cloud Functions 实例上处理 1 个请求。如果你执行外部 API 调用,你将白白浪费时间(你将等待答案,什么都不做)。

更好的解决方案是使用管理并发请求的产品,例如 Cloud Run or App Engine。使用 Cloud 运行 您最多可以有 250 个并发请求,但使用 App Engine 只能有 80 个。

使用这种解决方案,您将节省大量金钱和时间。


关于批处理,我不太懂。

  • 如果您可以在向外部 API 的 1 个请求中发送 20 条消息中包含的 20 个值,是的,最好对请求进行批处理(在您的第一个 Cloud Functions 中创建 20 条消息块)
  • 如果你继续一个一个发送请求,但是你使用语言的并发能力(Node 或 Go 在这方面很少),与一个一个地处理消息相比,没有真正的优势。

事实上,您会减少调用次数(但它真的很便宜),相反,会增加代码的复杂性。不确定是否值得。


编辑 1

事实上,PubSub 不会生成任何 Cloud 运行 实例。 PubSub 订阅仅将消息推送到 URL。 PubSub 的工作到此结束。

现在,在云端 运行 端,服务根据 HTTP 流量进行扩展。因此,平台选择创建 1 个、2 个或更多实例来吸收流量。在您的情况下,该平台将创建很多实例(我认为大约 100 个),但您只需为实例处理流量付费。不处理请求,不计费。

您还可以使用 max instance 参数限制 Cloud 运行 上的并行实例数。有了它,你既可以限制成本,又可以限制处理能力。

现在,关于延迟,当然有不同的来源。

  1. 当您在 PubSub 中发布消息时,在第一个创建和第 10kth 之间存在“延迟”。
  2. 每次云运行平台创建一个新实例时,实例需要启动并初始化其运行时间环境(称为冷启动);根据您的开发语言和设计,它可能需要几毫秒(大约 200 - 500)或几秒(例如 Spring Boot)。您可以想象使用 min instance 功能来保持多个实例的温暖,从而限制 clod start 的数量。但是,每小时 1 运行,这个功能对你来说可能太贵了(IMO,我不推荐这个)
  3. 在同一个实例上,如果您同时处理 250 个请求,它们必须共享相同的 CPU 资源,并且一些请求将等待 CPU 时间来处理它们。您可以增加 CPU 的数量以减少此延迟(例如设置 4vCPU),但这是任何多线程系统的正常行为。