-
vs PubSub
- Cloud Tasks and Pub/Sub may be used to implement message passing and asynchronous integration
- The core difference between Pub/Sub and Cloud Tasks is the notion of implicit vs explicit invocation
- Pub/Sub aims to decouple publishers of events and subscribers to those events
- Publishers do not need to know anything about their subscribers
- Pub/Sub gives publishers no control over the delivery of the messages save for the guarantee of delivery
- Pub/Sub supports implicit invocation: a publisher implicitly causes the subscribers to execute by publishing an event
- Cloud Tasks is aimed at explicit invocation where the publisher retains full control of execution
- Publisher specifies an endpoint where each message is to be delivered
-
Cloud Tasks provides tools for queue and task management unavailable to Pub/Sub publishers
- Scheduling specific delivery times
- Delivery rate controls
- Configurable retries
- Access and management of individual tasks in a queue
- Task/message creation deduplication
-
vs Scheduler
- Cloud Tasks triggers actions based on how the individual task object is configured
- Cloud Scheduler triggers actions at regular fixed intervals
- Cloud Task initiates actions based on the amount of traffic coming through the queue
- Cloud Scheduler initiates actions on a fixed periodic schedule
- Each Cloud Task has a unique name, and can be identified and managed individually in the queue
- With exception of time of execution, each run of a Cloud Scheduler cron job is exactly the same as every other run of that cron job
- If the execution of a Cloud Task task fails, the task is re-tried until it succeeds
- If the execution of a Cloud Scheduler cron job fails, the failure is logged, and the job is not rerun until the next scheduled interval
-
Pitfalls
- With the exception of tasks scheduled to run in the future, task queues are completely agnostic about execution order
- There are no guarantees or best effort attempts made to execute tasks in any particular order
- There are no guarantees that old tasks will execute unless a queue is completely emptied
- A number of common cases exist where newer tasks are executed sooner than older tasks, and the patterns surrounding this can change without notice
- Cloud Tasks aims for a strict "execute exactly once" semantic
- In situations where a design trade-off must be made between guaranteed execution and duplicate execution, the service errs on the side of guaranteed execution
- A non-zero number of duplicate executions do occur
- Developers should take steps to ensure that duplicate execution is not a catastrophic event
- In production, more than 99.999% of tasks are executed only once
- The most common source of backlogs in immediate processing queues is exhausting resources on the target instances
- If a user is attempting to execute 100 tasks per second on frontend instances that can only process 10 requests per second, a backlog will build
- This typically manifests in one of two ways, either of which can generally be resolved by increasing the number of instances processing requests
- Servers that are being overloaded can start to return backoff errors in the form of HTTP response code 503
- Cloud Tasks will react to these errors by slowing down execution until errors stop
- This can be observed by looking at the "enforced rate" field in the Cloud Console
- Overloaded servers can also respond with large increases in latency
- Requests remain open for longer
- Because queues run with a maximum concurrent number of tasks, this can result in queues being unable to execute tasks at the expected rate
- Increasing the max_concurrent_tasks for the affected queues can help in situations where the value has been set too low, introducing an artificial rate limit
- Increasing max_concurrent_tasks is unlikely to relieve any underlying resource pressure
-
Security
- Restrict queue management methods to a small set of people or entities
- For large organizations, use a service account to run software that enforces proper queue configuration
- Separate users and other entities into Queue Admins, Cloud Task Workers and App Engine Deployer categories
- Queue Admins group have permission to call Cloud Tasks queue management methods, or to upload queue.yaml files
- Queue Admins group is restricted to a very small set of users so as to reduce the risk of clobbering queue configuration
- Cloud Tasks Workers group have permission to perform common interactions with Cloud Tasks such as enqueuing and dequeuing tasks
- Cloud Tasks Workers group are not allowed to call Cloud Tasks queue management methods
- App Engine Deployers for projects that have App Engine apps have permission to deploy the app
- They are not permitted to upload queue.yaml files or make any Cloud Tasks API calls, thus allowing the queue admins to enforce the proper policies
- Users who are queue admins should not also be Cloud Tasks workers, since that would defeat the purpose of the separation
- Small projects and organizations can assign Cloud IAM roles directly to users to place them into the groups above
- Large projects and organizations can use Service Accounts to separate duties and responsibilities
-
Queues
- Most standard App Engine apps use queue.yaml to configure queues in the App Engine Task Queue service
- For Java apps, the queue.xml file is used instead
- The Cloud Tasks API provides an App Engine-independent interface to the App Engine Task Queue service
- Cloud Tasks API provides the ability to manage queues, including doing so via the console or the gcloud command
- Queues that are created by Cloud Tasks API are accessible from the App Engine SDK and vice versa
- To maintain compatibility, it is possible to use the configuration file used by the App Engine SDK, queue.yaml, to create and configure queues used via the Cloud Tasks API
- It is strongly recommended to use either the configuration file method or the Cloud Tasks API to configure queues, but not both
- If new to Cloud Tasks or App Engine, use the Cloud Tasks API exclusively to manage queues and avoid the use of queue.yaml and queue.xml altogether
- Cloud Tasks queue management methods give users more choice in creating, updating and deleting queues
- Inspect project's Admin Activity audit logs to retrieve the history of queue configuration changes including queue creations, updates, and deletions.
- Resuming many high-QPS queues at the same time can lead to target overloading
-
Scaling
-
Queues or queue groups can become overloaded any time traffic increases suddenly and experience increased task creation latency, task creation error rate, and reduced dispatch rate
- To defend against this, establish controls in any situation where the create or dispatch rate of a queue or queue group can spike suddenly
- Google recommends a maximum of 500 operations per second to a cold queue or queue group, then increasing traffic by 50% every 5 minutes
- In theory, traffic can grow to 740K operations per second after 90 minutes using this ramp up schedule
- If tasks are created by an App Engine app, leverage App Engine traffic splitting to smooth traffic increases
- By splitting traffic between versions, requests that need to be rate-managed can be spun up over time to protect queue health
- When launching a release that significantly increases traffic to a queue or queue group, gradual rollout is, again, an important mechanism for smoothing the increases
- Gradually roll out instances such that the initial launch does not exceed 500 total operations to the new queues, increasing by no more than 50% every 5 minutes
-
Newly created queues are especially vulnerable
- Groups of queues, for example [queue0000, queue0001, …, queue0199], are just as sensitive as single queues during the initial rollout stages
- For these queues, gradual rollout is an important strategy.
- Launch new or updated services, which create high-TPS queues or queue groups, in stages such that initial load is below 500 TPS and increases of 50% or less are staged 5 minutes or more apart
- When increasing the total capacity of a queue group, for example expanding [queue0000-queue0199 to queue0000-queue0399], follow the 500/50/5 pattern.
- For rollout procedures, new queue groups behave no differently than individual queues
- Apply the 500/50/5 pattern to the new group as a whole, not just to individual queues within the group
- For queues group expansions, gradual rollout is an important strategy
- When migrating service to add tasks to the increased number of queues, gradually roll out instances such that the initial launch does not exceed 500 total operations to the new queues, increasing by no more than 50% every 5 minutes
- An existing queue group may be expanded because tasks are expected to be added to the queue group faster than the group can dispatch them
-
If the source of traffic is App Engine, use traffic splitting
- If the names of the new queues are spread out evenly among existing queue names when sorted lexicographically, then traffic can be sent immediately to those queues as long as there are no more than 50% new interleaved queues and the traffic to each queue is less than 500 TPS.
- This method is an alternative to using traffic splitting and gradual rollout.
-
When a large number of tasks, for example millions or billions, need to be added, a double-injection pattern can be useful
- Instead of creating tasks from a single job, use an injector queue
- Each task added to the injector queue fans out and adds 100 tasks to the desired queue or queue group
- The injector queue can be sped up over time, for example start at 5 TPS, then increase by 50% every 5 minutes
-
A name can be assigned to a task using the name parameter
- When a new task is created, Cloud Tasks assigns the task a unique name by default
- Name parameter introduces significant performance overhead, resulting in increased latencies and potentially increased error rates associated with named tasks
- These costs can be magnified significantly if tasks are named sequentially, such as with timestamps
- If assigning own names, use a well-distributed prefix for task names, such as a hash of the contents
-
Cloud Tasks can overload other services that such as App Engine, Datastore
- Network usage increases if dispatches from a queue increase dramatically in a short period of time
- If a backlog of tasks has accumulated, unpausing queues can potentially overload these services
- The recommended defense is the 500/50/5 pattern suggested for queue overload
- If a queue dispatches more than 500 TPS, increase traffic triggered by a queue by no more than 50% every 5 minutes
- Monitoring and logging metrics can be used to proactively monitor traffic increases
- Alerts can be used to detect potentially dangerous situations
-
Unpausing or resuming high-TPS queues
- When a queue or series of queues is unpaused or re-enabled, queues resume dispatches
- If the queue has many tasks, the newly-enabled queue’s dispatch rate could increase dramatically from 0 TPS to the full capacity of the queue
- To ramp up, stagger queue resumes or control the queue dispatch rates
-
Bulk scheduled tasks
- Large numbers of tasks, which are scheduled to dispatch at the same time, can also introduce a risk of target overloading
- To start a large number of tasks at once, consider using queue rate controls to increase the dispatch rate gradually or explicitly spinning up target capacity in advance
-
Increased fan-out
- When updating services that are executed through Cloud Tasks, increasing the number of remote calls can create production risks
- Use gradual rollout or traffic splitting to manage ramp up
-
Retries
- Code can retry on failure when making Cloud Tasks API calls
- When a significant proportion of requests are failing with server-side errors, a high rate of retries can overload queues even more and cause them to recover more slowly
- Google recommends capping the amount outgoing traffic if a client detects that a significant proportion of requests are failing with server-side errors