本文說明 Google API 如何與各種 HTTP 版本和實作搭配運作。如果您使用我們產生或手動編寫的用戶端程式庫 (大部分的用途都建議使用這種做法),就不需要擔心這些細節。程式庫會自動處理與伺服器的低層級通訊。
如果您是經驗豐富的開發人員,使用第三方 HTTP 用戶端編寫自訂程式碼來存取 API 的 REST 介面,則應瞭解本文記錄的相關概念,以及所選 HTTP 程式庫提供的功能。
使用傳輸通訊協定 (HTTP/*)
本節說明 Google API 可用來在用戶端和伺服器之間通訊的受支援傳輸通訊協定 (通常是 HTTP 的版本),以及這些通訊協定的建議使用方式。
HTTP 語意
開發 API 用戶端程式碼時,請遵循標準 HTTP 通訊協定語意。伺服器端 Proxy 或 API 堆疊可能只支援標準 HTTP 功能的子集,也可能支援其回溯相容版本。
必須由伺服器端 API 實作處理的 HTTP 通訊協定語意是由伺服器堆疊控管。只有在這些功能明確記載為屬於 API 規格的一部分 (例如快取支援) 時,才可依賴這類語意。
HTTP 版本
用戶端可使用用戶端平台或其用戶端網路允許的任何 HTTP/* 通訊協定,或與伺服器端 Proxy 交涉的任何 HTTP/* 通訊協定。支援的通訊協定包括 HTTP/1.1、HTTP/2 和 HTTP/3 (QUIC)。強烈建議不要繼續支援 HTTP/1.0。
部分 API 功能可能只有較新版本的 HTTP 通訊協定支援;有些功能則只有 HTTP/2 和 HTTP/3 提供完整支援,例如全雙工多工串流。如果您需要任何這些功能做為 API 規格的一部分,請注意不同 HTTP 版本的限制。請注意,HTTP/2 伺服器推送等較舊的功能已遭淘汰,現代網路用戶端不支援這些功能。
一般來說,我們建議使用 HTTP/3 或 HTTP/2,以獲得較佳效能、減少隊頭阻塞,並在網路發生問題時有較佳的恢復能力。
管道
管道是指第 4 層網路連線,通常是 HTTP/1.1 和 HTTP/2 的 TCP 通訊端,以及 HTTP/3 (QUIC) 的 UDP 通訊端。用戶端應用程式不應假設系統會如何管理端對端管道,因為連線幾乎一律是由 Google Front End (GFE) Proxy 代表伺服器程序終止。
HTTP/1.1 用戶端:如果使用 HTTP/1.1,請一律重複使用 TCP 連線 (連線:保持運作)。HTTP 用戶端程式庫通常會管理連線集區,以利重複使用連線。請避免在 HTTP/1.1 連線上使用 HTTP 管線,因為這類連線的支援度不佳,可能會導致問題。詳情請參閱「HTTP 和 TCP」。
HTTP/2 和 HTTP/3 用戶端:現代用戶端和瀏覽器主要使用 HTTP/2 或 HTTP/3。這兩種通訊協定都支援多工處理,可透過單一連線同時傳送多項要求和回應。
- HTTP/2:每個來源使用單一 TCP 連線。
- HTTP/3:每個來源透過 UDP 使用單一 QUIC 連線。QUIC 整合了 TLS 加密、壅塞控制和連線管理,通常可提供連線設定速度更快 (0-RTT 或 1-RTT) 等優點,且不受 TCP 串流隊頭阻塞問題影響。
使用 HTTP/2 和 HTTP/3 時,瀏覽器對單一主機的平行 TCP 連線數量限制 (例如 2 到 10 個) 不再是主要的效能問題。不過請注意,伺服器 (或 GFE 等 Proxy) 仍可對單一 HTTP/2 或 HTTP/3 連線中的並行串流數量強制設限。這可避免過載,並確保資源使用量合理 (例如將每個連線的並行要求或串流數量限制為 100 個)。
HTTPS
用戶端可根據 API 規格的支援情況,透過 HTTPS 或 HTTP 存取 API。TLS 交涉和 TLS 版本對用戶端應用程式而言是公開透明的。根據預設,Google API 只接受 HTTPS 流量。
要求和回應格式
本節說明 API 互動的結構,包括使用網址編碼資料、RESTful 動作的特定 HTTP 方法,以及以 JSON 為基礎的酬載格式。
要求網址
JSON 與 REST 的對應支援網址編碼要求資料,且 HTTP 要求和回應主體是使用 application/json 做為 Content-Type。
HTTP 主體使用 JSON 陣列來支援串流 RPC 方法,且 JSON 陣列可包含任意數量的 JSON 訊息或錯誤狀態 JSON 訊息。
較長的要求網址
網址有實際長度限制,通常預設為 16 KB,但實際情況可能因伺服器而異。如果 API 使用的 GET 要求所含網址超出此長度,要求可能無法送達目的地 API 伺服器,且會遭 Google Front End (GFE) 拒絕,並傳回 Your client has issued a malformed or illegal request. 錯誤訊息。
如要規避這類限制,用戶端程式碼應使用 POST 要求,其中含有 application/x-www-form-urlencoded 的 Content-Type 和 HTTP 標頭 X-HTTP-Method-Override: GET。這種方法也適用於 DELETE 要求。
HTTP 方法 (動詞)
如果要求網址遵循 REST 模型,其 HTTP 方法會列在 API 規格中。特別要注意的是,每個 API 方法都必須符合 HTTP 通訊協定的要求,實際要求視 API 方法對應的特定 HTTP 動詞而定。詳情請參閱超文本傳輸通訊協定規格和 PATCH 方法 RFC。
HTTP GET 和 HEAD 等安全方法不應代表擷取以外的動作。具體來說,HTTP GET 應視為「安全」的方法,而不應有任何用戶端可見的副作用。
HTTP 中的冪等性表示多個相同要求和單一要求的副作用相同。GET、PUT 和 DELETE 是與本風格指南相關的冪等 HTTP 方法。請注意,冪等性只會以伺服器副作用表示,而不會指定任何與回應相關的內容。尤其要注意的是,針對不存在的資源進行的 DELETE 應傳回 404 (Not Found)。
HTTP POST 和 PATCH 並不安全,也不是冪等的 (PATCH 是在 RFC 5789 中導入)。
| HTTP 動詞 | 安全 | 冪等 |
|---|---|---|
GET |
是 | 是 |
PUT |
是 | |
DELETE |
是 | |
POST |
||
PATCH |
酬載格式
要求和回應應共用相同的 Content-Type,但主體為「
application/x-www-form-urlencoded」的GET或POST要求除外。application/jsonMIME 類型支援 JSON。proto3 至 JSON 的對應關係正式列載於 JSON 對應一文中。表單參數 (
POST) 可用來取代網址查詢參數 (GET),但要遵循將要求欄位對應至查詢參數所適用的 REST 風格對應規則。支援的Content-Type為application/x-www-form-urlencoded。
串流
本節將詳細說明 Google API 如何處理用戶端和伺服器串流,特別是半雙工與全雙工通訊的限制,以及串流 JSON 訊息的編碼需求。
半雙工和全雙工的比較
HTTP 是要求-回應通訊協定,可讓其要求或回應主體透過不同的串流導向傳輸機制來傳送,例如 TCP (HTTP/1.x) 或其多路複用的版本 (SPDY、HTTP/2、QUIC)。
身為用戶端開發人員,您的應用程式可透過串流模式 (即用戶端串流) 產生要求主體。同樣地,應用程式也可透過串流模式 (即伺服器串流) 使用回應主體。
不過,HTTP 規格不會指定伺服器是否可在要求主體仍待處理時,透過串流傳回回應主體 (錯誤回應除外)。這個語意稱為「全雙工串流」。雖然許多 HTTP 用戶端/伺服器/Proxy 軟體允許全雙工串流,但即使是針對 HTTP 1.1,HTTP 式 Cloud API 也只能使用半雙工串流,以避免發生任何互通性問題。
根據預設,Cloud API 中的雙向串流方法會採用全雙工語意。也就是說,使用 HTTP 呼叫這類方法並不安全。如果串流方法僅為半雙工 (由伺服器強制執行),API 文件應清楚指定半雙工行為。
對於瀏覽器用戶端,標準 HTTP 語意會受到瀏覽器網路 API 的進一步限制。瀏覽器支援使用 XHR 或 Fetch 的伺服器串流 (通常會遵守傳輸層級的框架)。Fetch API 會使用 whatwg 串流。
由於瀏覽器限制,需要瀏覽器支援的 Cloud API 必須避免用戶端串流和全雙工串流,或必須專為瀏覽器用戶端另外提供 API。
一般來說,透過網際網路進行的用戶端串流不如伺服器串流實用。這是因為使用用戶端串流往往會產生有狀態的服務,這會對負載平衡產生負面影響,並使系統更容易發生錯誤或受到攻擊。另一方面,伺服器串流可大幅縮短延遲時間,因此或許很有幫助。
訊息編碼
JSON 訊息在串流時會編碼為 JSON 訊息陣列。要求或回應主體仍是有效的 JSON MIME 類型。
用戶端串流編碼範例如下:
1 <length> <message-bytes> 1 <length> <message-bytes> … EOF
伺服器串流編碼範例如下:
1 <length> <message-bytes> … 2 <length> <status-bytes> EOF
傳輸層級編碼:StreamBody 定義的唯一重要之處,在於其針對「messages」和「status」欄位分配的標記 ID <length> 會經過 Varint 編碼;一般訊息在進行這類編碼時會使用 1 到 2 個位元組,因此每則訊息的總編碼額外資料量為 2 到 3 個位元組。
另外需要選用的填充欄位來支援 Base64 編碼串流:
message StreamBody {
repeated bytes message = 1;
google.rpc.Status status = 2;
repeated bytes padding = 15; // max one-byte tag-id: xxx01111
}
錯誤訊息應採一般訊息的格式附加為 JSON 或 protobuf 陣列的最後一個元素。
狀態管理
半關閉行為在任何 HTTP 版本中都有完善定義,以便用戶端或伺服器向另一端告知主體已完成。
特別要注意的是,用戶端程式碼可在等候回應時自行完成要求。同樣地,用戶端可於系統仍在將要求主體寫入伺服器時查看完成的回應。當回應以非預期的方式完成時,HTTP 標準會預期用戶端取消或完成要求 (通常會傳回錯誤狀態)。也就是說,在正常情況下,當用戶端仍在傳送要求時,伺服器不應完成回應。
取消
「取消」支援功能可讓用戶端在要求或回應仍待處理時取消要求。
用戶端可在要求完成後自行關閉 TCP 連線,而不必取消要求或回應交易,因此 HTTP/1.* 用戶端沒有可靠的取消支援功能。使用 HTTP/1.1 時的 TCP FIN 不應視為取消,即使連線被標示為 keep-alive 亦然 (連線:保持運作)。
不過在用戶端關閉 TCP 連線後,如果伺服器嘗試寫入任何資料至用戶端,就會產生 RST,這樣可能會觸發取消作業。
另請注意,取消對於非串流 API 而言也是個問題,尤其當回應牽涉長時間輪詢,因而使連線可處於閒置狀態更長的時間時更是如此。
SPDY、HTTP/2 和 QUIC (特別是驅離訊息) 都支援明確取消。
保持運作
「保持運作」支援功能可讓用戶端或伺服器偵測發生錯誤的對等端,即使是封包遺失或網路發生錯誤也可偵測。
HTTP/1.1 不支援保持運作功能,因為 TCP 保持運作並不可行。
QUIC 或 HTTP/2 提供特殊控管訊息,以便讓應用程式 (包括瀏覽器) 支援 keep-alive 功能。
不過,如要可靠地偵測 keep-alive 和失敗情況,則可能需要具有必要伺服器端支援的用戶端程式庫:如果依賴基本 HTTP 做為通訊協定,透過網際網路執行長時間串流作業往往容易發生錯誤。
流量控制
「流量控制」支援功能需要用戶端將傳輸層級的流量控制事件傳播至用戶端應用程式,實際的機制取決於用戶端應用程式使用的 HTTP 用戶端 API 風格。舉例來說,您需要透過明確的流量控制支援功能,使用封鎖式寫入和讀取或非封鎖式寫入和讀取,讓應用程式處理及遵循流量控制事件,藉此避免用戶端或伺服器超載。
HTTP/1.1 需依賴 TCP 流量控制。
SPDY 和 HTTP/2 可在串流層級自行進行流量控制,但這會在連線層級進一步受到 TCP 流量控制的限制,因為要求會透過單一 TCP 連線多路複用。
QUIC 是透過 UDP 執行,因此流量控制完全由其自行管理。