# Java Task Queue Configuration - Google App Engine - Google Code

English ▼
Skip to page content Skip to main navigation
e.g. "templates" or "datastore"

# Java Task Queue Configuration

Java applications define task queues in a configuration file called `queue.xml`. This file is stored in the application's `WEB-INF` directory. You can use `queue.xml` to configure both push queues and pull queues. This configuration file is optional for push queues, which have a default queue. Pull queues must be specifically configured in `queue.xml`.

- About Queues
- Setting the Storage Limit for All Queues
- Defining Push Queues and Processing Rates
- Defining Pull Queues
- Configuring Retry Attempts for Failed Tasks
- Queue Definitions
- Updating Task Queue Configuration

## About Queues

A Java app can define task queues using a file named `queue.xml`, in the app's `WEB-INF/` directory in the WAR. The file specifies an element named `queue`. Within this element, you can name any number of individual queues and define their processing rates. If no `queue.xml` file is provided, the app can still use the default queue returned by `QueueFactory.getDefaultQueue()`.

The app's queue configuration applies to all versions of the app. If a given version of an app enqueues a task, the queue uses the task handler for that version of the app. To control this behaviour see the target parameter.

An app can only add tasks to queues defined in `queue.xml` and the default queue. If you upload a new `queue.xml` file that removes a queue, but that queue still has tasks, the queue is "paused" (its rate is set to 0) but not deleted. You can re-enable the deleted queue by uploading a new `queue.xml` file with the queue defined.

## Setting the Storage Limit for All Queues

You can use `queue.xml` to define the total amount of storage that task data can consume over all queues. To define the total storage limit, include an element named `<total-storage-limit>` at the first level under `<queue-entries>`:

    <!--Change the total storage limit for all queues to 50MB-->
    <queue-entries>
      <total-storage-limit>50M</total-storage-limit>
      <queue>
        ...
      </queue>
    </queue-entries>

The value is a number followed by a unit: `B` for bytes, `K` for kilobytes, `M` for megabytes, `G` for gigabytes, `T` for terabytes. For example, `100K` specifies a limit of 100 kilobytes. If adding a task would cause the queue to exceed its storage limit, the call to add the task will fail. The default limit is `100M` (100 megabytes).

## Defining Push Queues and Processing Rates

You can define any number of individual queues by providing a queue `<name>`. You can control the rate at which tasks are processed in each queue by defining other directives, such as `<rate>`, `<bucket-size>`, and `<max-concurrent-requests>`. You can read more about these directives in the Queue Definitions section.

The task queue uses token buckets to control the rate of task execution. Each named queue has a token bucket that holds a certain number of tokens, defined by the `<bucket-size>` directive. Each time your application executes a task, it uses a token. Your app continues processing tasks in the queue until the queue's bucket runs out of tokens. App Engine refills the bucket with new tokens continuously based on the `<rate>` that you specified for the queue.

### Configuring the Default Queue

All apps have a push queue named `default`. This queue has a preset rate of 5 tasks per second, but you can change this rate by defining a default queue in `queue.xml`. If you do not configure a default queue in `queue.xml`, the `default` queue doesn't display in the Administration Console until the first time it is used. You can customize the settings for this queue by defining a queue named `default` in `queue.xml`:

    <queue-entries>
    <!--Change the refresh rate of the default queue to 1/s-->
      <queue>
        <name>default</name>
        <rate>1/s</rate>
      </queue>
    </queue-entries>

### Configuring the Processing Rate

If your queue contains tasks to process, and the queue's bucket contains tokens, App Engine processes as many tasks as there are tokens remaining in the bucket. This can lead to bursts of processing, consuming system resources and competing with user-serving requests. You can adjust the bucket size and rate based on your application's needs and available resources as follows:

    <queue-entries>
      <queue>
        <name>optimize-queue</name>
        <rate>20/s</rate>
        <bucket-size>40</bucket-size>
      </queue>
    <queue-entries>

### Configuring the Maximum Number of Concurrent Requests

You can further control the processing rate by setting `<max-concurrent-requests>`, which limits the number of tasks that can execute simultaneously.

If your application queue has a rate of 20/s and a bucket size of 40, tasks in that queue execute at a rate of 20/s and can burst up to 40/s briefly. These settings work fine if task latency is relatively low; however, if latency increases significantly, you'll end up processing significantly more concurrent tasks. This extra processing load can consume extra instances and slow down your application.

For example, let's assume that your normal task latency is 0.3 seconds. At this latency, you'll process at most around 40 tasks simultaneously. But if your task latency increases to 5 seconds, you could easily have over 100 tasks processing at once. This increase forces your application to consume more instances to process the extra tasks, potentially slowing down the entire application and interfering with user requests.

You can avoid this possibility by setting `<max-concurrent-requests>` to a lower value. For example, if you set `<max-concurrent-requests>` to 10, our example queue maintains about 20 tasks/second when latency is 0.3 seconds. However, when the latency increases over 0.5 seconds, this setting throttles the processing rate to ensure that no more than 10 tasks run simultaneously.

    <queue-entries>
    <!--Set the number of max concurrent requests to 10-->
      <queue>
        <name>optimize-queue</name>
        <rate>20/s</rate>
        <bucket-size>40</bucket-size>
        <max-concurrent-requests>10</max-concurrent-requests>
      </queue>
    </queue-entries>

## Defining Pull Queues

You can specify any named queue as a pull queue by adding the `<mode>pull</mode>` element to `queue.xml`. If you are using the Task Queue REST API, you also need to create an access control list (ACL) using the <acl> directive. This directive allows you to restrict access to user email addresses corresponding to an account hosted by Google. The following code snippet creates a pull queue named pull-queue with two users in the ACL:

    <queue-entries>
      <queue>
        <name>pull-queue</name>
        <mode>pull</mode>
        <acl>
          <user-email>bar@foo.com</user-email>
          <user-email>user@gmail.com</user-email>
        </acl>
      </queue>
    </queue-entries>

## Configuring Retry Attempts for Failed Tasks

Tasks executing in the task queue can fail for many reasons. If a task fails to execute (by returning any HTTP status code outside of the range 200-299), App Engine retries the task until it succeeds. By default, the system gradually reduces the retry rate to avoid flooding your application with too many requests, but schedules retry attempts to recur at a maximum of once per hour until the task succeeds.

Push queues and pull queues differ in how they retry tasks.

### Retrying Tasks in Push Queues

In push queues, you can specify your own scheme for task retries by adding the <retry-parameters> element in `queue.xml`. This addition allows you to specify the maximum number of times to retry failed tasks in a specific queue. You can also set a time limit for retry attempts and control the interval between attempts.

The following example demonstrates various retry scenarios:

- In `fooqueue`, tasks are retried at least seven times and for up to two days from the first execution attempt. After both limits are passed, it fails permanently.
- In `barqueue`, App Engine attempts to retry tasks, increasing the interval linearly between each retry until reaching the maximum backoff and retrying indefinitely at the maximum interval (so the intervals between requests are 10s, 20s, 30s, ..., 190s, 200s, 200s, ...).
- In `bazqueue`, the interval increases to twice the minimum backoff and retries indefinitely at the maximum interval (so the intervals between requests are 10s, 20s, 40s, 80s, 120s, 160s, 200s, 200s, ...).

    <queue-entries>
      <queue>
        <name>fooqueue</name>
        <rate>1/s</rate>
        <retry-parameters>
          <task-retry-limit>7</task-retry-limit>
          <task-age-limit>2</task-age-limit>
        </retry-parameters>
      </queue>
      <queue>
        <name>barqueue</name>
        <rate>1/s</rate>
        <retry-parameters>
          <min-backoff-seconds>10</min-backoff-seconds>
          <max-backoff-seconds>200</max-backoff-seconds>
          <max-doublings>0</max-doublings>
        </retry-parameters>
      </queue>
      <queue>
        <name>bazqueue</name>
        <rate>1/s</rate>
        <retry-parameters>
          <min-backoff-seconds>10</min-backoff-seconds>
          <max-backoff-seconds>200</max-backoff-seconds>
          <max-doublings>2</max-doublings>
        </retry-parameters>
      </queue>
    </queue-entries>

### Retrying Tasks in Pull Queues

In pull queues, you can specify the number of times to retry a task using the <retry-parameters> element with the <task-retry-limit> field. The system counts each time you lease a task using leaseTasks(). When the count exceeds the `<task-retry-limit>`, the system deletes the task automatically. If you don't specify a `<task-retry-limit>`, the system never deletes a task automatically.

The following code sample shows how to specify a pull queue limited to seven retry attempts:

    <queue-entries>
      <queue>
        <name>pull-queue</name>
        <mode>pull</mode>
        <retry-parameters>
          <task-retry-limit>7</task-retry-limit>
        </retry-parameters>
      </queue>
    </queue-entries>

## Queue Definitions

The `queue.xml` file is an XML file whose root element is `<queue-entries>`. This element contains zero or more `<queue>` elements, one for each named queue.

A `<queue>` element contains configuration for a queue. It can contain the following elements:

`<acl>`Experimental! (pull queues only)

  Creates an access control list (ACL) for Pull Queues using the Task Queue REST API. The ACL is composed of the specified email addresses. Accepts email addresses only from a Google Account. Enter each email address on its own line as follows `<user-email>user@gmail.com</user-email>`. For more information, please see Defining Pull Queues.

`<bucket-size>` (push queues only)

  Task queues use a "token bucket" algorithm for dequeueing tasks. The bucket size limits how fast the queue is processed when many tasks are in the queue and the rate is high. This allows you to have a high rate so processing starts shortly after a task is enqueued, but still limit resource usage when many tasks are enqueued in a short period of time.

  If no `<bucket-size>` is specified for a queue, the default value is 5.

  For more information on the algorithm, see the Wikipedia article on token buckets.

`<max-concurrent-requests>` (push queues only)

  Sets the maximum number of tasks that can be executed at any given time in the specified queue. The value is an integer. By default, this directive is unset and there is no limit on the maximum number of concurrent tasks.

  Restricting the maximum number of concurrent tasks gives you more control over your queue's rate of execution. In particular, you can explicitly control the number of clones that a queue consumes. Limiting the number of concurrent requests in a given queue allows you to make resources available for other queues or online processing.

`<mode>`

  Identifies the queue mode. This setting defaults to `push`, which identifies a queue as a push queue. If you wish to use pull queues, set the mode to `pull`.

`<name>`

  The name of the queue. This is the name you specify when you call `QueueFactory.getQueue()`.

  A queue name can contain letters, numbers, and hyphens.

`<rate>` (push queues only)

  How often tasks are processed on this queue. The value is a number followed by a slash and a unit of time, where the unit is `s` for seconds, `m` for minutes, `h` for hours, or `d` for days. For example, the value `5/m` says tasks will be processed at a rate of 5 times per minute.

  If the number is `0` (such as `0/s`), the queue is considered "paused," and no tasks are processed.

`<retry-parameters>`
  Configures retry attempts for failed tasks. This addition allows you to specify the maximum number of times to retry failed tasks in a specific queue. You can also set a time limit for retry attempts and control the interval between attempts.
  <task-retry-limit>
    The maximum number of retry attempts for a failed task. If specified with `task-age-limit`, App Engine retries the task until both limits are reached.
  <min-backoff-seconds> (push queues only)
    The minimum number of seconds to wait before retrying a task after it fails.
  <max-backoff-seconds> (push queues only)
    The maximum number of seconds to wait before retrying a task after it fails.
  <max-doublings> (push queues only)
    The maximum number of times that the interval between failed task retries will be doubled before the increase becomes constant. The constant is:
    2**(max-doublings - 1) * min-backoff-seconds.
  <task-age-limit> (push queues only)
    The time limit for retrying a failed task, in seconds, measured from the time the task was created. The value is a number followed by a unit of time, where the unit is `s` for seconds, `m` for minutes, `h` for hours, or `d` for days. For example, the value `5d` specifies a limit of five days after the task's first execution attempt. If specified with `task-retry-limit`, App Engine retries the task until both limits are reached.
`<target>` (push queues only)

  The version of your application on which the tasks in this queue will be invoked.

  If unspecified, then tasks are invoked on the same version of the application where they were enqueued. So, if you enqueued a task from the default application version without specifying a target on the queue, the task is invoked in the default application version.

## Updating Task Queue Configuration

The task queue configuration for the app is updated when you upload the application using `appcfg.sh update`. You can update just the configuration for an app's task queues without uploading the full application. To upload the `queue.xml` file, use the `appcfg.sh update_queues` command:

    ./appengine-java-sdk/bin/appcfg.sh update_queues myapp/war

See Uploading an and Managing a Java App for more information.