שיטות מומלצות לשימוש בשירותי האינטרנט של Geolocation API

שירותי האינטרנט של פלטפורמת מפות Google הם אוסף של ממשקי HTTP לשירותי Google שמספקים נתונים גיאוגרפיים לאפליקציות המפות שלכם.

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

מהו שירות אינטרנט?

שירותי האינטרנט של הפלטפורמה של מפות Google הם ממשק לבקשת נתונים מ-Maps API משירותים חיצוניים ולהשתמש בנתונים באפליקציות של מפות Google. השירותים האלה מיועדים לשימוש בשילוב עם מפה, בהתאם להגבלות הרישיון שמפורטות בתנאים ובהגבלות של פלטפורמת מפות Google.

שירותי האינטרנט של Maps API משתמשים בבקשות HTTP(S) לכתובות URL ספציפיות, ומעבירים לשירותים פרמטרים של כתובות URL ו/או נתוני POST בפורמט JSON כארגומנטים. בדרך כלל, השירותים האלה מחזירים נתונים בגוף התגובה כ-JSON לניתוח ו/או לעיבוד על ידי האפליקציה.

בקשות למיקום גיאוגרפי נשלחות באמצעות POST לכתובת ה-URL הבאה:

https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR_API_KEY

הערה: כל האפליקציות של Geolocation API מחייבות אימות. מידע נוסף על פרטי כניסה לאימות

גישה ל-SSL/TLS

צריך להשתמש ב-HTTPS בכל הבקשות לפלטפורמה של מפות Google שמשתמשות במפתחות API או מכילות נתוני משתמשים. יכול להיות שנדחה בקשות שנשלחות ב-HTTP ומכילות מידע אישי רגיש.

שימוש מנומס ב-Google APIs

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

השהיה מעריכית לפני ניסיון חוזר (exponential backoff)

במקרים נדירים, יכול להיות משהו השתבש בטיפול בבקשה. יכול להיות שתקבלו קוד תגובה HTTP‏ 4XX או 5XX, או שפשוט החיבור ל-TCP נכשל במקום כלשהו בין הלקוח שלכם לשרת של Google. לרוב כדאי לנסות שוב את הבקשה, כי ייתכן שהבקשה הבאה תצליח אם הבקשה המקורית נכשלה. עם זאת, חשוב לא לשלוח בקשות שוב ושוב לשרתים של Google. התנהגות הלולאה הזו עלולה לגרום לעומס ברשת בין הלקוח ל-Google, וכתוצאה מכך לבעיות אצל גורמים רבים.

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

לדוגמה, נניח שאפליקציה רוצה לשלוח את הבקשה הבאה ל-Time Zone API:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

בדוגמה הבאה ב-Python מוסבר איך לשלוח את הבקשה עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff):

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined below isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

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

בקשות מסונכרנות

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

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

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

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

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

עיבוד התשובות

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

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

תוכנית הניתוח שבה משתמשים תלויה בפורמט הפלט: JSON או לא. תגובות JSON, שכבר נמצאות בפורמט של אובייקטים של JavaScript, יכולות לעבור עיבוד ב-JavaScript עצמו בצד הלקוח.