เว็บเซอร์วิสของ Google Maps Platform คือชุดอินเทอร์เฟซ HTTP สำหรับบริการของ Google ที่ให้ข้อมูลทางภูมิศาสตร์สำหรับแอปพลิเคชันแผนที่ของคุณ
คู่มือนี้อธิบายแนวทางปฏิบัติทั่วไปบางอย่างที่เป็นประโยชน์สำหรับการตั้งค่าคำขอเว็บเซอร์วิสและการประมวลผลการตอบกลับของบริการ ดูเอกสารประกอบฉบับเต็มของ Route Optimization API ได้ที่คู่มือสำหรับนักพัฒนาซอฟต์แวร์
บริการบนเว็บคืออะไร
เว็บเซอร์วิสของ Google Maps Platform เป็นอินเทอร์เฟซสำหรับขอข้อมูล Maps API จากบริการภายนอกและใช้ข้อมูลภายในแอปพลิเคชัน Maps บริการเหล่านี้ออกแบบมาเพื่อใช้ร่วมกับแผนที่ตามข้อจำกัดของใบอนุญาตในข้อกำหนดในการให้บริการของ Google Maps Platform
เว็บเซอร์วิสของ Maps API ใช้คำขอ HTTP(S) ไปยัง URL ที่เฉพาะเจาะจง โดยส่งพารามิเตอร์ของ URL และ/หรือข้อมูล POST ในรูปแบบ JSON เป็นอาร์กิวเมนต์ไปยังบริการ โดยทั่วไป บริการเหล่านี้จะแสดงข้อมูลในเนื้อหาการตอบกลับเป็น JSON เพื่อแยกวิเคราะห์และ/หรือประมวลผลโดยแอปพลิเคชันของคุณ
ตัวอย่างต่อไปนี้แสดง URL ของคำขอ RESTPOST ไปยังเมธอด optimizeTours
https://routeoptimization.googleapis.com/v1/projects/PROJECT_NUMBER:optimizeTours
แทนที่ PROJECT_NUMBER ด้วยหมายเลขหรือรหัสของโปรเจ็กต์ Cloud ที่เปิดใช้ Route Optimization API
ใส่ข้อความ OptimizeToursRequest เป็นเนื้อหาคำขอ JSON
หมายเหตุ: แอปพลิเคชัน Route Optimization API ทั้งหมดต้องมีการตรวจสอบสิทธิ์ ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลรับรองการตรวจสอบสิทธิ์
การเข้าถึง SSL/TLS
คำขอ Google Maps Platform ทั้งหมดที่ใช้คีย์ API หรือมีข้อมูลผู้ใช้ต้องใช้ HTTPS ระบบอาจปฏิเสธคำขอที่ส่งผ่าน HTTP ซึ่งมีข้อมูลที่ละเอียดอ่อน
การสร้าง URL ที่ถูกต้อง
คุณอาจคิดว่า URL ที่ "ถูกต้อง" นั้นชัดเจนในตัวเอง แต่จริงๆ แล้วไม่ใช่เช่นนั้น ตัวอย่างเช่น URL ที่ป้อนในแถบที่อยู่ของเบราว์เซอร์อาจมีสัญลักษณ์พิเศษ (เช่น "上海+中國") ซึ่งเบราว์เซอร์ต้องแปลสัญลักษณ์เหล่านั้นเป็นการเข้ารหัสอื่นภายในก่อนที่จะส่ง
ในทำนองเดียวกัน โค้ดใดๆ ที่สร้างหรือยอมรับอินพุต UTF-8 อาจถือว่า URL ที่มีอักขระ UTF-8 เป็น "ถูกต้อง" แต่ก็ต้องแปลอักขระเหล่านั้นก่อนที่จะส่งไปยังเว็บเซิร์ฟเวอร์ด้วย
กระบวนการนี้เรียกว่า
การเข้ารหัส URL หรือการเข้ารหัสเปอร์เซ็นต์
อักขระพิเศษ
เราจำเป็นต้องแปลสัญลักษณ์พิเศษเนื่องจาก URL ทั้งหมดต้องเป็นไปตามไวยากรณ์ที่ระบุไว้ในข้อกำหนดตัวระบุทรัพยากรสากล (URI) ซึ่งหมายความว่า URL ต้องมีเฉพาะชุดย่อยพิเศษของอักขระ ASCII เท่านั้น ซึ่งก็คือสัญลักษณ์ที่เป็นตัวอักษรและตัวเลขคละกันที่คุ้นเคย และอักขระที่สงวนไว้บางตัวเพื่อใช้เป็นอักขระควบคุมภายใน URL ตารางนี้สรุปอักขระเหล่านี้ไว้ดังนี้
| ตั้งค่า | อักขระ | การใช้ URL |
|---|---|---|
| ตัวอักษรและตัวเลขคละกัน | a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 | สตริงข้อความ การใช้รูปแบบ (http) พอร์ต (8080) ฯลฯ |
| ไม่ได้จอง | - _ . ~ | สตริงข้อความ |
| จองแล้ว | ! * ' ( ) ; : @ & = + $ , / ? % # [ ] | อักขระควบคุมและ/หรือสตริงข้อความ |
เมื่อสร้าง URL ที่ถูกต้อง คุณต้องตรวจสอบว่า URL นั้นมีเฉพาะอักขระที่แสดงในตารางเท่านั้น การปรับ URL ให้ใช้อักขระชุดนี้โดยทั่วไปจะทำให้เกิดปัญหา 2 อย่าง ได้แก่ การละเว้นและการแทนที่
- อักขระที่คุณต้องการจัดการอยู่นอกชุดอักขระข้างต้น ตัวอย่างเช่น อักขระในภาษาต่างประเทศ เช่น
上海+中國ต้องเข้ารหัสโดยใช้อักขระข้างต้น ตามแบบแผนที่นิยมใช้กัน ช่องว่าง (ซึ่งไม่อนุญาตให้ใช้ภายใน URL) มักจะแสดงโดยใช้อักขระบวก'+'ด้วยเช่นกัน - อักขระมีอยู่ในชุดด้านบนเป็นอักขระที่สงวนไว้ แต่ต้องใช้ตามตัวอักษร
เช่น มีการใช้
?ภายใน URL เพื่อระบุจุดเริ่มต้นของสตริงคำค้นหา หากต้องการใช้สตริง "? and the 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
อักขระทั่วไปที่ต้องเข้ารหัส
อักขระทั่วไปบางตัวที่ต้องเข้ารหัสมีดังนี้
| ตัวละครที่ไม่ปลอดภัย | ค่าที่เข้ารหัส |
|---|---|
| Space | %20 |
| " | %22 |
| < | %3C |
| > | %3E |
| # | %23 |
| % | %25 |
| | | %7C |
การแปลง URL ที่คุณได้รับจากอินพุตของผู้ใช้บางครั้งอาจเป็นเรื่องที่ยุ่งยาก เช่น ผู้ใช้อาจป้อนที่อยู่เป็น "5th&Main St." โดยทั่วไป คุณควรสร้าง URL จากส่วนต่างๆ ของ URL โดยถือว่าข้อมูลที่ผู้ใช้ป้อนเป็นอักขระตามตัวอักษร
นอกจากนี้ URL ยังมีความยาวไม่เกิน 16384 อักขระสำหรับเว็บเซอร์วิสและ Web API แบบคงที่ทั้งหมดของ Google Maps Platform สำหรับบริการส่วนใหญ่ จำนวนอักขระสูงสุดนี้จะไม่ค่อยมีผล อย่างไรก็ตาม โปรดทราบว่าบริการบางอย่างมีพารามิเตอร์หลายรายการที่อาจส่งผลให้ 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×tamp=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 เองในฝั่งไคลเอ็นต์