作业调度系统设计

作业调度系统设计

问题:

实现在指定时间调用 API/BASCH 脚本的调度程序。

要求:

  1. 用于运行 API/BASH 脚本的分布式作业调度程序
  2. 平均执行时间为 1 小时。
  3. 作业将获取配置信息,其中包括 CRON 格式的调度程序信息和 BASCH 脚本。

例子:

例如:每天中午 12:00(中午)开火

0 0 12 * * ?入口.sh

4. 节流——没有足够的机器,遵循先进先出。

5.重试失败的工作——3次

6. 如果工作时间超过 1 小时,终止工作。

非功能性要求:

可扩展

可靠的

可用的

设计与推理:

工作流程:

想要安排工作的客户,他们调用名为 Job Accepter 的服务。

作业接受器位于反向代理后面,该代理也充当负载平衡器。

Job Acceptor 公开了如下 API:

  1. 添加工作
  2. 删除作业
  3. 暂停作业
  4. 编辑作业

作业接受者将接受作业定义并保留在数据存储中。

RDBMS 在这里很好,因为我们需要强一致性。

保存作业定义的架构是

JOB_ID -> 主键

USER_ID -> 谁安排了这个工作

CRON_EXPRESSION -> 原始表达式

LAST_FIRED_AT -> 上次作业运行时间戳

LAST_EXECUTION_RUN_STATUS -> 完成/失败/中止

NEXT_FIRE_TIME -> 下一次作业运行的时间戳

状态 -> 活动/暂停

BASCH_SCRIPT -> 脚本作为任务运行的一部分运行。

Job Scheduler 是一个组件,它从 DB 中获取作业并添加到队列中。

如果需要,作业调度程序可以在调度作业时考虑优先级/FIFO 顺序。

为了避免单点故障,我们可以有一个辅助调度器,它在主调度器关闭时将处于活动状态。

作业调度程序不知道此设计中的工作人员状态。这将导致松散耦合。

我们可以在这里使用像 SQS 这样的基于云的队列服务。

我想快速总结一下 SQS 的一般工作原理

当生产者向 SQS 发送消息时,消息将被存储,直到消费者被消费。

消费者轮询 SQS 队列以获取新消息。

消费者拿起消息后,消息不会自动从队列中删除。

从 SQS 中删除消息是消费者的工作。

这是为了防止消息在传输过程中丢失或消费者在处理消息时失败等问题。

SQS 如何防止只有一个消费者正在处理消息?

它需要可见性超时设置的帮助。默认值为 30 秒。

根据这个超时值,SQS 在消费者拿起消息的那一刻使消息不可见。消费者必须在超时窗口中处理消息并将其删除,否则消息将对其他消费者可见并准备再次被拾取。

如果消费者认为需要额外的时间来处理该消息,SQS 还提供了让消费者延长可见性时间的灵活性。

因此,最好的策略是

1. 将超时设置为消费者处理和删除消息所需的最大值。

0r

2. 如果您事先不知道此值,请将超时设置为基线值并继续扩展它,直到您的消费者完成消息。

一个更重要的配置是传递延迟,它可以用来延迟处理消息,即使它被添加到队列中。

SQS 还维护每条消息的接收计数,指示消息重试了多少次。

可以在此处阅读有关 SQS 的更多信息。

https://medium.com/geekculture/11-1-things-you-need-to-know-about-sqs-parameters-and-configurations-e7415f61fb93

工作人员:

作业工作者可以长时间轮询队列以运行新作业。一旦他们收到,他们可以尝试在要求中提到的一小时内完成工作。这个一小时的消息在 SQS 中是不可见的。

如果作业成功完成,worker 可以更新数据存储中的作业状态并将新消息推送到已完成队列。

我们可以根据已完成的队列消息构建指标和仪表板。

如果工作没有在一个小时内完成,工人将杀死它。消息将再次变为可见以进行重试。

如果作业失败,在这种情况下,我们也可以重试相同的消息。

超过 3 次重试后,我们可以将消息移动到 DLQ,然后我们可以从那里更新数据存储作业运行历史表。

跟进问题?

  1. 您如何处理没有计划的工作激增?

我们可以实现一个基于队列大小添加/删除工作人员的组件。这类似于自动缩放。

2. 执行成功后,worker在从SQS中删除消息之前就死掉了怎么办?

这是一个难以处理的场景。最好的解决方案是让工作 IDEMPOTENT。提供工作定义的客户应该使他们的工作具有幂等性。

3. Job Scheduler 多久轮询一次数据库中的新作业?

我们可以每分钟轮询一次并选择应该在下一分钟安排的作业,并将它们添加到具有交付延迟配置的 SQS。

例如,如果需要在接下来的 30 秒内安排一个作业,我们可以将作业消息添加到队列中,延迟 30 秒。消息仅在 30 秒后可见。

4. 谁来计算作业的下一次运行时间?

当调度程序将作业推送到队列中时,它可以在数据存储中更新下一个触发时间。

5.我们如何处理机器之间的时区差异?

我们可以在任何地方使用 UTC 来拥有共同的时区。

快乐学习:)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/39748/35022909

posted @   哈哈哈来了啊啊啊  阅读(86)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示