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

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

问题 :我们有多个web服务器,需要运行crons来进行批量作业,比如创buildRSS feed,触发电子邮件,实际上有很多不同的事情。 但是cron作业只需要在一台机器上运行,因为它们经常写入数据库,所以如果在多台机器上运行,就会复制结果。

到目前为止,我们将其中一个networking服务器指定为“主networking服务器”,并且具有其他networking服务器所没有的一些“特殊”任务。 云计算的权衡是可靠的 – 我们不需要一个“主 – networking服务器”,因为这是一个单一的故障点。 我们希望它们都是相同的,并且能够升级和降级,而不用记住不把master-web服务器带出集群。

我们如何重新devise我们的应用程序,将Linux cron作业转换为没有单点故障的暂时性工作项?

我的想法到目前为止:

  • 有一台机器专门只运行crons。 这样会更容易pipe理,但仍然是一个单一的失败点,并会浪费一些金钱有额外的实例。
  • 有些工作可以想象从Linux cron移到MySQL Events,但是我并不是很喜欢这个想法,因为我不想将应用程序逻辑放到数据库层。
  • 也许我们可以在所有的机器上运行所有的cron,但是改变我们的cron脚本,使它们都以一些实现locking机制的逻辑开始,所以只有一个服务器实际上采取行动,其他的只是跳过。 我不是这个想法的粉丝,因为这听起来可能是错误的,我宁愿使用亚马逊的最佳做法,而不是滚动我们自己的。
  • 我想象的是一个工作安排在某个地方的情况,join队列,然后networking服务员可以成为一名工作人员,可以说“嗨,我会拿这个工作的”。 亚马逊简单的工作stream服务听起来正是这样的事情,但我目前不知道太多,所以任何细节将有所帮助。 对于像cron这样简单的东西来说,它似乎有点沉重? 这是正确的服务还是有更合适的亚马逊服务?

更新:由于提问我已经观看了YouTube上的亚马逊简单工作stream服务networking研讨会,并在34:40注意到( http://www.youtube.com/watch?v=lBUQiek8Jqk#t=34m40s ),我瞥见了一个将提及cron作业的幻灯片作为示例应用程序提供。 在他们的文档页面,“ 亚马逊SWF的AWS Flow Framework示例 ”中,亚马逊说他们有crons的示例代码:

> Cron作业在本示例中,长时间运行的工作stream会定期执行一个活动。 演示了将执行继续作为新执行的能力,以便执行可以在非常长的时间内运行。 …

我下载了适用于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中缺less同样的示例,似乎没有一个教程能够通过这个过程。 所以基本上,我还在寻求build议或提示。

我注册了亚马逊金牌支持,问他们这个问题,这是他们的回应:

汤姆

我对我的一些同事做了一个快速的调查,并在cron上空了,但在睡了之后,我意识到重要的一步可能仅限于locking。 于是我寻找“分布式cron作业locking”,并find了一个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或类似的caching机制来创buildTTL的方法。 用这种方法设置一个标志,TTL为300秒,没有其他的cron worker会执行这个任务。 TTL过期后,锁将自动释放。 这在概念上与我们昨天讨论的SQS选项非常相似。

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

让我知道,如果这有帮助,并随时提出问题,我们非常清楚,我们的服务可能是复杂和艰巨的初学者和经验丰富的开发人员都。 我们总是乐于提供build筑和最佳实践的build议。

最好的祝福,

Ronan G.amazon web services

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

使用Amazon简单工作stream在云中使用Cron

该video使用实现cronjob的特定用例来描述SWF服务。

如果您直接从crontab中获得解决scheme,则解决scheme的相对复杂性可能难以满足。 最后还有一个案例研究,帮助我了解额外的复杂性会给您带来什么。 我build议观察案例研究,并考虑您对可扩展性和容错性的要求,以决定是否应该从现有的crontab解决scheme进行迁移。

对cronjobs使用SQS要小心,因为他们不能保证只有“一个工作只能看到一台机器”。 他们保证“至less有一个”会得到这个信息。

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

问:我会收到多less封邮件?

Amazon SQS被devise为提供队列中所有消息的“至less一次”传递。 尽pipe大部分时间每个消息都会被传送到应用程序中,但是您应该devise系统,以便多次处理消息不会产生任何错误或不一致。

到目前为止,我可以考虑安装有Gearman Job Server实例的一个实例的解决scheme: http : //gearman.org/ 。 在同一台计算机上,您可以configuration正在生成命令的cron作业,以在后台执行您的cronjob任务。 然后你的一个networking服务器(工作人员)将开始执行这个任务,它保证只有一个人会接受它。 不pipe你有多less工人(特别是当你使用自动缩放)。

这个解决scheme的问题是:

  • Gearman服务器是单点故障,除非您使用分布式存储进行configuration,例如使用memcached或某些数据库
  • 然后使用多个Gearman服务器,你必须select一个通过cronjob创build任务,所以我们又回到了同样的问题。 但是如果你能忍受这种使用Gearman的单点故障看起来相当不错的解决scheme。 特别是你不需要大的实例(在我们的例子中是微观实例就足够了)。

亚马逊刚刚发布了Elastic Beanstalk的新function。 从文档 :

AWS Elastic Beanstalk支持工作人员环境的定期任务
在运行预定义configuration的环境中使用包含“v1.2.0”的解决scheme堆栈。 “

现在可以创build一个包含configuration调度任务的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有很多消息要处理,执行可能会被延迟。

我现在第三次遇到这个问题,并认为我会陷入困境。现在我们已经有了这个困境。 我仍然觉得AWS在这里缺less一个function。

在我们的案例中,在看到可能的解决scheme后,我们决定有两个select:

  • 设置一个cronjob服务器,运行一次只能运行一次的作业,自动缩放它,并确保在某些CloudWatch统计信息不是他们应该的时候将其replace。 我们使用cloud-init脚本来运行cronjob。 当然,这是一个停机时间,导致错过cronjobs(每分钟运行一些任务,就像我们一样)。
  • 使用rcron使用的逻辑。 当然,魔术本身并不在rcron ,它是用来检测失败节点的逻辑(我们在这里使用keepalived )和“升级”另一个节点来掌握。

我们决定采用第二种scheme,仅仅因为速度非常快,而且我们已经有了运行这些cronjob的web服务器的经验(在我们之前的AWS时代)。

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

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

亚马逊在12 / Feb / 16上发表了关于使用AWS Lambda调度SSH作业的博客。 我认为这回答了这个问题。

“亚马逊”的方式是分布式的,这意味着庞大的克朗应该分成许多小的工作,并交给正确的机器。 使用SQS将它们粘合在一起可确保每台作业只有一台机器可见。 它也容忍失败,因为队列将缓冲直到一台机器恢复。

还要考虑你是否真的需要“批量”这些操作。 如果一晚的更新比预期的要大得多,会发生什么? 即使dynamic资源,您的处理可能会延迟等待足够的机器旋转起来。 相反,将数据存储在SDB中,通过SQS通知计算机更新,并快速创buildRSS提要(使用caching)。

批处理作业来自处理资源有限且“实时”服务优先的时间。 在云端,情况并非如此。

如果您已经有Redis服务,这看起来是一个很好的解决scheme:

https://github.com/kvz/cronlock

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

你为什么要build立自己的? 为什么不使用像Quartz(与群集调度)。 见文件。

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

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

像冠军一样工作。

如果您愿意使用非AWS服务,那么您可以检出Microsoft Azure 。 Azure提供了一个很好的调度程序 。

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