在EC2 / Elastic Beanstalk上复制AppEngine的任务队列工具

时间:2011-03-25 19:58:37

标签: google-app-engine amazon-ec2 amazon-web-services

我正在考虑从AppEngine迁移到EC2 / Elastic Beanstalk,因为我需要位于EU内的服务器[AppEngine不提供服务器位置选项AFAIK]。我已经运行了Elastic Beanstalk示例应用程序,尽管它很好;但是我非常依赖的AppEngine功能之一是离线任务队列/ cron工具,因为我会定期从其他站点获取大量数据。我想知道我需要在Elastic Beanstalk / EC2上设置什么才能复制这个任务队列工具,是否还有最佳实践,需要做多少工作等等。

谢谢!

2 个答案:

答案 0 :(得分:1)

Beanstalk中cron服务的潜在问题是,如果应用程序在多个实例上运行,则可能由多个服务调用给定的调度命令。在运行的Tomcat实例之间需要协调以确保作业仅由一个运行,并且如果其中一个死亡,则cron服务不会被中断。

我如何实现它是这样的:

  1. 使用WAR打包cron作业“config file”。此文件应包含频率和URL(因为每个实际的cron只是对特定URL的调用,因为AE会这样做)
  2. 使用单个数据库表来维持协调。它至少需要两列。
    1. 用于保存命令及其频率的主键或唯一键(字符串)。 (例如“@daily http://your-app/some/cron/handler/url”)
    2. 保留最后执行时间的第二列。
  3. 每个tomcat实例都将运行一个cron线程,该线程应该从WAR读取配置,并根据需要安排自己休眠直到下一次服务调用。一旦时间到达,实例应首先尝试通过首先从数据库中获取该命令的最后一次调用时间来“声明”该调用,然后更新它以获得“锁定”。

    1. query(SELECT last_execution_time FROM crontable WHERE command = ?)
    2. if(NOW() - last_execution_time < reasonable window) skip;
    3. query(UPDATE crontable SET last_execution_time = NOW() WHERE command = ? AND last_execution_time = ?)
    4. if(number of rows updated == 0) skip;
    5. run task()
    6. 这里的关键元素是我们还在WHERE子句中包含last_execution_time,确保如果其他实例在SELECT和UPDATE之间更新它,更新将返回没有行受影响的情况和此实例将跳过执行该任务。

答案 1 :(得分:0)

如果您要移动自己的应用,最好只使用TyphoonAEAppScale。两者都是备用环境,您可以在其中不加修改地运行App Engine应用程序,并且都支持EC2。