ChatGPT解决这个技术问题 Extra ChatGPT

如何将 Linux cron 作业转换为“亚马逊方式”?

无论好坏,我们已将整个 LAMP Web 应用程序从专用机器迁移到云(Amazon EC2 机器)。到目前为止进展顺利,但我们做 crons 的方式不是最佳的。我有一个亚马逊特有的问题,关于如何使用“亚马逊方式”最好地管理云中的 cron 作业。

问题:我们有多个网络服务器,并且需要为批处理作业运行 crons,例如创建 RSS 提要、触发电子邮件,实际上还有许多不同的事情。但是 cron 作业只需要在一台机器上运行,因为它们经常写入数据库,因此如果在多台机器上运行会重复结果。

到目前为止,我们将其中一个网络服务器指定为“主网络服务器”,它有一些其他网络服务器没有的“特殊”任务。云计算的权衡是可靠性——我们不想要“主网络服务器”,因为它是单点故障。我们希望它们都是相同的,并且能够在不记住不要将主网络服务器从集群中取出的情况下进行升级和降级。

我们如何重新设计我们的应用程序以将 Linux cron 作业转换为没有单点故障的临时工作项?

到目前为止我的想法:

有一台专门用于运行 crons 的机器。这将更易于管理,但仍然是单点故障,并且会浪费一些钱来获得额外的实例。

可以想象,一些工作可以从 Linux crons 转移到 MySQL Events,但是我不喜欢这个想法,因为我不想将应用程序逻辑放入数据库层。

也许我们可以在所有机器上运行所有的 cron,但是改变我们的 cron 脚本,使它们都从一些实现锁定机制的逻辑开始,这样只有一个服务器实际采取行动,而其他服务器只是跳过。我不喜欢这个想法,因为它听起来可能有问题,我更愿意使用亚马逊的最佳实践而不是自己动手。

我在想象这样一种情况,工作被安排在某个地方,添加到队列中,然后网络服务器每个都可以是一个工作人员,可以说“嘿,我会接受这个”。 Amazon Simple Workflow Service 听起来正是这种事情,但我目前对此了解不多,因此任何细节都会有所帮助。对于像 cron 这样简单的东西来说,它似乎有点重量级?它是正确的服务还是有更合适的亚马逊服务?

更新: 自从提出这个问题后,我在 YouTube 上观看了 Amazon Simple Workflow Service 网络研讨会,并在 34:40 (http://www.youtube.com/watch?v=lBUQiek8Jqk#t=34m40s) 注意到,我瞥见了一张幻灯片,其中提到了 cron 作业作为示例应用程序。在他们的文档页面“AWS Flow Framework samples for Amazon SWF”中,亚马逊说他们有 crons 的示例代码:

... > Cron 作业 在此示例中,长时间运行的工作流会定期执行活动。演示了将执行作为新执行继续执行的能力,以便执行可以运行很长时间。 ...

我下载了适用于 Java 的 AWS 开发工具包 (http://aws.amazon.com/sdkforjava/),果然埋在可笑的文件夹层中,有一些 java 代码 (aws-java-sdk-1.3.6/samples/AwsFlowFramework/src/com/amazonaws/services/simpleworkflow/flow/examples/periodicworkflow)。

问题是,老实说,这并没有真正的帮助,因为这不是我可以用我的技能轻松消化的东西。 PHP SDK 中缺少相同的示例,并且似乎没有指导该过程的教程。所以基本上,我仍在寻找建议或提示。


M
Michael Currie

我注册了 Amazon Gold 支持来问他们这个问题,这是他们的回答:

Tom 我对我的一些同事进行了一次快速调查,结果发现 cron 是空的,但在睡了之后我意识到重要的一步可能仅限于锁定。所以我找了“分布式 cron 作业锁定”,找到了一个 Apache 项目 Zookeeper 的引用。 http://zookeeper.apache.org/doc/r3.2.2/recipes.html http://highscalability.com/blog/2010/3/22/7-secrets-to-successfully-scaling-with-scalr-on -amazon-by-se.html 我还看到了使用 memcached 或类似的缓存机制作为使用 TTL 创建锁的方法的参考。通过这种方式,您设置了一个 TTL 为 300 秒的标志,并且没有其他 cron worker 将执行该作业。 TTL 过期后,锁会自动释放。这在概念上与我们昨天讨论的 SQS 选项非常相似。另见;谷歌的胖乎乎的 http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en//archive/chubby-osdi06.pdf 让我知道这是否有帮助,并随时提出问题,我们非常清楚对于初学者和经验丰富的开发人员来说,我们的服务可能很复杂且令人生畏。我们总是乐于提供架构和最佳实践建议。最好的问候, Ronan G. Amazon Web Services


老实说,“看谷歌的胖乎乎的”不是我期望的表达方式。
N
Nathan Buesgens

我认为这个视频回答了你的确切问题 - cronjobs aws 方式(可扩展和容错):

Using Cron in the Cloud with Amazon Simple Workflow

该视频使用实施 cronjobs 的特定用例描述了 SWF 服务。

如果您直接来自 crontab,则该解决方案的相对复杂性可能难以接受。最后有一个案例研究帮助我了解额外的复杂性会给你带来什么。我建议您观看案例研究并考虑您对可扩展性和容错性的要求,以决定是否应该从现有的 crontab 解决方案迁移。


这是一个很好的答案,因为它使用了来自 AWS 的良好支持的工具,而且 SWF 是一个强大的产品。 imo 唯一的缺点是 SWF 具有显着的学习曲线,并且很难用它来做复杂的事情。至少那是我对 Java 教程的体验
M
Maciej Majewski

将 SQS 用于 cronjobs 时要小心,因为它们不能保证“只有一台机器可以看到一个作业”。他们保证“至少一个”会收到消息。

来自:http://aws.amazon.com/sqs/faqs/#How_many_times_will_I_receive_each_message

问:每条消息我会收到多少次? Amazon SQS 旨在提供其队列中所有消息的“至少一次”传输。尽管大多数情况下每条消息都将只传递给您的应用程序一次,但您应该设计您的系统,以便多次处理消息不会产生任何错误或不一致。

到目前为止,我可以考虑一个安装了 Gearman 作业服务器实例的实例的解决方案:http://gearman.org/。在同一台机器上,您配置生成命令的 cron 作业以在后台执行您的 cronjob 任务。然后你的一个网络服务器(worker)将开始执行这个任务,它保证只有一个会接受它。你有多少工人并不重要(尤其是当你使用自动缩放时)。

这个解决方案的问题是:

Gearman 服务器是单点故障,除非您使用分布式存储对其进行配置,例如使用 memcached 或某些数据库

然后使用多个 Gearman 服务器,您必须选择一个通过 cronjob 创建任务的服务器,所以我们又回到了同样的问题。但是,如果您可以忍受这种单点故障,那么使用 Gearman 看起来是个不错的解决方案。特别是你不需要大实例(在我们的例子中微实例就足够了)。


好吧,消息在收到后会保留在服务器上。之后由开发人员删除它们。在处理它们时,其他服务器无法访问它们。
@FrederikWordenskjold 这是不正确的,即使在将一条消息提供给一个客户端之后,它仍然可以提供给另一个客户端,因为 SQS 状态的复制是异步的。您甚至可以在消息被删除“之后”获得其副本!
这个答案已经过时了 现在有两种类型的队列。使用 FIFO 获得 Exactly-Once 处理:消息被传递一次并保持可用,直到消费者处理并删除它。不会将重复项引入队列中。 aws.amazon.com/sqs/features
M
Michael Currie

Amazon 为 Elastic Beanstalk 提供了 released 个新功能。从 docs

AWS Elastic Beanstalk 支持在运行预定义配置的环境中对工作线程环境层执行定期任务,该配置的解决方案堆栈在容器名称中包含“v1.2.0”。 "

您现在可以创建一个包含配置调度任务的 cron.yaml 文件的环境:

version: 1
cron:
- name: "backup-job"          # required - unique across all entries in this file
  url: "/backup"              # required - does not need to be unique
  schedule: "0 */12 * * *"    # required - does not need to be unique
- name: "audit"
  url: "/audit"
   schedule: "0 23 * * *"

我想通过消息队列(SQS)使用在自动缩放环境中只运行一次的保险。当 cron 守护程序触发一个事件时,它会将调用放入 SQS 队列中,并且队列中的消息只被评估一次。文档说如果 SQS 有很多消息要处理,执行可能会延迟。


您能否还包括链接中的一些内容?
J
Jaap Haagmans

我现在第三次遇到这个问题,并认为我会参与进来。我们已经陷入困境有一段时间了。我仍然觉得 AWS 在这里缺少一个功能。

在我们的案例中,在查看了可能的解决方案后,我们决定有两种选择:

设置一个 cronjob 服务器,该服务器运行一次只能运行一次的作业,自动扩展它并确保在某些 CloudWatch 统计信息不应该是时替换它。我们使用 cloud-init 脚本来运行 cronjobs。当然,这会带来停机时间,从而导致错过 cronjobs(当每分钟运行某些任务时,就像我们一样)。

使用 rcron 使用的逻辑。当然,真正的魔力并不在于 rcron 本身,它在于您用来检测故障节点(我们在这里使用 keepalived)并将另一个节点“升级”为 master 的逻辑。

我们决定采用第二个选项,仅仅是因为它速度非常快,而且我们已经拥有运行这些 cronjobs 的网络服务器的经验(在我们之前的 AWS 时代)。

当然,此解决方案专门用于替换传统的单节点 cronjob 方法,其中时间是决定性因素(例如“我希望作业 A 每天早上 5 点运行一次”,或类似我们的案例“我希望作业 B 每分钟运行一次”)。如果您使用 cronjobs 来触发批处理逻辑,您应该真的看看 SQS。没有主动-被动的困境,这意味着您可以使用单个服务器或整个劳动力来处理您的队列。我还建议查看 SWF 来扩展您的员工队伍(尽管在大多数情况下 auto scaling 可能也能做到这一点)。

依赖另一个第三方是我们想要避免的。


T
Tom

2016 年 2 月 12 日,亚马逊发布了关于 Scheduling SSH jobs using AWS Lambda 的博客。我认为这回答了这个问题。


是否可以使用 AWS lambda 添加动态 cronjobs 或计划?
是的,您可以让 Cloudwatch 事件调用 Lambda。你认为合适的时间。
b
barbolo

如果您已经启动了 Redis 服务,这看起来是一个不错的解决方案:

https://github.com/kvz/cronlock

阅读更多:http://kvz.io/blog/2012/12/31/lock-your-cronjobs/


L
Lukas Liesis

“亚马逊”方式是分布式的,这意味着庞大的 crons 应该被分成许多较小的作业并交给正确的机器。

使用类型设置为 FIFO 的 SQS 队列,将其粘合在一起以确保每个作业仅由一台机器执行。它还容忍失败,因为队列将缓冲直到机器重新启动。

FIFO Exactly-Once Processing:消息被传递一次并保持可用,直到消费者处理并删除它。不会将重复项引入队列中。

还要考虑您是否真的需要“批处理”这些操作。如果一晚的更新比预期的大得多,会发生什么?即使使用动态资源,您的处理也可能会延迟,等待足够多的机器启动。相反,将您的数据存储在 SDB 中,通过 SQS 通知机器更新,并动态创建您的 RSS 提要(使用缓存)。

批处理作业始于处理资源有限且“实时”服务优先的时代。在云中,情况并非如此。


谢谢 - 我喜欢你描述的方向。
请注意,SQS 仅保证消息最终会被机器看到,而不是消息只会被单个服务器看到。您放入 SQS 队列的任何内容都应该是幂等的。
我的 cron 作业应该每天运行,而使用 SQS,您最多只能延迟 15 分钟。一种选择可能是在消息中添加一个自定义标签,其中包含执行它的目标时间,如果尚未达到该时间,则将其放回队列中 - 但这看起来确实是一件愚蠢的事情。此外,我仍然需要一个 cron 作业来最初填充队列。这似乎是一个先有鸡还是先有蛋的问题 :) 但我仍然认为使用 SQS 是正确的,因为它保证了可扩展性和容错性
“批处理作业是从处理资源有限且‘实时’服务优先的时代开始的。在云中,情况并非如此。”对于某些但不是所有活动都是如此。例如,处理流量日志作为批处理比实时处理更好。
我的讨论已经很晚了,但我认为更好的方法是让预定的 CloudWatch 事件充当玉米“ping”。这可以发布一个 SNS 主题,该主题由一个队列订阅,如果您需要一次性交付,该队列本身可以是一个 FIFO 队列。当然还有一些并发症,但这对我来说是一个不错的系统!
R
Rama Nallamilli

你为什么要建立自己的?为什么不使用 Quartz 之类的东西(带有集群调度)。请参阅文档。

http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJDBCJobStoreClustering


我在一个严重依赖计划任务的 SaaS 解决方案中使用了 Quartz.NET。有些是系统维护任务,但大多数是由最终用户安排的活动。我们所有的任务都写入消息队列(amq),我们有任意数量的幂等服务。 API 非常好,并允许强大的时间表。我们没有集群多个 Quartz 实例,但它确实支持。
P
Patrick Steil

我们所做的是我们有一个特定的服务器,它是我们 Web 应用程序集群的一部分,位于 ELB 后面,还分配了一个特定的 DNS 名称,以便我们可以在该特定服务器上运行作业。这还有一个好处是,如果该作业导致该服务器变慢,ELB 会将其从集群中删除,然后在作业结束并再次恢复健康时将其返回。

像冠军一样工作。


K
Kevin Eid

验证您的 cron 表达式是否以 Amazon 方式工作的一种方法是通过 events 命令运行它。例如:

aws events put-rule --name "DailyLambdaFunction" --schedule-expression "<your_schedule_expression>

如果您的计划表达式无效,那么这将失败。

更多资源:https://docs.aws.amazon.com/cli/latest/reference/events/put-rule.html


j
johnnyodonnell

如果您愿意使用非 AWS 服务,则可以查看 Microsoft Azure。 Azure 提供了很好的job scheduler


w
wanghq

由于没有人提到 CloudWatch Event,我会说这是 AWS 执行 cron 作业的方式。它可以运行许多操作,例如 Lambda 函数、ECS 任务。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅