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


112

不管是好是坏,我们已经将整个LAMP Web应用程序从专用计算机迁移到了云(Amazon EC2计算机)。这将极大到目前为止,但我们做的方式crons是次优的。我有一个特定于亚马逊的问题,关于如何使用“亚马逊方式”最好地管理云中的cron作业。

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

到目前为止,我们将其中一个Web服务器指定为“主Web服务器”,它具有其他Web服务器所没有的一些“特殊”任务。云计算的权衡是可靠性-我们不希望有“主服务器”,因为它是单点故障。我们希望它们全部相同,并且能够进行升迁和降尺度,而不必记住不要将主Web服务器从群集中移出。

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

到目前为止,我的想法是:

  • 有一台专用于仅运行克朗的机器。这将更易于管理,但仍将是单点故障,并且由于额外的实例而浪费一些钱。
  • 可以将一些作业从Linux克隆转移到MySQL Events,但是我并不赞成这个想法,因为我不想将应用程序逻辑放入数据库层。
  • 也许我们可以在所有机器上运行所有cron,但是可以更改cron脚本,因此它们都以实现锁定机制的逻辑开始,因此只有一台服务器实际采取了行动,而其他服务器只是跳过了。我不是这个想法的拥护者,因为它听起来可能有问题,我宁愿使用Amazon的最佳实践而不是自己动手做。
  • 我正在想象这样一种情况:将作业安排在某个地方,添加到队列中,然后Web服务器可能每个都是工人,可以说“嘿,我来接这个”。Amazon Simple Workflow Service听起来完全是这种事情,但我目前对此了解不多,因此任何细节都将有所帮助。像cron这样简单的东西似乎有点沉重?是正确的服务还是有更合适的亚马逊服务?

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

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

我下载了适用于Java的AWS开发工具包(http://aws.amazon.com/sdkforjava/),并确保将足够的代码埋在一个荒谬的文件夹层中aws-java-sdk-1.3.6/samples/AwsFlowFramework/src/com/amazonaws/services/simpleworkflow/flow/examples/periodicworkflow

问题是,如果我说实话,这并没有真正的帮助,因为这不是我可以轻松使用自己的技能组合来消化的东西。PHP SDK中缺少相同的示例,并且似乎没有教程可循此过程。因此,基本上,我仍在寻找建议或技巧。


Answers:


38

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

汤姆

我对我的一些同事进行了快速调查,发现自己的工作空无一人,但是在睡觉之后,我意识到重要的一步可能仅限于锁定。因此,我寻找“分布式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工作者都不会执行该作业。TTL过期后,该锁定将自动释放。从概念上讲,这与我们昨天讨论的SQS选项非常相似。

另见; Google的胖 http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en//archive/chubby-osdi06.pdf

让我知道这是否有帮助,并随时提出问题,我们非常了解我们的服务可能很复杂,无论对于初学者还是经验丰富的开发人员均如此。我们总是很乐意提供架构和最佳实践建议。

最好的祝福,

Ronan G.亚马逊网络服务


13

我认为这段视频回答了您的确切问题-cronjobs aws方式(可伸缩且容错):

通过Amazon Simple Workflow在云中使用Cron

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

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


2
这是一个很好的答案,因为它使用了AWS提供的受支持的工具,而SWF是功能强大的产品。imo唯一的缺点是,SWF的学习曲线很长,很难用它来做复杂的事情。至少那是我对Java教程的经验
Don Cheadle 2014年

11

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

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

问:每条消息我会收到多少次?

Amazon SQS经过精心设计,可以“至少一次”传递其队列中的所有消息。尽管在大多数情况下,每条消息都会一次准确地传递到您的应用程序,但是您应该对系统进行设计,以使多次处理一条消息不会造成任何错误或不一致。

到目前为止,我可以考虑以下解决方案:在其中安装了一个Gearman Job Server实例的实例:http : //gearman.org/。在同一台计算机上,您配置正在生成命令的cron作业,以在后台执行cronjob任务。然后,您的一台Web服务器(工作人员)将开始执行此任务,从而确保只有一台服务器可以承担此任务。拥有多少工人无关紧要(尤其是在使用自动缩放时)。

该解决方案的问题是:

  • Gearman服务器是单点故障,除非您使用分布式存储(例如,使用memcached或某些数据库)对其进行配置
  • 然后,使用多个Gearman服务器,您必须选择一个通过cronjob创建任务的服务器,因此我们又回到了同样的问题。但是,如果您可以忍受使用Gearman的这种单点故障,那将是一个很好的解决方案。特别是您不需要大实例(在我们的例子中,微实例就足够了)。

好了,收到消息后,消息会保留在服务器上。由开发人员将其删除。在处理它们时,它们不能被其他服务器访问。
Frederik Wordenskjold

2
@FrederikWordenskjold这是不正确的,即使在已将消息发送给一个客户端之后,仍然可以将消息传递给另一个客户端,因为SQS状态的复制是异步的。您甚至可以在删除消息后获得消息的副本!
克里斯·皮特曼

这个答案已经过时了。现在有2种队列。使用FIFO进行一次精确处理:消息只传递一次,并一直可用,直到使用者处理并删除它。副本不引入队列。aws.amazon.com/sqs/features
Lukas Liesis

10

亚马逊刚刚发布了Elastic Beanstalk的新功能。从文档


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

现在,您可以创建一个环境,其中包含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有许多消息要处理,则执行可能会延迟。


您还可以在链接中包含一些内容吗?
罗伯特

6

我第三次遇到这个问题,以为自己会陷入困境。我们已经有一段时间处于这种困境了。我仍然真的感到AWS在这里缺少功能。

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

  • 设置一个cronjob服务器,该服务器运行一次只能运行一次的作业,自动缩放并确保在某些CloudWatch统计数据不正确时将其替换。我们使用cloud-init脚本来运行cronjobs。当然,这会伴随停机时间,导致错过cronjobs(每分钟运行某些任务时,就像我们一样)。
  • 使用所使用的逻辑rcron。当然,魔术rcron本身并不真正,它在于您用来检测故障节点(我们keepalived在此使用)并“升级”另一个节点以掌握的逻辑。

我们决定选择第二种方法,只是因为它速度极快,而且我们已经具有运行这些cronjobs的Web服务器的经验(在AWS之前的时代)。

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

我们希望避免依赖第三方。




4

“亚马逊”方式将被分发,这意味着笨重的箱子应该被分割成许多较小的工作,并交给合适的机器。

使用类型设置为FIFO的SQS队列,将其粘合在一起以确保每个作业仅由一台计算机执行。由于队列将一直缓存到计算机回滚,因此它也可以容忍故障。

先进先出(FIFO)一次处理:一条消息仅传递一次,并一直可用,直到使用者处理并删除它。副本不引入队列。

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

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


谢谢-我喜欢您所描述的方向。
汤姆(Tom)

5
请注意,SQS仅保证最终一台机器可以看到一条消息,而不保证仅一台服务器可以看到该消息。您放入SQS队列中的任何东西都是幂等的。
理查德·赫特

我的Cron工作应该每天运行,而使用SQS,您最多只能延迟15分钟。一种选择是在消息中添加自定义标签,并在目标时间执行消息,如果尚未达到该时间,则将其放回队列中-但这确实是一件愚蠢的事情。另外,我仍然需要cron作业来初始填充队列。似乎是个鸡蛋问题:)但是我仍然认为SQS是正确的选择,因为它可以确保可伸缩性和容错能力
Raffaele Rossi 2014年

“批处理作业是从有限的处理资源和'实时'服务优先的时代开始的。在云计算中,情况并非如此。” 对于部分但并非全部活动都是如此。例如,处理流量日志在批处理过程中要比实时处理更好。
Jordan Reiter 2015年

1

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

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


我在严重依赖计划任务的SaaS解决方案中使用了Quartz.NET。有些维护任务由系统维护,而大多数维护任务由最终用户安排。我们所有的任务都写入了我们拥有任意数量幂等服务的消息队列(amq)。该API非常好,并且允许强大的计划。我们没有集群多个Quartz实例,但是它确实支持。
杰里科·桑德霍恩

1

我们要做的是在ELB后面的Web应用程序集群中有一台特定的服务器,该服务器还分配了一个特定的DNS名称,以便我们可以在该特定服务器上运行作业。这还有一个好处,就是如果该作业导致该服务器速度降低,则ELB会将其从群集中删除,然后在作业结束后又将其返回并恢复正常。

像冠军一样工作。




0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.