העברת תורי הודעות Push ל-Cloud Tasks‏ (Java)

בדף הזה מוסבר איך אפשר להעביר קוד של תור דחיפה (push queue) מ-Task Queues ל-Cloud Tasks. ‫Cloud Tasks היא הדרך המומלצת לעבודה עם תורים של הודעות Push ב-App Engine.

באמצעות Cloud Tasks, אתם ניגשים לאותו שירות שאליו אתם ניגשים באמצעות Task Queues RPC API. המשמעות היא שלא צריך ליצור מחדש את תורי ההודעות הקיימים ואת משימות ה-Push. עם זאת, כדי להשתמש ב-Cloud Tasks API, צריך להעביר קוד שיוצר תורים של הודעות בדחיפה או משימות בדחיפה, או קוד שמבצע אינטראקציה עם התורים או המשימות האלה.

אפשר ליצור תורים של משימות מסוג push ומשימות מסוג push ולבצע איתם אינטראקציה באמצעות ממשקי ה-API ל-REST ול-RPC של Cloud Tasks, ספריית הלקוח של Cloud Tasks, Google Cloud CLI ומסוףGoogle Cloud . בדף הזה מובאות דוגמאות לשימוש ב-gcloud CLI ובספריית הלקוח של Cloud Tasks.

ב-Cloud Tasks, כל התורים פועלים כתורי push. בהמשך המדריך הזה ובמסמכי Cloud Tasks, המונח תור זהה למונח תור דחיפה. באופן דומה, המונח משימה שווה ערך למונח משימת push.

תכונות שלא זמינות ב-Cloud Tasks

התכונות הבאות לא זמינות ב-Cloud Tasks:

  • הוספת משימות לתור בעסקאות ב-Datastore
  • שימוש בספריית המשימות שמושהות במקום בשירות worker
  • עבודה עם משימות באפליקציות לפי עקרון ה-Multi-tenancy
  • סימולציה באמצעות שרת הפיתוח המקומי
  • הוספת משימות באופן אסינכרוני

תמחור ומכסות

העברה של תורי הודעות בדחיפה ל-Cloud Tasks עשויה להשפיע על התמחור והמכסות של האפליקציה.

תמחור

ל-Cloud Tasks יש תמחור משלו. בדומה לתורי משימות, שליחת בקשות לאפליקציית App Engine עם משימה עלולה לגרום לאפליקציה לצבור עלויות.

מכסות

המכסות של Cloud Tasks שונות מהמכסות של תורי משימות. בדומה ל-Task Queues, שליחת בקשות לאפליקציית App Engine מ-Cloud Tasks עשויה להשפיע על מכסות הבקשות של App Engine.

לפני ההעברה

בקטעים הבאים מפורטים שלבי ההגדרה לפני העברת תורי ההודעות מסוג Push ל-Cloud Tasks.

העברת תורים להוצאת הודעות

לפני שמתחילים, צריך להעביר תורים של שליפת הודעות לפני שמבצעים את ההוראות במדריך הזה להעברת תורים של דחיפת הודעות. לא מומלץ להעביר תורי משיכה אחרי העברת תורי דחיפה, כי סביר להניח שהשימוש הנדרש בקובץ queue.yaml יגרום להתנהגות לא צפויה ב-Cloud Tasks.

הגנה על הגדרות התור

אחרי שמתחילים את תהליך ההעברה ל-Cloud Tasks, שינוי הקובץ queue.yaml עלול לגרום להתנהגות לא צפויה ולא מומלץ. כדי להגן על הגדרות התור מפני שינויים בקובץ queue.yaml, מבצעים את השלבים הבאים.

  1. מגדירים את ה-CLI של gcloud כך שקובץ queue.yaml לא ייכלל בהמשך הפריסות.

    מוסיפים את קובץ queue.yaml לקובץ .gcloudignore. כדי לבדוק אם כבר יש לכם קובץ .gcloudignore, אתם יכולים להריץ את הפקודה הבאה בטרמינל מהספרייה ברמה העליונה של האפליקציה. הפקודה הזו תציג את שם הקובץ אם הוא קיים.

    ls -a | grep .gcloudignore

    מידע נוסף על קובצי .gcloudignore זמין במאמר בנושא קובצי עזר של .gcloudignore.

  2. מגבילים את ההרשאות בקובץ queue.yaml.

    מומלץ לפעול לפי השיטות המומלצות שמתוארות במדריך שלנו בנושא הגדרת אבטחה לתור.

  3. מידע על Cloud Tasks ועל קובץ queue.yaml (אופציונלי).

    כשמשתמשים ב-Cloud Tasks API כדי לנהל את הגדרות התור, פריסה של קובץ queue.yaml מבטלת את ההגדרות שנקבעו על ידי Cloud Tasks, וזה עלול לגרום להתנהגות בלתי צפויה. מידע נוסף זמין במאמר שימוש בניהול תורים לעומת queue.yaml.

הפעלת Cloud Tasks API

כדי להפעיל את Cloud Tasks API, לוחצים על Enable ב-Cloud Tasks API ב-API Library. אם מופיע לחצן Manage (ניהול) במקום לחצן Enable (הפעלה), סימן שהפעלתם בעבר את Cloud Tasks API בפרויקט, ואין צורך להפעיל אותו שוב.

אימות האפליקציה ב-Cloud Tasks API

צריך לאמת את האפליקציה ב-Cloud Tasks API. בקטע הזה נדון באימות בשני תרחישים שונים לדוגמה.

כדי לפתח או לבדוק את האפליקציה באופן מקומי, מומלץ להשתמש בחשבון שירות. הוראות להגדרת חשבון שירות ולחיבור שלו לאפליקציה מופיעות במאמר קבלת פרטי כניסה לחשבון שירות וצירופם באופן ידני.

כדי לפרוס את האפליקציה ב-App Engine, לא צריך לספק אימות חדש. פרטי האימות של אפליקציות App Engine מוסקים מ-Application Default Credentials‏ (ADC).

הורדה של ה-CLI של gcloud

הורידו והתקינו את ה-CLI של gcloud כדי להשתמש בו עם Cloud Tasks API אם לא התקנתם אותו בעבר. אם ה-CLI של gcloud כבר מותקן, מריצים את הפקודה הבאה מהטרמינל.

gcloud components update

ייבוא ספריות לקוח של Cloud

כדי להשתמש בספריית הלקוח של Cloud Tasks באפליקציית App Engine:

  1. מציינים את התלות בספריית הלקוח של Cloud Tasks בקובץ pom.xml:

    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-tasks</artifactId>
      <version>1.3.0</version>
    </dependency>
  2. מייבאים את התלויות של ספריית הלקוח של Cloud Tasks בקבצים שאחראים ליצירה ולהוספה לתור של המשימות:

    import com.google.cloud.tasks.v2.AppEngineHttpRequest;
    import com.google.cloud.tasks.v2.CloudTasksClient;
    import com.google.cloud.tasks.v2.HttpMethod;
    import com.google.cloud.tasks.v2.QueueName;
    import com.google.cloud.tasks.v2.Task;

יצירה וניהול של תורים

בקטע הזה מוסבר איך ליצור ולנהל תורים באמצעות Cloud Tasks API.

ב-Cloud Tasks, לא משתמשים בקובץ queue.yaml כדי ליצור תורים או לנהל אותם. במקום זאת, משתמשים ב-Cloud Tasks API. לא מומלץ להשתמש גם בקובץ queue.yaml וגם ב-Cloud Tasks API, אבל יכול להיות שזה יהיה חלק בלתי נמנע מהמעבר מ-Task Queues ל-Cloud Tasks, בהתאם לאפליקציה שלכם. כדאי לקרוא את המאמר שימוש בניהול תורים לעומת queue.yaml כדי ללמוד על שיטות מומלצות.

יצירת תורים

כדאי לקרוא את הקטע הזה אם האפליקציה שלכם יוצרת תורים באופן פרוגרמטי, או אם אתם רוצים ליצור תורים נוספים משורת הפקודה.

ב-Cloud Tasks, שמות התורים הם בפורמט projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID. החלק LOCATION_ID בשם התור תואם ל Google Cloud אזור. החלק QUEUE_ID בשם התור שווה לשדה name של התור ב-Task Queues. שם התור נוצר במהלך יצירת התור על סמך הפרויקט, האזור וQUEUE_ID שאתם מציינים.

באופן כללי, המיקום של התור (כלומר, האזור) צריך להיות זהה לאזור של האפליקציה. יש שני חריגים לכלל הזה: אפליקציות שמשתמשות באזור europe-west ואפליקציות שמשתמשות באזור us-central. ב-Cloud Tasks, האזורים האלה נקראים europe-west1 ו-us-central1 בהתאמה.

אפשר להגדיר את התור במהלך היצירה שלו, אבל אפשר גם לעדכן אותו אחרי שהוא נוצר.

אין צורך ליצור מחדש תורים קיימים. במקום זאת, אפשר להעביר את הקוד שפועל באינטראקציה עם התורים הקיימים על ידי קריאת החלקים הרלוונטיים במדריך הזה.

שימוש חוזר בשמות של תורים

צריך להמתין 7 ימים אחרי מחיקת תור כדי ליצור תור עם אותו מזהה תור באותו פרויקט ובאותו מיקום (כלומר, באותו אזור).

בדוגמה הבאה נוצרות שתי תורים באמצעות Cloud Tasks. לתור הראשון יש מזהה תור queue-blue, והוא מוגדר לשליחת כל המשימות לגרסה v2 של השירות task-module בקצב של 5/s. לתור השני יש מזהה תור queue-red והוא משבץ משימות בקצב של 1/s. שניהם נוצרים בפרויקט עם מזהה הפרויקט your-project-id במיקום us-central1. זהו המקבילה ב-Cloud Tasks ליצירת תורים ב-Task Queues.

gcloud

ה-CLI של gcloud מסיק את הפרויקט והמיקום מההגדרה של ה-CLI של gcloud.

gcloud tasks queues create queue-blue \
--max-dispatches-per-second=5 \
--routing-override=service:task-module,version:v2
gcloud tasks queues create queue-red \
--max-dispatches-per-second=1

ספריית משתמש

import com.google.cloud.tasks.v2.AppEngineRouting;
import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.LocationName;
import com.google.cloud.tasks.v2.Queue;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.RateLimits;

public class CreateQueue {
  public static void createQueue(
      String projectId, String locationId, String queueBlueName, String queueRedName)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueBlueName = "queue-blue";
      // String queueRedName = "queue-red";

      LocationName parent = LocationName.of(projectId, locationId);

      Queue queueBlue =
          Queue.newBuilder()
              .setName(QueueName.of(projectId, locationId, queueBlueName).toString())
              .setRateLimits(RateLimits.newBuilder().setMaxDispatchesPerSecond(5.0))
              .setAppEngineRoutingOverride(
                  AppEngineRouting.newBuilder().setVersion("v2").setService("task-module"))
              .build();

      Queue queueRed =
          Queue.newBuilder()
              .setName(QueueName.of(projectId, locationId, queueRedName).toString())
              .setRateLimits(RateLimits.newBuilder().setMaxDispatchesPerSecond(1.0))
              .build();

      Queue[] queues = new Queue[] {queueBlue, queueRed};
      for (Queue queue : queues) {
        Queue response = client.createQueue(parent, queue);
        System.out.println(response);
      }
    }
  }
}

מידע נוסף זמין במאמר בנושא יצירת תור של Cloud Tasks.

הגדרת קצב העיבוד של התור

בטבלה הבאה מפורטים השדות ששונים בין Task Queues לבין Cloud Tasks.

השדה Task Queues (תורי משימות) שדה Cloud Tasks תיאור
rate max_dispatches_per_second הקצב המקסימלי שבו המערכת משייכת משימות מהתור
max_concurrent_requests max_concurrent_dispatches המספר המקסימלי של משימות בו-זמניות שאפשר לשלוח מהתור
bucket_size max_burst_size

‫Cloud Tasks מחשב מאפיין לקריאה בלבד max_burst_size שמגביל את מהירות העיבוד של משימות בתור על סמך הערך של max_dispatches_per_second. השדה הזה מאפשר לתור להגיע לקצב גבוה כדי שהעיבוד יתחיל זמן קצר אחרי שהמשימה נוספת לתור, אבל עדיין מגביל את השימוש במשאבים כשמתווספות לתור הרבה משימות בפרק זמן קצר.

בתורים של App Engine שנוצרו או עודכנו באמצעות קובץ queue.xml/yaml, הערך של max_burst_size שווה בהתחלה לערך של bucket_size. עם זאת, אם התור יועבר בהמשך לפקודה update באמצעות ממשק Cloud Tasks כלשהו, הערך של max_burst_size יתאפס על סמך הערך של max_dispatches_per_second, בלי קשר לעדכון של max_dispatches_per_second.

total_storage_limit הוצא משימוש ב-Cloud Tasks ב-Cloud Tasks אין תמיכה בהגדרת מגבלת אחסון מותאמת אישית

אפשר להגדיר את קצב העיבוד של התור כשיוצרים את התור או כשמעדכנים אותו בהמשך. בדוגמה הבאה נעשה שימוש ב-Cloud Tasks כדי להגדיר את קצב העיבוד בתור שנקרא queue-blue שכבר נוצר. אם queue-blue נוצר או הוגדר באמצעות קובץ queue.yaml, הדוגמה הבאה מאפסת את max_burst_size על סמך הערך max_dispatches_per_second של 20. זהו הערך המקביל ב-Cloud Tasks להגדרת קצב העיבוד של התור ב-Task Queues.

gcloud

gcloud tasks queues update queue-blue \
--max-dispatches-per-second=20 \
--max-concurrent-dispatches=10

ספריית משתמש

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.LocationName;
import com.google.cloud.tasks.v2.Queue;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.RateLimits;
import com.google.cloud.tasks.v2.UpdateQueueRequest;

public class UpdateQueue {
  public static void updateQueue(String projectId, String locationId, String queueId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "queue-blue";

      LocationName parent = LocationName.of(projectId, locationId);

      Queue queueBlue =
          Queue.newBuilder()
              .setName(QueueName.of(projectId, locationId, queueId).toString())
              .setRateLimits(
                  RateLimits.newBuilder()
                      .setMaxDispatchesPerSecond(20.0)
                      .setMaxConcurrentDispatches(10))
              .build();

      UpdateQueueRequest request = UpdateQueueRequest.newBuilder().setQueue(queueBlue).build();

      Queue response = client.updateQueue(request);
      System.out.println(response);
    }
  }
}

מידע נוסף זמין במאמר הגדרת מגבלות קצב.

השבתה והפעלה מחדש של תורים

ב-Cloud Tasks משתמשים במונח השהיה באותו אופן שבו משתמשים במונח השבתה ב-Task Queues. השהיה של תור מפסיקה את הביצוע של המשימות בתור עד להפעלה מחדש של התור. אבל אפשר להמשיך להוסיף משימות לתור שהושהה. ב-Cloud Tasks, המונח resume (המשך) משמש באותו אופן כמו ב-Task Queues.

בדוגמה הבאה מושהה תור עם מזהה התור queueName . הפעולה הזו מקבילה להשבתה של תורים ב-Task Queues.

gcloud

gcloud tasks queues pause 

queueName

ספריית משתמש

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.QueueName;

public class PauseQueue {
  public static void pauseQueue(String projectId, String locationId, String queueId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "foo";

      // Construct the fully qualified queue name.
      String queueName = QueueName.of(projectId, locationId, queueId).toString();

      client.pauseQueue(queueName);
      System.out.println("Queue Paused.");
    }
  }
}

מידע נוסף זמין במאמר בנושא Cloud Tasks בקטע השהיית תורים.

מחיקת תורים

אחרי שמוחקים תור, צריך לחכות 7 ימים לפני שיוצרים תור עם אותו שם. אם אתם לא יכולים לחכות 7 ימים, כדאי למחוק את כל המשימות מתור ההמתנה ולהגדיר מחדש את תור ההמתנה.

בדוגמה הבאה נמחקת התור עם מזהה התור foo . זהו המקבילה ב-Cloud Tasks למחיקת תורים ב-Task Queues.

gcloud

gcloud tasks queues delete 

foo

ספריית משתמש

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.QueueName;

public class DeleteQueue {
  public static void deleteQueue(String projectId, String locationId, String queueId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "foo";

      // Construct the fully qualified queue name.
      String queueName = QueueName.of(projectId, locationId, queueId).toString();

      client.deleteQueue(queueName);
      System.out.println("Queue Deleted.");
    }
  }
}

מידע נוסף זמין במאמר בנושא Cloud Tasks מחיקת תורים.

יצירה וניהול של משימות

בקטע הזה מוסבר איך ליצור משימות ולנהל אותן באמצעות Cloud Tasks API.

יצירת משימות

בטבלה הבאה מפורטים השדות ששונים בין Task Queues לבין Cloud Tasks.

השדה Task Queues (תורי משימות) שדה Cloud Tasks תיאור
מה חדש ב-Cloud Tasks app_engine_http_request יוצר בקשה שמיועדת לשירות App Engine. המשימות האלה נקראות משימות של App Engine.
method http_method מציינת את שיטת הבקשה, לדוגמה: POST
url relative_uri מציין את המטפל במשימה. שימו לב להבדל באות האחרונה: i עבור מזהה משאבים אחיד במקום l עבור מען משאבים אחיד
target app_engine_routing זה שינוי אופציונלי. מציינים את service, version ו-instance של App Engine למשימת App Engine. אם לא מגדירים את המאפיין, המערכת משתמשת בגרסת השירות, במופע ובשירות שמוגדרים כברירת מחדל.

בדוגמה הבאה נוצרת משימה שמופנית אל פונקציית ה-handler‏ /worker בשירות ברירת המחדל של App Engine. זהו המקבילה ב-Cloud Tasks ליצירת משימות בתורי משימות.

gcloud

gcloud tasks create-app-engine-task --queue=default \
--method=POST --relative-uri=/worker?key=key

ספריית משתמש

import com.google.cloud.tasks.v2.AppEngineHttpRequest;
import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.protobuf.ByteString;
import java.nio.charset.Charset;

public class CreateTask {
  public static void createTask(String projectId, String locationId, String queueId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "default";
      String key = "key";

      // Construct the fully qualified queue name.
      String queueName = QueueName.of(projectId, locationId, queueId).toString();

      // Construct the task body.
      Task taskParam =
          Task.newBuilder()
              .setAppEngineHttpRequest(
                  AppEngineHttpRequest.newBuilder()
                      .setRelativeUri("/worker?key=" + key)
                      .setHttpMethod(HttpMethod.GET)
                      .build())
              .build();

      Task taskPayload =
          Task.newBuilder()
              .setAppEngineHttpRequest(
                  AppEngineHttpRequest.newBuilder()
                      .setBody(ByteString.copyFrom(key, Charset.defaultCharset()))
                      .setRelativeUri("/worker")
                      .setHttpMethod(HttpMethod.POST)
                      .build())
              .build();

      // Send create task request.
      Task[] tasks = new Task[] {taskParam, taskPayload};
      for (Task task : tasks) {
        Task response = client.createTask(queueName, task);
        System.out.println(response);
      }
    }
  }
}

מידע נוסף זמין במאמר בנושא יצירת משימות App Engine במאמרי העזרה של Cloud Tasks.

ציון שירות היעד והניתוב

הגדרה של שירות היעד, הגרסה והמופע של App Engine למשימות של App Engine היא אופציונלית. כברירת מחדל, משימות ב-App Engine מנותבות לשירות, לגרסה ולמופע שמוגדרים כברירת מחדל בזמן הניסיון לבצע את המשימה.

במהלך יצירת המשימה, מגדירים את המאפיין app_engine_routing של המשימה כדי לציין שירות, גרסה או מופע אחרים של App Engine עבור המשימה.

כדי להפנות את כל המשימות בתור מסוים לאותו שירות, גרסה ומופע של App Engine, אפשר להגדיר את המאפיין app_engine_routing_override בתור.

מידע נוסף זמין במאמר בנושא Cloud Tasks הגדרת ניתוב.

העברת נתונים אל ה-handler

בדומה לתורי משימות, אפשר להעביר נתונים ל-handler בשתי דרכים באמצעות Cloud Tasks. אפשר להעביר נתונים כפרמטרים של שאילתה ב-URI היחסי, או להעביר נתונים בגוף הבקשה באמצעות שיטות HTTP‏ POST או PUT.

ב-Cloud Tasks, המונח body משמש באותו אופן שבו המונח payload משמש ב-Task Queues. ב-Cloud Tasks, סוג התוכן שמוגדר כברירת מחדל לגוף הבקשה הוא octet-stream ולא טקסט פשוט. אפשר להגדיר את סוג התוכן של גוף ההודעה על ידי ציון שלו בכותרת.

בדוגמה הבאה מועבר מפתח ל-handler‏ /worker בשתי דרכים שונות. זהו המקבילה ב-Cloud Tasks להעברת נתונים ל-handler ב-Task Queues.

console

gcloud tasks create-app-engine-task --queue=default --method=GET  \
--relative-uri=

/worker

?key=blue --routing=service:worker
gcloud tasks create-app-engine-task --queue=default --method=POST \
--relative-uri=

/worker

 --routing=service:worker \
--body-content="{'key': 'blue'}"

ספריית משתמש

import com.google.cloud.tasks.v2.AppEngineHttpRequest;
import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.protobuf.ByteString;
import java.nio.charset.Charset;

public class CreateTask {
  public static void createTask(String projectId, String locationId, String queueId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "default";
      String key = "key";

      // Construct the fully qualified queue name.
      String queueName = QueueName.of(projectId, locationId, queueId).toString();

      // Construct the task body.
      Task taskParam =
          Task.newBuilder()
              .setAppEngineHttpRequest(
                  AppEngineHttpRequest.newBuilder()
                      .setRelativeUri("/worker?key=" + key)
                      .setHttpMethod(HttpMethod.GET)
                      .build())
              .build();

      Task taskPayload =
          Task.newBuilder()
              .setAppEngineHttpRequest(
                  AppEngineHttpRequest.newBuilder()
                      .setBody(ByteString.copyFrom(key, Charset.defaultCharset()))
                      .setRelativeUri("/worker")
                      .setHttpMethod(HttpMethod.POST)
                      .build())
              .build();

      // Send create task request.
      Task[] tasks = new Task[] {taskParam, taskPayload};
      for (Task task : tasks) {
        Task response = client.createTask(queueName, task);
        System.out.println(response);
      }
    }
  }
}

מתן שמות למשימות

אפשר לציין את שם המשימה, אבל זה לא חובה. אם לא מציינים את שם המשימה, Cloud Tasks יוצר אותו בשבילכם על ידי יצירת מזהה משימה והסקת הפרויקט והמיקום (כלומר, האזור) על סמך התור שציינתם במהלך יצירת המשימה.

שמות המשימות הם בפורמט projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID/tasks/TASK_ID. החלק TASK_ID בשם המשימה שווה לשדה name של המשימה ב-Task Queues.

שימוש חוזר בשמות של משימות

צריך לחכות לפני שמשתמשים שוב בשם של משימה. משך הזמן שצריך להמתין לפני שמבצעים את הפעולה משתנה בהתאם לשאלה אם תור השליחה של המשימה נוצר ב-Cloud Tasks או ב-Task Queues.

לגבי משימות בתורים שנוצרו באמצעות Task Queues (כולל תור ברירת המחדל), צריך להמתין כ-9 ימים אחרי שהמשימה המקורית נמחקה או בוצעה. לגבי משימות בתורים שנוצרו באמצעות Cloud Tasks, צריך להמתין כשעה אחרי שהמשימה המקורית נמחקה או בוצעה.

בדוגמה הבאה נוצרת משימה עם הערך TASK_ID שמוגדר ל-first-try, והיא מתווספת לתור ברירת המחדל. זהו השם המקביל ב-Cloud Tasks לשם המשימה ב-Task Queues.

gcloud

ה-CLI של gcloud יוצר את שם המשימה על סמך הפרויקט והמיקום שמוגדרים בהגדרות.

gcloud tasks create-app-engine-task first-try --queue=default \
--method=GET --relative-uri=

/worker

ספריית משתמש

כשמשתמשים בספריית הלקוח, צריך לציין את השם המלא של המשימה אם רוצים לציין את TASK_ID. הפרויקט והמיקום צריכים להיות זהים לפרויקט ולמיקום של התור שאליו המשימה מתווספת.

import com.google.cloud.tasks.v2.AppEngineHttpRequest;
import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import com.google.cloud.tasks.v2.TaskName;

public class CreateTaskWithName {
  public static void createTaskWithName(
      String projectId, String locationId, String queueId, String taskId) throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "default";
      // String taskId = "first-try"

      String queueName = QueueName.of(projectId, locationId, queueId).toString();

      Task.Builder taskBuilder =
          Task.newBuilder()
              .setName(TaskName.of(projectId, locationId, queueId, taskId).toString())
              .setAppEngineHttpRequest(
                  AppEngineHttpRequest.newBuilder()
                      .setRelativeUri("/worker")
                      .setHttpMethod(HttpMethod.GET)
                      .build());

      // Send create task request.
      Task response = client.createTask(queueName, taskBuilder.build());
      System.out.println(response);
    }
  }
}

ניסיון חוזר של משימות שנכשלו

אפשר להגדיר את ההגדרה של ניסיון חוזר לביצוע משימה בתורים במהלך יצירת התור, או על ידי עדכון התור. בטבלה הבאה מפורטים השדות של Task Queues והשדות התואמים ב-Cloud Tasks.

השדה Task Queues (תורי משימות) שדה Cloud Tasks
task_retry_limit max_attempts
task_age_limit max_retry_duration
min_backoff_seconds min_backoff
max_backoff_seconds max_backoff
max_doublings max_doublings

פרמטרים של ניסיון חוזר ספציפי למשימה

פרמטרים ספציפיים של ניסיון חוזר למשימה שהוגדרו ב-Task Queues פועלים ב-Cloud Tasks, אבל אי אפשר לערוך אותם או להגדיר אותם במשימות חדשות. כדי לשנות את פרמטרים הניסיון החוזר של משימה שיש לה פרמטרים ספציפיים לניסיון חוזר, צריך ליצור מחדש את המשימה עם תור של Cloud Tasks שיש לו את פרמטרים הניסיון החוזר הרצויים.

בדוגמה הבאה מוצגים תרחישי ניסיון חוזר שונים:

  • ב-fooqueue, המערכת מנסה לבצע מחדש משימות עד שבע פעמים, למשך עד יומיים מניסיון ההפעלה הראשון. אחרי שמגיעים לשתי המגבלות, הפעולה נכשלת באופן סופי.
  • ב-barqueue,‏ App Engine מנסה לבצע מחדש משימות, ומגדיל את המרווח באופן לינארי בין כל ניסיון חוזר עד שמגיע להשהיה לפני ניסיון חוזר (backoff) המקסימלית, ואז מנסה שוב ללא הגבלה במרווח המקסימלי (כך שהמרווחים בין הבקשות הם 10 שניות, 20 שניות, 30 שניות וכו', עד 190 שניות, 200 שניות, 200 שניות וכו').
  • בדוגמה bazqueue, מרווח הזמן בין הניסיונות החוזרים מתחיל ב-10 שניות, מוכפל שלוש פעמים, ואז גדל באופן לינארי. לבסוף, המערכת מנסה שוב ושוב ללא הגבלה במרווח המקסימלי (כך שמרווחי הזמן בין הבקשות הם 10 שניות, 20 שניות, 40 שניות, 80 שניות, 160 שניות, 240 שניות, 300 שניות, 300 שניות וכן הלאה).

זהו המקבילה ב-Cloud Tasks לניסיון חוזר של משימות בתורי משימות.

gcloud

כשמגדירים אפשרויות שמציינות מספר שניות, צריך לכלול s אחרי המספר השלם (למשל 200s ולא 200).

gcloud tasks queues create fooqueue \
--max-attempts=7 \
--max-retry-duration=172800s  #2*60*60*24 seconds in 2 days
gcloud tasks queues create barqueue \
--min-backoff=10s \
--max-backoff=200s \
--max-doublings=0
gcloud tasks queues create bazqueue \
--min-backoff=10s \
--max-backoff=300s \
--max-doublings=3

ספריית משתמש

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.LocationName;
import com.google.cloud.tasks.v2.Queue;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.RateLimits;
import com.google.cloud.tasks.v2.RetryConfig;
import com.google.protobuf.Duration;

public class RetryTask {
  public static void retryTask(
      String projectId, String locationId, String fooqueue, String barqueue, String bazqueue)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String fooqueue = "fooqueue";
      // String barqueue = "barqueue";
      // String bazqueue = "bazqueue";

      LocationName parent = LocationName.of(projectId, locationId);

      Duration retryDuration = Duration.newBuilder().setSeconds(2 * 60 * 60 * 24).build();
      Duration min = Duration.newBuilder().setSeconds(10).build();
      Duration max1 = Duration.newBuilder().setSeconds(200).build();
      Duration max2 = Duration.newBuilder().setSeconds(300).build();

      Queue foo =
          Queue.newBuilder()
              .setName(QueueName.of(projectId, locationId, fooqueue).toString())
              .setRateLimits(RateLimits.newBuilder().setMaxDispatchesPerSecond(1.0))
              .setRetryConfig(
                  RetryConfig.newBuilder().setMaxAttempts(7).setMaxRetryDuration(retryDuration))
              .build();

      Queue bar =
          Queue.newBuilder()
              .setName(QueueName.of(projectId, locationId, barqueue).toString())
              .setRateLimits(RateLimits.newBuilder().setMaxDispatchesPerSecond(1.0))
              .setRetryConfig(
                  RetryConfig.newBuilder()
                      .setMinBackoff(min)
                      .setMaxBackoff(max1)
                      .setMaxDoublings(0))
              .build();

      Queue baz =
          Queue.newBuilder()
              .setName(QueueName.of(projectId, locationId, bazqueue).toString())
              .setRateLimits(RateLimits.newBuilder().setMaxDispatchesPerSecond(1.0))
              .setRetryConfig(
                  RetryConfig.newBuilder()
                      .setMinBackoff(min)
                      .setMaxBackoff(max2)
                      .setMaxDoublings(3))
              .build();

      Queue[] queues = new Queue[] {foo, bar, baz};
      for (Queue queue : queues) {
        Queue response = client.createQueue(parent, queue);
        System.out.println(response);
      }
    }
  }
}

מידע נוסף זמין במאמר בנושא Cloud Tasks הגדרת פרמטרים של ניסיון חוזר.

מחיקת משימות מתור

כשמוחקים משימה, צריך לחכות 9 ימים לפני שיוצרים משימה עם אותו שם אם המשימה הייתה בתור שנוצר באמצעות קובץ queue.yaml, או שעה אחת אם המשימה הייתה בתור שנוצר באמצעות Cloud Tasks.

בדוגמה הבאה נמחקת המשימה עם מזהה המשימה foo מהתור עם מזהה התור queue1. זהו המקבילה ב-Cloud Tasks למחיקת משימות בתורי משימות.

gcloud

הפרויקט והמיקום של המשימה נגזרים מפרויקט ברירת המחדל של ה-CLI של gcloud.

gcloud tasks delete foo --queue=queue1

ספריית משתמש

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.TaskName;

public class DeleteTask {
  public static void deleteTask(String projectId, String locationId, String queueId, String taskId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "queue1";
      // String taskId = "foo";

      // Construct the fully qualified queue name.
      String taskName = TaskName.of(projectId, locationId, queueId, taskId).toString();

      client.deleteTask(taskName);
      System.out.println("Task Deleted.");
    }
  }
}

מידע נוסף זמין במאמר בנושא Cloud Tasks מחיקת משימה מתור.

מחיקת משימות

בדוגמה הבאה, כל המשימות בתור עם מזהה התור foo נמחקות. זוהי הפעולה המקבילה ב-Cloud Tasks לניקוי משימות בתורי משימות.

gcloud

הפרויקט והמיקום של התור נגזרים מפרויקט ברירת המחדל של ה-CLI של gcloud.

gcloud tasks queues purge 

foo

ספריית משתמש

import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.QueueName;

public class PurgeQueue {
  public static void purgeQueue(String projectId, String locationId, String queueId)
      throws Exception {
    try (CloudTasksClient client = CloudTasksClient.create()) {
      // TODO(developer): Uncomment these lines and replace with your values.
      // String projectId = "your-project-id";
      // String locationId = "us-central1";
      // String queueId = "foo";

      // Construct the fully qualified queue name.
      String queueName = QueueName.of(projectId, locationId, queueId).toString();

      client.purgeQueue(queueName);
      System.out.println("Queue Purged.");
    }
  }
}

מידע נוסף זמין במאמר בנושא מחיקת כל המשימות מתור בתיעוד של Cloud Tasks.

דוגמה ל-Cloud Tasks ב-Java 8

בדוגמה הבאה מוצג תהליך הגדרה בסיסי ליצירת תור ולהוספת משימה לתור באמצעות Cloud Tasks. ההנחה היא שהמפתח יצר קובץ pom.xml כדי לציין את התלות ב-Cloud Tasks, כפי שמתואר בקטע ייבוא ספריית הלקוח. זוהי דוגמה לתור משימות ב-Task Queues ששווה ערך ל-Cloud Tasks ב-Java 8.

הקובץ שאחראי ליצירת המשימה ולהוספה שלה לתור יוצר משימה ומוסיף אותה לתור ברירת המחדל באמצעות ספריית הלקוח של Cloud Tasks:

import com.google.cloud.tasks.v2.AppEngineHttpRequest;
import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.cloud.tasks.v2.QueueName;
import com.google.cloud.tasks.v2.Task;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
    name = "TaskEnqueue",
    description = "Enqueue a task targeted at endpoint '/cloudtasks/worker'",
    urlPatterns = "/cloudtasks/enqueue")
public class Enqueue extends HttpServlet {

  // TODO(developer): Replace these variables before running the sample.
  static final String projectId = "my-project-id";
  static final String locationId = "us-central1";

  // Function creates Cloud Tasks from form submissions.
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String key = request.getParameter("key");

    try (CloudTasksClient client = CloudTasksClient.create()) {
      // Construct the fully qualified queue name.
      String queueName = QueueName.of(projectId, locationId, "default").toString();

      // Construct the task body.
      Task task =
          Task.newBuilder()
              .setAppEngineHttpRequest(
                  AppEngineHttpRequest.newBuilder()
                      .setRelativeUri("/cloudtasks/worker?key=" + key)
                      .setHttpMethod(HttpMethod.POST)
                      .build())
              .build();

      // Add the task to the default queue.
      Task taskResponse = client.createTask(queueName, task);
      System.out.println("Task created: " + taskResponse.getName());
    }

    response.sendRedirect("/");
  }
}

הקובץ שמגדיר את העובד מטפל במשימה:

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
    name = "TaskWorker",
    description = "Endpoint to process Cloud Task requests",
    urlPatterns = "/cloudtasks/worker"
)
public class Worker extends HttpServlet {

  private static final Logger log = Logger.getLogger(Worker.class.getName());

  // Worker function to process POST requests from Cloud Tasks targeted at the
  // '/cloudtasks/worker' endpoint.
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String key = request.getParameter("key");
    log.info("Worker is processing " + key);
  }
}

המאמרים הבאים