แนวทางปฏิบัติแนะนําโดยใช้ Roads API Web Services

บริการบนเว็บของ Google Maps Platform คือคอลเล็กชันอินเทอร์เฟซ HTTP ไปยังบริการของ Google ซึ่งให้ข้อมูลทางภูมิศาสตร์สําหรับแอปพลิเคชันแผนที่ของคุณ

คู่มือนี้จะอธิบายหลักปฏิบัติทั่วไปที่มีประโยชน์สําหรับการตั้งค่าคําขอเว็บ และดําเนินการกับการตอบกลับของบริการ อ่านคู่มือสําหรับนักพัฒนาซอฟต์แวร์เพื่อดูเอกสารฉบับเต็มของ Roads API

บริการเว็บคืออะไร

บริการบนเว็บของ Google Maps Platform เป็นอินเทอร์เฟซสําหรับขอข้อมูล Maps API จากบริการภายนอก และใช้ข้อมูลภายในแอปพลิเคชัน Maps บริการเหล่านี้ได้รับการออกแบบให้ใช้ร่วมกับแผนที่ตามข้อจํากัดสัญญาอนุญาตในข้อกําหนดในการให้บริการของ Google Maps Platform

บริการเว็บ Maps API ใช้คําขอ HTTP(S) ไปยัง URL ที่เฉพาะเจาะจง ส่งพารามิเตอร์ URL และ/หรือข้อมูล POST ในรูปแบบ JSON เป็นอาร์กิวเมนต์ให้กับบริการ โดยทั่วไป บริการเหล่านี้จะส่งคืนข้อมูลในส่วนเนื้อหาของการตอบกลับเป็น JSON สําหรับการแยกวิเคราะห์และ/หรือประมวลผลโดยแอปพลิเคชันของคุณ

โดยทั่วไปแล้ว คําขอบริการถนน Roads API มักอยู่ในรูปแบบต่อไปนี้

https://roads.googleapis.com/v1/snapToRoads?parameters&key=YOUR_API_KEY

โดยที่ snapToRoads หมายถึงบริการที่ต้องการ บริการอื่นๆ ของถนน ได้แก่ nearestRoads และ speedLimits

หมายเหตุ: แอปพลิเคชัน Roads API ทั้งหมดจะต้องมีการตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลเข้าสู่ระบบการตรวจสอบสิทธิ์

การเข้าถึง SSL/TLS

ต้องใช้ HTTPS สําหรับคําขอ Google Maps Platform ทั้งหมดที่ใช้คีย์ API หรือมีข้อมูลผู้ใช้ คําขอที่ส่งผ่าน HTTP ซึ่งมีข้อมูลที่ละเอียดอ่อนอาจถูกปฏิเสธ

การสร้าง URL ที่ถูกต้อง

คุณอาจคิดว่า URL ที่ "ถูกต้อง" จะชัดเจนในตัวเอง แต่ก็ไม่ใช่อย่างนั้น ตัวอย่างเช่น URL ที่ป้อนลงในแถบที่อยู่ในเบราว์เซอร์อาจมีสัญลักษณ์พิเศษ (เช่น "上海+中國") เบราว์เซอร์จะต้องแปลอักขระเหล่านั้นเป็นการเข้ารหัสก่อนการส่ง โทเค็นเดียวกันที่สร้างหรือยอมรับอินพุต UTF-8 อาจถือว่า URL ที่มีอักขระ UTF-8 เป็น "valid" แต่อาจต้องแปลอักขระเหล่านั้นก่อนที่จะส่งไปยังเว็บเซิร์ฟเวอร์ กระบวนการนี้เรียกว่า การเข้ารหัส URL หรือการเข้ารหัสเปอร์เซ็นต์

สัญลักษณ์พิเศษ

เราต้องแปลสัญลักษณ์พิเศษเนื่องจาก URL ทั้งหมดต้องสอดคล้องกับไวยากรณ์ที่ระบุโดยข้อกําหนด Uniform Resource Identifier (URI) ซึ่งหมายความว่า URL จะมีเฉพาะชุดย่อยของอักขระ ASCII พิเศษเท่านั้น ได้แก่ สัญลักษณ์ที่เป็นตัวอักษรและตัวเลขคละกันที่คุณคุ้นเคย และอักขระที่สงวนไว้บางส่วนเพื่อใช้เป็นอักขระควบคุมภายใน URL ตารางนี้จะสรุปอักขระเหล่านี้:

สรุปอักขระของ URL ที่ถูกต้อง
ตั้งค่าอักขระการใช้ URL
ตัวอักษรและตัวเลขคละกัน ก า ร รั บ ข้ อ มู ล แ ล้ ว สตริงข้อความ การใช้สคีม (http), พอร์ต (8080) ฯลฯ
ไม่ได้จอง - _ ~ สตริงข้อความ
จองแล้ว ! * ' ( ) ; : @ & = + $ , / ? % # [ ] ควบคุมอักขระและ/หรือสตริงข้อความ

เมื่อสร้าง URL ที่ถูกต้อง คุณต้องตรวจสอบว่า URL ดังกล่าวมีเฉพาะอักขระเหล่านั้นซึ่งแสดงอยู่ในตารางอักขระ URL ที่ถูกต้อง โดยทั่วไปแล้ว การทําตาม URL เพื่อใช้อักขระชุดนี้จะทําให้เกิดปัญหา 2 อย่าง ได้แก่ การละเว้นบางส่วนและการแทนที่ 1 อย่าง

  • มีอักขระที่คุณต้องการจัดการอยู่นอกชุดด้านบน ตัวอย่างเช่น ต้องเข้ารหัสอักขระภาษาต่างประเทศโดยใช้ 上海+中國 โดยใช้อักขระข้างต้น ตามรูปแบบที่ได้รับความนิยม การเว้นวรรค (ซึ่งไม่อนุญาตให้ใช้ภายใน URL) มักจะแสดงด้วยอักขระบวก '+' ด้วย
  • มีอักขระข้างต้นที่กําหนดให้เป็นอักขระที่สงวนไว้ แต่ต้องใช้ตามตัวอักษร เช่น ระบบจะใช้ ? ภายใน URL เพื่อระบุจุดเริ่มต้นของสตริงการค้นหา หากคุณต้องการใช้สตริง "? และ Mysterions" ก็จะต้องเข้ารหัสอักขระ '?'

อักขระทั้งหมดที่จะเข้ารหัส URL จะได้รับการเข้ารหัสโดยใช้อักขระ '%' และค่าฐานสิบหกสองอักขระ ซึ่งสัมพันธ์กับอักขระ UTF-8 ตัวอย่างเช่น 上海+中國 ใน UTF-8 จะได้รับการเข้ารหัส URL เป็น %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B สตริง ? and the Mysterians จะมีการเข้ารหัส URL เป็น %3F+and+the+Mysterians หรือ %3F%20and%20the%20Mysterians

อักขระทั่วไปที่ต้องเข้ารหัส

อักขระทั่วไปที่ต้องเข้ารหัสได้แก่

อักขระที่ไม่ปลอดภัย ค่าที่เข้ารหัส
เว้นวรรค %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

ในบางครั้ง การแปลง URL ที่คุณได้รับจากอินพุตของผู้ใช้เป็นเรื่องยุ่งยาก ตัวอย่างเช่น ผู้ใช้อาจป้อนที่อยู่เป็น "5th&Main St." โดยทั่วไปคุณควรสร้าง URL จากส่วนต่างๆ ให้โดยถือว่าอินพุตของผู้ใช้เป็นอักขระตามตัวอักษร

นอกจากนี้ URL จะมีอักขระไม่เกิน 8, 192 ตัวสําหรับบริการผ่านเว็บ Google Maps Platform และ API เว็บแบบคงที่ทั้งหมด สําหรับบริการส่วนใหญ่ ความยาวจะใกล้จะถึงจํานวนอักขระสูงสุด อย่างไรก็ตาม โปรดทราบว่าบริการบางอย่างมีพารามิเตอร์หลายรายการที่อาจส่งผลให้ URL ยาว

การใช้ Google API อย่างสุภาพ

ไคลเอ็นต์ 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 ซิงโครไนซ์ตั้งแต่ต้นนาที แม้จะเกิดขึ้นระหว่างอุปกรณ์ต่างๆ แทนที่จะกระจายเท่าๆ กันเมื่อเวลาผ่านไป แอปพลิเคชันที่ออกแบบมาไม่ดี จะทําให้เกิดการเข้าชมพุ่งขึ้น ที่ระดับปกติ 60 เท่าในช่วงต้นของแต่ละนาที

การออกแบบที่ดีวิธีหนึ่งคือการตั้งปลุกครั้งที่ 2 เป็นเวลาที่เลือกแบบสุ่ม เมื่อการปลุกครั้งที่สองนี้ทําให้แอปพลิเคชันเรียกใช้ API ที่จําเป็นและเก็บผลลัพธ์ เมื่อแอปพลิเคชันต้องการอัปเดตการแสดงเมื่อเริ่มต้นนาที แอปพลิเคชันจะใช้ผลลัพธ์ที่จัดเก็บไว้ก่อนหน้านี้แทนการเรียก API อีกครั้ง วิธีนี้ทําให้การเรียก API กระจายอย่างเท่าๆ กันเมื่อเวลาผ่านไป นอกจากนี้ การเรียก API จะไม่หน่วงการแสดงผลเมื่อมีการอัปเดตจอแสดงผล

นอกเหนือจากต้นนาทีแล้ว เวลาซิงค์ทั่วไปอื่นๆ ที่คุณควรระวังคือไม่กําหนดเป้าหมายคือตอนเริ่มต้นชั่วโมงและเริ่มต้นทุกวันตอนเที่ยงคืน

การประมวลผลการตอบกลับ

หัวข้อนี้จะกล่าวถึงวิธีแตกค่าเหล่านี้จากการตอบกลับบริการเว็บแบบไดนามิก

บริการบนเว็บของ Google Maps ให้คําตอบที่เข้าใจง่าย แต่ไม่เป็นมิตรกับผู้ใช้ เมื่อดําเนินการค้นหา แทนที่จะแสดงชุดข้อมูล คุณอาจต้องการดึงค่าเฉพาะสองสามค่า โดยทั่วไป คุณจะต้องแยกวิเคราะห์การตอบกลับจากบริการเว็บ และแยกเฉพาะค่าที่คุณสนใจ

สคีมที่คุณใช้จะขึ้นอยู่กับว่าคุณแสดงเอาต์พุตใน JSON หรือไม่ การตอบกลับ JSON อยู่ในรูปแบบของออบเจ็กต์ Javascript อยู่แล้ว อาจได้รับการประมวลผลภายใน JavaScript บนไคลเอ็นต์