פסק זמן ומועדים

במאמר הזה מוסבר איך להגדיר את הגדרות הזמן הקצוב לתפוגה והמועד האחרון לבקשות של Route Optimization API. הגדרת הערכים האלה בצורה לא נכונה או אי-הגדרתם עלולה לגרום לבעיות בחיבור או באיכות התגובה.

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

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

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

הערה: הפרמטרים של הזמן הקצוב לתפוגה ושל תאריך היעד חלים רק אם הערך של solvingMode הוא ערך ברירת המחדל DEFAULT_SOLVE. אפשרויות אחרות של solvingMode, כמו VALIDATE_ONLY, DETECT_SOME_INFEASIBLE_SHIPMENTS או TRANSFORM_AND_RETURN_REQUEST, בדרך כלל לא דורשות התאמות של זמן קצוב לתפוגה כי הן מהירות משמעותית.

הסבר על הצורך בהגדרת פסק זמן ותאריך יעד

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

ההנחיות הבאות יעזרו לכם לוודא שאתם משתמשים בהגדרה הנכונה להשגת היעדים שלכם.

  • כדאי להשתמש בנקודות קצה (endpoint) לא חוסמות לבקשות חוזרות ונשנות ולבקשות מורכבות שדורשות זמן פתרון ארוך יותר.
  • מומלץ להשתמש בנקודות קצה חוסמות לבקשות קטנות ולמסירת תוצאות מהירה, תוך התפשרות על איכות התוצאות.
  • מומלץ להשתמש ב-gRPC: בתהליך העבודה היומיומי, במיוחד באפליקציות בסביבת ייצור.
  • משתמשים ב-REST לבדיקות, לניסויים או לבקשות חד-פעמיות.

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

פתיחת התרשים בכרטיסייה נפרדת

הגדרת הפרמטר timeout

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

מגדירים את הפרמטר timeout באמצעות פרוטוקול משך הזמן buffer, שהוא משך זמן בשניות שיכול להיות בין שנייה אחת ל-1,800 שניות. אפשר להגדיל את הערך הזה עד 3,600 שניות באמצעות allowLargeDeadlineDespiteInterruptionRisk.

בטבלה הבאה מפורטים ערכים מומלצים של timeout על סמך מורכבות הבקשה ומספר המשלוחים וכלי הרכב.

מספר המשלוחים וכלי הרכב ללא אילוצים חלונות זמן רחבים ומגבלות טעינה או מסלולים ארוכים חלונות זמן קצרים, מגבלות על עומס, מגבלות מורכבות או מסלולים ארוכים מאוד
1 - 8 ‫2s ‫2s ‫5 שניות
‫9 עד 32 ‫5 שניות 10 שנ' 20 שנ'
‫33-100 15 שנ' ‎30ש 60 שנ'
‫101 עד 1,000 ‫45 שניות שנות ה-90 180s
‫1,001 עד 10,000 ‫120 שניות ‫360s 900s
‫10,001 או יותר ‫60 שניות + 120 שניות לכל 10,000 משלוחים סביבות 360 לכל 10,000 משלוחים ‫900s לכל 10,000 משלוחים

הגדרת תאריך היעד

מגדירים את תאריך היעד בכותרת הבקשה כדי להגדיר את הזמן המקסימלי שבו Route Optimization API מעבד בקשה. בקטעי המשנה הבאים מוסבר איך להגדיר מועדים לבקשות REST ו-gRPC.

בקשות REST

כשמשתמשים ב-REST כדי לקרוא לנקודת קצה חוסמת, אפשר להאריך את מועד היעד מעבר לערך ברירת המחדל של 60 שניות, שלרוב קצר מדי לבקשות מורכבות. חובה לעשות את זה גם אם כבר ציינתם מועד אחרון ארוך יותר בגוף הבקשה, כי מועד ברירת המחדל מבטל כל ערך של timeout שמוגדר בגוף הבקשה וארוך מ-60 שניות.

כדי להאריך את המועד האחרון מעבר ל-60 השניות שמוגדרות כברירת מחדל, צריך להגדיר את כותרת הבקשה X-Server-Timeout. שלא כמו בגוף הבקשה, הערך של הכותרת הוא מספר השניות, אבל בלי הסיומת s. הערך המקסימלי שאפשר להגדיר לכותרת הזו תואם למגבלות של הפרמטר timeout.

בדוגמת הקוד הבאה מוצגת כותרת HTTP עם הערך X-Server-Timeout שמוגדר ל-1,800 שניות.

curl -X POST 'https://routeoptimization.googleapis.com/v1/projects/:optimizeTours' \
-H "Content-Type: application/json" \
-H "X-Server-Timeout: 1800" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
--data @- << EOM
{
  "model": {
    ...
  }
}
EOM

ספריות לקוח ובקשות gRPC

כשמשתמשים בספריות לקוח או ב-gRPC, לא צריך להגדיר מועד אחרון. המועד האחרון שמוגדר כברירת מחדל כשמשתמשים בהם הוא 3,600 שניות, שהוא זמן הבקשה המקסימלי ל-API הזה. כדי להגדיר את זמן הפתרון, צריך להגדיר רק את מאפיין הזמן הקצוב לתפוגה בגוף הבקשה.

פרמטרים שמשפיעים על פסק זמן ועל מועדי סיום

הפרמטרים הבאים משפיעים על הפעולה של פסק זמן ושל מועד אחרון:

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

allowLargeDeadlineDespiteInterruptionRisk

הפרמטר allowLargeDeadlineDespiteInterruptionRisk מגדיל את המועד האחרון המקסימלי לשליחת בקשה ל-3,600 שניות. אם הפרמטר הזה לא מוגדר, הערך המקסימלי של הפרמטרים timeout ו-deadline הוא 1,800 שניות.

מגדירים את allowLargeDeadline DespiteInterruptionRisk ל-true כדי להגדיל את הערך של הפרמטרים של הזמן הקצוב לתפוגה ושל תאריך היעד ל-3,600 שניות.

הערכים המותרים למאפיין allowLargeDeadline DespiteInterruptionRisk הם:

  • true: מגדיל את הערך המקסימלי של פרמטרים של זמן קצוב לתפוגה ומועד אחרון ל-3,600 שניות, תוך הכרה בסיכון להפרעה.
  • false (ברירת מחדל): שומר על הערך המקסימלי של פרמטרים של זמן קצוב לתפוגה ומועד אחרון של 1,800 שניות.

אם לדעתכם אתם צריכים פסק זמן ארוך יותר מ-3,600 שניות, פנו לנציג שלכם ב-Google.

searchMode

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

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

הערכים המותרים של searchMode הם:

  • SEARCH_MODE_UNSPECIFIED (ברירת מחדל): מצב חיפוש לא מוגדר, ששווה ל-RETURN_FAST.
  • RETURN_FAST: מפסיק את החיפוש אחרי שנמצא הפתרון הטוב הראשון.
  • CONSUME_ALL_AVAILABLE_TIME: המערכת משקיעה את כל הזמן שזמין לה בחיפוש פתרונות טובים יותר. אם ה-API מוצא פתרון אופטימלי בשלב מוקדם, הוא לא משתמש בכל הזמן שזמין לו.

הפעלת פינגים של keepalive

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

מגדירים את הפרמטרים האלה בהתאם לפרוטוקול ה-API שבו משתמשים:

  • REST: הגדרת keepalive ברמת חיבור ה-TCP.
  • gRPC: מגדירים פינגים של keepalive בשקע ה-TCP הבסיסי או ישירות בפרוטוקול gRPC.

בקטעים הבאים מוסבר איך להגדיר פינגים של keepalive בשני הפרוטוקולים.

הודעת keep-alive של REST

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

אם הספרייה חושפת את שקע ה-TCP הבסיסי, אפשר להגדיר פינגים של keepalive ישירות בשקע ה-TCP באמצעות אפשרויות כמו SO_KEEPALIVE. כדי לעשות את זה, משתמשים בפונקציות כמו setsockopt() או בפונקציות מקבילות.

הפונקציה הזו שמתארחת ב-GitHub מדגימה איך להגדיר את זה בצורה נכונה עבור לקוח HTTP מובנה של Python.

פרטים נוספים על הודעות keep-alive ברמת TCP זמינים בסקירה הכללית של TLDP keepalive או במסמכי התיעוד של ספריית הלקוח של HTTP.

הודעת keep-alive ב-gRPC

פרוטוקול gRPC מציע מנגנון מובנה משלו לשמירת החיבור כחלק מהפרוטוקול. הוראות להגדרה בשפת הלקוח מופיעות במדריך בנושא שמירת חיבור פעיל ב-gRPC.

הערה: שרתי gRPC עשויים לדחות לקוחות ששולחים יותר מדי פינגים. מומלץ להימנע מהגדרת תדירות גבוהה מדי של פינג keepalive.

בקשת gRPC לדוגמה עם keepalive

בדוגמה הבאה מוצגת בקשת optimizeTours באמצעות ספריית הלקוח של Python ופינגים של שמירת חיבור ברמת gRPC.

from google.maps import routeoptimization_v1 as ro
from google.maps.routeoptimization_v1.services.route_optimization.transports import grpc as grpc_transport
import sys

_REQUEST_TIMEOUT_SECONDS = 1800
_KEEPALIVE_PING_SECONDS = 30

def create_channel(*args, **kwargs):
  raw_options = kwargs.pop("options", ())
  options = dict(raw_options)
  options["grpc.keepalive_time_ms"] = _KEEPALIVE_PING_SECONDS * 1000
  options["grpc.keepalive_timeout_ms"] = 5000
  # Allow any number of pings between the request and the response.
  options["grpc.http2.max_pings_without_data"] = 0
  print(f"Using options: {options}", file=sys.stderr)
  return grpc_transport.RouteOptimizationGrpcTransport.create_channel(
      *args,
      options=list(options.items()),
      **kwargs,
  )

def create_grpc_transport(*args, **kwargs):
  if "channel" in kwargs:
    raise ValueError(
        "`channel` is overridden by this function, and must not be provided."
    )
  return grpc_transport.RouteOptimizationGrpcTransport(
      *args,
      channel=create_channel,
      **kwargs,
  )

def run_optimize_tours(request):
  client = ro.RouteOptimizationClient(transport=create_grpc_transport)
  return client.optimize_tours(request, timeout=_REQUEST_TIMEOUT_SECONDS)