有没有办法使用 App Engine Java 运行时动态设置任务的目标?

Is there a way to set the target for a task dynamically with the App Engine Java runtime?

当使用 App Engine Python 运行 时间排队后台任务时,您可以 specify a target for the queue 将任务发送到 运行 特定服务,版本或实例:

task = taskqueue.add(
    url='/update_counter',
    target='worker',
    params={'amount': amount})

Java有没有办法做到这一点?文档 mentions the target parameter but doesn't show an example of how to use it. The Queue.add method has no option for target. The TaskOptions class 也没有任何看起来像 target 的内容。

,但答案是在queue.xml中配置。我想在 运行 时间选择目标,例如 Python。

TL;DR - 可能有一种方法可以根据早期版本的文档执行此操作,但这在最新版本的文档中没有描述。

基于最新文档的方法

根据 latest documentation regarding Push queues(正如您已经提到的那样),您可以根据 queue 在 queue.xml 中配置目标模块和版本。如果指定,任务请求将发送到指定的目标。正如您已经描述的那样,这是一个静态配置,并没有真正回答您的问题(只是为了完整性而描述)。

<?xml version="1.0" encoding="UTF-8"?>
  <queue-entries>
    <queue>
      <name>queue-blue</name>
      <target>v2.task-module</target>
    </queue>
    <queue>
      <name>queue-red</name>
      <rate>1/s</rate>
    </queue>
  </queue-entries>

documentation for creating tasks and specifying worker service中,它描述了为任务选择的目标,但没有明确描述如何指定它。

When a task is popped off its queue, the Task Queue service sends it on to a worker service. Every task has a target and a url, which determine what service and handler will ultimately perform the task.

target

The target specifies the service that will receive the HTTP request to perform the task. It is a string that specifies a service/version/instance in any one of the canonical forms. The most often-used ones are:

service
version.service
instance.version.service

The target string is prepended to the domain name of your app. There are three ways to set the target for a task:

  • Explicity declare the target when you construct the task.
  • Include a target directive when you define a queue in the queue.xml, as in the definition of queue-blue above. All tasks added to a queue with a target will use that target, even if a different target was assigned to the task at construction time.
  • If no target is specified according to either of the previous two methods, then the task's target is the version of the service that enqueues it. Note that if you enqueue a task from the default service and version in this manner, and the default version changes before the task executes, it will run in the new default version.

url

The url selects one of the handlers in the target service, which will perform the task.

The url should match one of the handler URL patterns in the target service. The url can include query parameters if the tasks's method is GET or PULL. If no url is specified the default URL /_ah/queue/[QUEUE_NAME] is used, where [QUEUE_NAME] is the name of the task's queue.

根据上述文档,如果您查看 TaskOptions.Builder,则没有指定任务目标的方法。这可能表明缺少有关如何指定目标的文档,或者只是在将任务添加到 queue 时无法再动态指定目标。根据早期文档查看下面描述的方法。

基于早期文档的方法

免责声明: 我在这里提到的内容看起来是基于过时的信息(我在下面引用了来源)因此可能无法按预期工作 and/or 中断将来。

您可以使用Host header指定将获取请求的模块、版本和实例信息。

要指定模块和版本,您可以这样做:

Queue queue = QueueFactory.getQueue("QUEUE_NAME");
    queue.add(TaskOptions.Builder
            .withUrl("/url/path")
            .param("key", "PARAM")
            .header("Host",
                    ModulesServiceFactory.getModulesService().getVersionHostname("MODULE_NAME", "VERSION")));

要指定实例,您可以执行以下操作:

Queue queue = QueueFactory.getQueue("QUEUE_NAME");
    queue.add(TaskOptions.Builder
            .withUrl("/url/path")
            .param("key", "PARAM")
            .header("Host",
                    ModulesServiceFactory.getModulesService().getInstanceHostname("MODULE_NAME", "VERSION", "INSTANCE_NAME"));

我在当前版本的 App Engine 文档中找不到此信息,但使用 Wayback 机器我也从 earlier version of the doc from Jan 1 2016 which describes the Push task execution. It has been discussed in a different context in this github issue 中找到了此信息。

Push task execution

App Engine executes push tasks by sending HTTP POST requests to your app. Specifying a programmatic asynchronous callback as an HTTP request is sometimes called a web hook. The web hook model enables efficient parallel processing.

The task's URL determines the handler for the task and the module that runs the handler.

The handler is determined by the path part of the URL (the forward-slash separated string following the hostname), which is specified by the url parameter in the TaskOptions that you include in your call to the Queue.add() method. The url must be relative and local to your application's root directory.

The module and version in which the handler runs is determined by:

  • The "Host" header parameter in the TaskOptions that you include in your call to the Queue.add() method.
  • The target directive in the queue.xml or queue.yaml file.

If you do not specify any of these parameters, the task will run in the same module/version in which it was enqueued, subject to these rules:

  • If the default version of the app enqueues a task, the task will run on the default version. Note that if the app enqueues a task and the default version is changed before the task actually runs, the task will be executed in the new default version.

  • If a non-default version enqueues a task, the task will always run on that same version.

Note: If you are using modules along with a dispatch file, a task's URL may be intercepted and re-routed to another module.

The namespace in which a push task runs is determined when the task is added to the queue. By default, a task will run in the current namespace of the process that created the task. You can override this behavior by explicitly setting the namespace before adding a task to a queue, as described on the multitenancy page.