แนวทางปฏิบัติแนะนำสำหรับการใช้บริการเว็บ Roads API

บริการเว็บของ 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 ว่า "ถูกต้อง" แต่ก็จะต้องแปลอักขระเหล่านั้นก่อนที่จะส่งไปยังเว็บเซิร์ฟเวอร์ กระบวนการนี้เรียกว่า การเข้ารหัส URL หรือการเข้ารหัสเปอร์เซ็นต์

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

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

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

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

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

อักขระทั้งหมดที่จะเข้ารหัส URL จะเข้ารหัสด้วยอักขระ '%' และค่าฐานสิบหกแบบ 2 อักขระที่สอดคล้องกับอักขระ 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 โดยถือว่าอินพุตของผู้ใช้เป็นอักขระตามตัวอักษร

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

ใช้ Google APIs อย่างสุภาพ

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

Exponential Backoff

ในบางกรณีที่เกิดขึ้นไม่บ่อยนัก อาจเกิดความผิดพลาดในการดำเนินการตามคำขอของคุณ คุณอาจได้รับรหัสตอบกลับ HTTP 4XX หรือ 5XX หรือการเชื่อมต่อ TCP อาจเกิดข้อผิดพลาดระหว่างไคลเอ็นต์ของคุณและเซิร์ฟเวอร์ของ Google บ่อยครั้งที่คุ้มค่าที่จะลองส่งคำขออีกครั้ง เนื่องจากคำขอติดตามผลอาจสำเร็จเมื่อคำขอเดิมล้มเหลว อย่างไรก็ตาม สิ่งที่ไม่ควรทำซ้ำๆ คือการส่งคำขอไปยังเซิร์ฟเวอร์ของ Google ซ้ำๆ การวนซ้ำอาจทำให้เครือข่ายระหว่างไคลเอ็นต์และ Google ทำงานหนักเกินไป ซึ่งจะทำให้เกิดปัญหาในหลายฝ่าย

วิธีที่ดีกว่าคือลองอีกครั้งโดยให้ความล่าช้าเพิ่มขึ้นระหว่างการดำเนินการแต่ละครั้ง โดยทั่วไปความล่าช้าจะเพิ่มขึ้นตามตัวคูณคูณในการพยายามแต่ละครั้ง ซึ่งวิธีการที่เรียกว่า Exponential Backoff

เช่น ลองพิจารณาแอปพลิเคชันที่ต้องการส่งคำขอนี้ไปยัง 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 อาจดูเหมือนการโจมตีแบบ Distributed Denial of Service (DDoS) บนโครงสร้างพื้นฐานของ Google จึงถือว่าคุณจัดการกับคำขอที่เหมาะสม เพื่อหลีกเลี่ยงปัญหานี้ คุณควรตรวจสอบว่าคำขอ API ไม่ได้ซิงค์ระหว่างไคลเอ็นต์

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

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

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

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

กำลังประมวลผลคำตอบ

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

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

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