简体   繁体   English

未来一段时间在App Engine上执行任务的最有效方法是什么?

[英]What's the most effective way to execute a task some distant time in the future on App Engine?

I have an application on App Engine which is consuming some data. 我在App Engine上有一个正在使用一些数据的应用程序。 After parsing that data, it will know that it needs to execute something in a period of time - possibly not for a number of hours or weeks. 解析该数据后,它将知道它需要在一段时间内执行某些操作-可能不需要数小时或数周。

What is the best way to execute a piece of code after some arbitrary amount of time on App Engine? 在App Engine上经过任意时间后,执行一段代码的最佳方法是什么?

I figured using Countdown Millis or EtaMillis from a TaskQueue would work, but haven't seen any evidence of anyone doing the same thing, especially for such long time frames. 我认为可以使用TaskQueue中的Countdown MillisEtaMillis起作用,但是还没有任何证据表明有人在做同样的事情,尤其是在这么长的时间范围内。

Is that the best approach, or is there a better way? 那是最好的方法,还是有更好的方法?

如果您能够使用所有相关信息将对象持久保存在数据存储中以备将来处理(包括何时开始处理对象数据的时间),则可以让cron作业定期使用日期/时间范围过滤器查询数据存储并在适当的时间触发处理上述任何对象。

We successfully use TaskQueue's countdown parameter for sending emails to customers 7 days after they registered and for number of other needs. 我们成功使用TaskQueue的countdown参数在注册后7天向客户发送电子邮件以及其他需求。

Task queues is core/basic API/service and are pretty reliable - my opinion it's a best way to go with task queues ETA/countdown unless you: 任务队列是核心/基本API /服务,并且非常可靠-我认为这是处理任务队列ETA /倒计时的最佳方法,除非您:

  • need ability programmatically see what is in the queue 需要能力以编程方式查看队列中有什么
  • need ability programmatically delete certain task from the queue 需要能力以编程方式从队列中删除某些任务

I'm using the task queue as a scheduler. 我正在使用任务队列作为调度程序。 There is a 30 day max eta declared in QueueConstants and applied in QueueImpl . QueueConstants中声明并在QueueImpl中应用的最大eta最长为30天。

  //Returns the maximum time into the future that a task may be scheduled.
  private static final long MAX_ETA_DELTA_MILLIS = 2592000000L;

1000ms * 60s * 60m * 24hr * 30days = 2592000000ms 1000ms * 60s * 60m * 24hr * 30天= 2592000000ms

 private long determineEta(TaskOptions taskOptions) {
Long etaMillis = taskOptions.getEtaMillis();
Long countdownMillis = taskOptions.getCountdownMillis();
if (etaMillis == null) {
  if (countdownMillis == null) {
    return currentTimeMillis();
  } else {
    if (countdownMillis > QueueConstants.getMaxEtaDeltaMillis()) {
      throw new IllegalArgumentException("ETA too far into the future");
    }
    if (countdownMillis < 0) {
      throw new IllegalArgumentException("Negative countdown is not allowed");
    }
    return currentTimeMillis() + countdownMillis;
  }
} else {
  if (countdownMillis == null) {
    if (etaMillis - currentTimeMillis() > QueueConstants.getMaxEtaDeltaMillis()) {
      throw new IllegalArgumentException("ETA too far into the future");
    }
    if (etaMillis < 0) {
      throw new IllegalArgumentException("Negative ETA is invalid");
    }
    return etaMillis;
  } else {
    throw new IllegalArgumentException(
        "Only one or neither of EtaMillis and CountdownMillis may be specified");
  }
}

} }

I do the following: 我执行以下操作:

  1. Enqueue a task with a delay configured as you mention. 按照您提到的配置延迟入队任务。 Have the task processing change datastore entries in a known way (for example: set a flag). 让任务处理以已知方式更改数据存储条目(例如:设置标志)。

  2. Have a stragglers low frequency cron job, to perform any processing that has somehow been missed by an enqueued task (for example: an uncaught exception happened in the task). 进行散乱的低频Cron作业,以执行排队任务以某种方式错过的任何处理(例如:任务中发生未捕获的异常)。

For this to work, ensure that the processing called by the tasks and cron job are idempotent. 为此,请确保任务和cron作业调用的处理是幂等的。

Enjoy? 请享用?

I think taskQueue is a good strategy but has one big problem "If a push task is created successfully, it will eventually be deleted (at most seven days after the task successfully executes)." 我认为taskQueue是一个不错的策略,但是有一个大问题:“如果成功创建了一个推送任务,它将最终被删除(在任务成功执行后最多7天)。” Source 资源

I would instead use the datastore . 我会改用数据存储区 here is one strategy you can take: 这是您可以采取的一种策略:

  1. Insert a record into datastore once you completed "parsing that data". 完成“解析数据”后,将记录插入数据存储中。
  2. Check the current date against the create/insert date to see how much time has passed by since your job was completed/started etc (clearly, you don't want to do every minute etc maybe do it once a day or every hour) 将当前日期与创建/插入日期进行对照,以查看自从您的工作完成/开始以来经过了多少时间(显然,您不想每分钟都这样做,也许每天或每小时都要做一次)
  3. Execute the next task that you need to do as soon as condition in step 2 become passed your "arbitrary amount of time" you want. 一旦步骤2中的条件通过所需的“任意时间”,就执行您需要做的下一个任务。

Here is how you can add a record to data store...to get you started .. 您可以通过以下方法将记录添加到数据存储中...以开始使用..

    Entity parsDataHolder = new Entity("parsing_data_done", guestbookKey);
    parsDataHolder.setProperty("date", date);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(parsDataHolder)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM