1. Introduction
Cloud Tasks is a fully managed queueing service for managing the execution, dispatch and delivery of a large number of tasks.
Cloud Tasks lets you separate out pieces of work, called tasks, that can be performed independently (eg. a task to update a database entry), outside of your main application flow, and send them off to be processed, asynchronously, using handlers that you create.
The offloaded task is added to a queue, which persists the task until it is successfully executed or gets a failure. Based on the configuration, the queue can also act as a dispatch flow control. You create and configure the queue which is then managed by the Cloud Tasks service. Once tasks are added, the queue dispatches the tasks and makes sure the workers reliably process them.
Some of the main features of Cloud Tasks are:
- HTTP targets: Add tasks targeting any HTTP service running on Compute Engine, Google Kubernetes Engine, Cloud Run, Cloud Functions or on-premises systems in a secure fashion using industry standard OAuth/OIDC authentication.
- Task deduplication: Tasks added multiple times will only be dispatched once.
- Guaranteed delivery: Tasks are guaranteed to be delivered at-least-once and most tasks are delivered exactly once.
- Rate and retry controls: Control the execution by setting the rate at which tasks are dispatched, the maximum number of attempts, and the minimum amount of time to wait between attempts.
- Future scheduling: Control the time at which a task is run.
In this codelab, you will first learn how to create and use a regular Cloud Tasks queue for HTTP target tasks. Then, you'll learn how to use queue-level HTTP URI override and the new BufferTask API to more easily buffer HTTP requests with Cloud Tasks.
What you'll learn
- How to create HTTP target tasks.
- How to create HTTP target tasks with the new queue-level HTTP URI override.
- How to change the pending tasks with the new queue-level HTTP URI override.
- How to more easily buffer HTTP requests with the new BufferTask API.
2. Setup and Requirements
Self-paced environment setup
- Sign-in to the Google Cloud Console and create a new project or reuse an existing one. If you don't already have a Gmail or Google Workspace account, you must create one.
- The Project name is the display name for this project's participants. It is a character string not used by Google APIs. You can always update it.
- The Project ID is unique across all Google Cloud projects and is immutable (cannot be changed after it has been set). The Cloud Console auto-generates a unique string; usually you don't care what it is. In most codelabs, you'll need to reference your Project ID (typically identified as
PROJECT_ID
). If you don't like the generated ID, you might generate another random one. Alternatively, you can try your own, and see if it's available. It can't be changed after this step and remains for the duration of the project. - For your information, there is a third value, a Project Number, which some APIs use. Learn more about all three of these values in the documentation.
- Next, you'll need to enable billing in the Cloud Console to use Cloud resources/APIs. Running through this codelab won't cost much, if anything at all. To shut down resources to avoid incurring billing beyond this tutorial, you can delete the resources you created or delete the project. New Google Cloud users are eligible for the $300 USD Free Trial program.
Start Cloud Shell
While Google Cloud can be operated remotely from your laptop, in this codelab you will be using Google Cloud Shell, a command line environment running in the Cloud.
From the Google Cloud Console, click the Cloud Shell icon on the top right toolbar:
It should only take a few moments to provision and connect to the environment. When it is finished, you should see something like this:
This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory, and runs on Google Cloud, greatly enhancing network performance and authentication. All of your work in this codelab can be done within a browser. You do not need to install anything.
3. Create a regular queue for HTTP target tasks
In this first step, you'll learn how to create a regular Cloud Tasks queue and add HTTP tasks to it to target a Cloud Run service.
What are HTTP target tasks?
HTTP target tasks can target any HTTP service running on Compute Engine, Google Kubernetes Engine, Cloud Run, Cloud Functions or on-premises systems in a secure fashion using industry standard OAuth/OIDC authentication.
Deploy a Cloud Run service
First, make sure the required APIs are enabled:
gcloud services enable \ cloudtasks.googleapis.com \ run.googleapis.com
Deploy a Cloud Run service which will serve as the target of the HTTP tasks:
SERVICE1=hello1 REGION=us-central1 gcloud run deploy $SERVICE1 \ --allow-unauthenticated \ --image=gcr.io/cloudrun/hello \ --region=$REGION
Create a Cloud Tasks queue
Create a regular Cloud Tasks queue:
QUEUE1=http-queue LOCATION=us-central1 gcloud tasks queues create $QUEUE1 --location=$LOCATION
Pause the queue temporarily, so you can observe HTTP tasks as they are created:
gcloud tasks queues pause $QUEUE1 --location=$LOCATION
4. Create and test an HTTP task
In this step, you will create an HTTP task to target the queue you created earlier.
Create an HTTP task
You can create HTTP tasks using gcloud
:
gcloud tasks create-http-task \ --queue=$QUEUE1 \ --location=$LOCATION \ --url=$SERVICE1_URL \ --method=GET
Optional: You can also create an HTTP task with client libraries. For example, you can check out the Program.cs
for a C# sample where an HTTP request is wrapped into a Task
and a TaskRequest
before being sent to Cloud Tasks with a CloudTasksClient
:
var taskRequest = new CreateTaskRequest { Parent = new QueueName(projectId, location, queue).ToString(), Task = new Task { HttpRequest = new HttpRequest { HttpMethod = HttpMethod.Get, Url = url } } }; var client = CloudTasksClient.Create(); var response = client.CreateTask(taskRequest);
You can run it as follows to create and add the task to the queue:
dotnet run $PROJECT_ID $LOCATION $QUEUE1 $SERVICE1_URL
Test the HTTP task
At this point, the task is created but it's not executed yet, as the queue is paused. You can verify this by listing the queues:
gcloud tasks queues list --location=$LOCATION
You should see the queue in PAUSED
state:
QUEUE_NAME STATE http-queue PAUSED
Resume the queue:
gcloud tasks queues resume $QUEUE --location=$LOCATION
Check the logs of the Cloud Run service:
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE1" --limit 1
You should see that the Cloud Run service received an HTTP GET request from Cloud Tasks:
httpRequest: latency: 0.227597158s protocol: HTTP/1.1 remoteIp: 35.243.23.192 requestMethod: GET requestSize: '415' requestUrl: https://hello1-idcwffc3yq-uc.a.run.app/ responseSize: '5510' serverIp: 216.239.32.53 status: 200 userAgent: Google-Cloud-Tasks
5. Create a queue with a routing configuration
In this step, you'll learn how to create a Cloud Tasks queue with a routing configuration to add an HTTP URI override using the Queue-level Task Routing Configuration feature. You'll then add HTTP tasks to it to target the first Cloud Run service and observe that the routing configuration overrides the URI to route tasks to the second Cloud Run service.
What is Queue-level Task Routing Configuration?
Queue-level Task Routing Configuration changes the HTTP task routing for the entire queue for all pending and new tasks. This allows easier creation of tasks as the HTTP target need not be set at the task level and it shifts more control to the service provider as they are able to set the target of all task in a queue (eg. route traffic to a different backend if the original backend is down).
The following configuration can be set at the queue-level:
- Headers: Queue-level headers when specified at the queue-level, will upsert headers for all tasks in the queue.
- HTTP Method: HTTP method when specified at the queue-level, will override the HTTP method for all tasks in the queue.
- Target URI: Host, path, query, port, scheme (HTTP or HTTPS) can be individually overridden.
- Authorization: OIDC/OAuth config when specified at the queue-level will override the task-level OIDC/OAuth config.
Deploy a second Cloud Run service
Deploy a second Cloud Run service which will serve as the target of the HTTP URI override later:
SERVICE2=hello2 REGION=us-central1 gcloud run deploy $SERVICE2 \ --allow-unauthenticated \ --image=gcr.io/cloudrun/hello \ --region=$REGION
Save the host of the service URL for later:
SERVICE2_URL=$(gcloud run services describe $SERVICE2 --region $REGION --format 'value(status.url)') SERVICE2_HOST=$(echo $SERVICE2_URL | sed 's,http[s]*://,,g')
Create a Cloud Tasks queue with a routing configuration
Create a queue with a routing configuration with HTTP URI override to the second Cloud Run service.
QUEUE2=http-queue-uri-override gcloud beta tasks queues create $QUEUE2 \ --http-uri-override=host:$SERVICE2_HOST \ --location=$LOCATION
Note that the URI override refers to the second Cloud Run service. Any HTTP task added to the queue will have its original URI host overridden. You can see the queue configuration:
gcloud beta tasks queues describe $QUEUE2 --location=$LOCATION
You should see that the httpTarget
has an uriOverride
pointing to the host of the second service:
httpTarget: uriOverride: host: hello2-idcwffc3yq-uc.a.run.app pathOverride: {} queryOverride: {} ...
Pause the queue temporarily, so you can observe HTTP tasks as they are created:
gcloud tasks queues pause $QUEUE2 --location=$LOCATION
6. Create and test an HTTP task for the queue with the routing configuration
In this step, you will create an HTTP task to target the first service and observe that its URI is overridden by the queue to point to the second service.
Create an HTTP task
Create an HTTP task with the first service's URL:
gcloud tasks create-http-task \ --queue=$QUEUE2 \ --location=$LOCATION \ --url=$SERVICE1_URL \ --method=GET
Test the HTTP task
Resume the queue:
gcloud tasks queues resume $QUEUE2 --location=$LOCATION
You should see that the second (not the first) Cloud Run service received an HTTP GET request from Cloud Tasks due to the override:
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE2" --limit 1
--- httpRequest: latency: 0.228982142s protocol: HTTP/1.1 remoteIp: 35.187.132.84 requestMethod: GET requestSize: '426' requestUrl: https://hello2-idcwffc3yq-uc.a.run.app/ responseSize: '5510' serverIp: 216.239.34.53 status: 200 userAgent: Google-Cloud-Tasks
7. Change the pending tasks with the routing configuration
You can also use the routing configuration to change the HTTP URI of all pending tasks in a queue. This is useful if the backend service goes down and you want to quickly route to another service. Let's see how this works in this step.
Pause the queue again:
gcloud tasks queues pause $QUEUE2 --location=$LOCATION
Create an HTTP task with google.com
as the task URL:
gcloud tasks create-http-task \ --queue=$QUEUE2 \ --location=$LOCATION \ --url=https://www.google.com \ --method=GET
The task is in pending state as the queue is paused.
Now, update the HTTP URI override to point to the first service. This will override the pending task's host from google.com
to the first service's host:
SERVICE1_URL=$(gcloud run services describe $SERVICE1 --region $REGION --format 'value(status.url)') SERVICE1_HOST=$(echo $SERVICE1_URL | sed 's,http[s]*://,,g') gcloud beta tasks queues update $QUEUE2 \ --http-uri-override=host:$SERVICE1_HOST \ --location=$LOCATION
Resume the queue:
gcloud tasks queues resume $QUEUE2 --location=$LOCATION
You should see that the first Cloud Run service received an HTTP GET request from Cloud Tasks due to the override (instead of google.com
):
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE1" --limit 1 --- httpRequest: latency: 0.228982142s protocol: HTTP/1.1 remoteIp: 35.187.132.84 requestMethod: GET requestSize: '426' requestUrl: https://hello1-idcwffc3yq-uc.a.run.app/ responseSize: '5510' serverIp: 216.239.34.53 status: 200 userAgent: Google-Cloud-Tasks
8. Create a queue for BufferTask API
Normally, you create tasks by using the Tasks API either from gcloud
or Tasks client libraries. This burdens the applications to wrap HTTP requests into Tasks using client libraries and it also creates a dependency between applications and the Tasks client libraries.
In this step, you'll see how to take advantage of the queue-level HTTP URI override and the new BufferTask API to create HTTP target tasks more easily by simply sending an HTTP request. Any application that can send HTTP requests can now create HTTP target tasks.
What is the BufferTask API?
The CreateTask API is the old way of creating Tasks and requires the client to send in a Task object to the API with all the required fields set.
BufferTask API is a new feature that allows the users to create an HTTP Task without the need to provide any Task Configuration (HTTP URL, headers, authorization), allowing you to simply send a message or the body of your request to the Buffer API.
This enables easier integration with services as Cloud Tasks can now be deployed in front of your service without needing any code changes on the client side. Any arbitrary HTTP request sent to the BufferTask API will be wrapped as a Task object and delivered to the destination set at the queue-level.
To use the BufferTask API, the queue needs to have the Target URI configuration set, or in other words, the Queue-level Routing Configuration feature is a prerequisite for using the BufferTask API.
Create a Cloud Tasks queue with routing configuration
Create a queue with a routing configuration pointing to the first service we deployed in the previous step:
SERVICE1=hello1 SERVICE1_URL=$(gcloud run services describe $SERVICE1 --region $REGION --format 'value(status.url)') SERVICE1_HOST=$(echo $SERVICE1_URL | sed 's,http[s]*://,,g') QUEUE3=http-queue-uri-override-buffer gcloud beta tasks queues create $QUEUE3 \ --http-uri-override=host:$SERVICE1_HOST \ --location=$LOCATION
Pause the queue temporarily, so you can observe HTTP tasks as they are created:
gcloud tasks queues pause $QUEUE3 --location=$LOCATION
9. Buffer HTTP requests with BufferTask API
In this step, you will buffer simple HTTP GET or POST requests with BufferTask API. Under the covers, Cloud Tasks will wrap these HTTP requests into HTTP tasks with the default routing configuration settings of the queue.
First, login to get an access token and set some variables:
gcloud auth application-default login ACCESS_TOKEN=$(gcloud auth application-default print-access-token) PROJECT_ID=$(gcloud config get-value project) TASKS_QUEUES_API="https://cloudtasks.googleapis.com/v2beta3/projects/$PROJECT_ID/locations/$LOCATION/queues"
Create an HTTP task
Create an HTTP task with BufferTask API. Notice how it's a simple a HTTP GET request without the need for creating a Task:
curl -X GET "$TASKS_QUEUES_API/$QUEUE3/tasks:buffer" \ -H "Authorization: Bearer $ACCESS_TOKEN"
Create another HTTP task with HTTP POST and a body:
curl -X POST "$TASKS_QUEUES_API/$QUEUE3/tasks:buffer" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d "{'message': 'Hello World'}"
Optional: You can also create an HTTP task with client libraries. For example, you can check out the Program.cs
for a C# sample where an HTTP GET request is sent directly to the BufferTask API without having to wrap it into a Task
or needing the client-library for Cloud Tasks:
var BufferTaskApiUrl = $"https://cloudtasks.googleapis.com/v2beta3/projects/{ProjectId}/locations/{Location}/queues/{Queue}/tasks:buffer"; using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", $"Bearer {AccessToken}"); var response = await client.GetAsync(BufferTaskApiUrl); var content = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Response: {content}"); }
You can run it as follows:
dotnet run $PROJECT_ID $LOCATION $QUEUE3 $ACCESS_TOKEN
BufferTask API takes care of creating a Task out of the HTTP requests and adds the URL from the queue's routing configuration settings for the URI.
Test the HTTP task
Resume the queue:
gcloud tasks queues resume $QUEUE3 --location=$LOCATION
You should see that the Cloud Run service received an HTTP GET and POST requests from Cloud Tasks:
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE1" --limit 4
--- httpRequest: latency: 0.002279292s protocol: HTTP/1.1 remoteIp: 35.243.23.42 requestMethod: POST requestSize: '777' requestUrl: https://hello1-idcwffc3yq-uc.a.run.app/ responseSize: '5450' serverIp: 216.239.32.53 status: 200 userAgent: Google-Cloud-Tasks ... httpRequest: latency: 0.228982142s protocol: HTTP/1.1 remoteIp: 35.187.132.84 requestMethod: GET requestSize: '426' requestUrl: https://hello1-idcwffc3yq-uc.a.run.app/ responseSize: '5510' serverIp: 216.239.34.53 status: 200 userAgent: Google-Cloud-Tasks
10. Congratulations
Congratulations, you finished the codelab!
As a follow up, you can try the Cloud Tasks as a buffer between Pub/Sub and Cloud Run to see a real-world example of how these new features of Cloud Tasks can help to easily create a buffer queue between services.
Cleanup (Optional)
To avoid incurring charges, it's a good idea to clean up resources.
If you don't need the project, you can simply delete the project:
gcloud projects delete $PROJECT_ID
If you need the project, you can delete resources individually.
Delete the Cloud Run services:
gcloud run services delete $SERVICE1 --region $REGION gcloud run services delete $SERVICE2 --region $REGION
Delete the Cloud Tasks queues:
gcloud tasks queues delete $QUEUE1 --location=$LOCATION gcloud tasks queues delete $QUEUE2 --location=$LOCATION gcloud tasks queues delete $QUEUE3 --location=$LOCATION
What we've covered
- How to create HTTP target tasks.
- How to create HTTP target tasks with the new queue-level HTTP URI override.
- How to change the pending tasks with the new queue-level HTTP URI override.
- How to more easily buffer HTTP requests with the new BufferTask API.