如果您要編寫自訂程式碼,透過第三方 HTTP 用戶端存取 API 的 REST 介面,請務必瞭解 Google API 如何搭配各種 HTTP 版本和實作方式運作。對於大多數工作負載,請改用 Google 建議的用戶端程式庫,這類程式庫會自動處理本文討論的低階伺服器通訊。
使用傳輸通訊協定 (HTTP/*)
本節說明 Google API 可用於在用戶端和伺服器之間通訊的支援線路通訊協定 (通常是 HTTP 版本),以及我們建議的使用方式。
HTTP 語意
開發 API 用戶端程式碼時,請遵循標準 HTTP 通訊協定語意。伺服器端 Proxy 或 API 堆疊可能只支援部分標準 HTTP 功能,也可能支援回溯相容版本。
需要由 API 伺服器端實作處理的 HTTP 通訊協定語意,是由伺服器堆疊控制。只有在 API 規格中明確記錄這些功能 (例如快取支援) 時,才可依賴這類語意。
HTTP 版本
用戶端可以使用任何 HTTP/* 通訊協定,只要用戶端平台或用戶端網路允許,或是與伺服器端 Proxy 協商即可。支援的通訊協定包括 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 連線 (Connection: Keep-Alive)。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
用戶端可以使用 HTTPS 或 HTTP 存取 API,具體取決於 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.
如要略過這項限制,用戶端程式碼應使用 Content-Type 為 application/x-www-form-urlencoded 的 POST 要求,以及 HTTP 標頭 X-HTTP-Method-Override: GET。這個方法也適用於 DELETE 要求。
HTTP 方法 (動詞)
如果要求網址遵循 REST 模型,其 HTTP 方法會列在 API 規格中。具體來說,每個 API 方法都必須根據 API 方法對應的特定 HTTP 動詞,遵守 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,除非要求是
GET或POST,且主體為「application/x-www-form-urlencoded」。JSON 支援
application/jsonMIME 類型。從 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 為基礎的雲端 API 僅限於半雙工串流。
根據預設,Cloud API 中的雙向串流方法會採用全雙工語意。也就是說,使用 HTTP 叫用這類方法並不安全。如果串流方法僅支援半雙工 (伺服器強制執行),API 文件應清楚說明半雙工行為。
如果是瀏覽器用戶端,標準 HTTP 語意會受到瀏覽器網路 API 的進一步限制。瀏覽器支援使用 XHR 或 Fetch 進行伺服器串流 (通常遵循傳輸層級框架)。Fetch API 會使用 whatwg 串流。
由於瀏覽器限制,需要瀏覽器支援的 Cloud API 必須避免用戶端串流和全雙工串流,或為瀏覽器用戶端提供專屬 API。
一般來說,透過網際網路進行用戶端串流的效果不如伺服器串流。這是因為使用用戶端串流通常會導致有狀態服務,這會對負載平衡產生負面影響,並使系統更容易發生故障或遭受攻擊。另一方面,伺服器串流則可大幅降低 RTT 延遲時間較長的網路延遲,因此相當實用。
訊息編碼
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 標準預期用戶端會在回應以非預期方式完成時,中止或完成要求,通常會出現錯誤狀態。也就是說,在正常情況下,當用戶端仍在傳送要求時,伺服器不應完成回應。
取消
「取消」支援功能可讓用戶端在要求或回應仍待處理時取消要求。
HTTP/1.* 用戶端沒有可靠的取消支援,因為用戶端可以在要求完成後自由關閉 TCP 連線,而不必取消要求或回應交易。在 HTTP/1.1 下,即使連線標示為保持運作 (Connection: Keep-Alive),TCP FIN 也不應解讀為取消。
不過在用戶端關閉 TCP 連線後,如果伺服器嘗試寫入任何資料至用戶端,就會產生 RST,這樣可能會觸發取消作業。
另請注意,取消對於非串流 API 而言也是個問題,如果回應涉及長輪詢,連線可能會長時間閒置,此時就特別需要這項功能。
SPDY、HTTP/2 和 QUIC (特別是驅離訊息) 都支援明確取消。
保持運作
Keep-alive 支援可讓用戶端或伺服器偵測失敗的對等互連,即使發生封包遺失或網路故障也一樣。
HTTP/1.1 不支援保持運作功能,因為 TCP 保持運作並不可行。
QUIC 或 HTTP/2 提供專用的控制訊息,供應用程式 (包括瀏覽器) 實作連線存續支援。
不過,可靠的持續連線和故障偵測功能可能需要用戶端程式庫,並提供必要的伺服器端支援:如果依賴基本 HTTP 做為通訊協定,透過網際網路進行長時間串流通常容易出錯。
流量控制
流量控制支援需要用戶端將傳輸層級流量控制事件傳播至用戶端應用程式。實際的機制取決於用戶端應用程式使用的 HTTP 用戶端 API 風格。舉例來說,您需要封鎖寫入和讀取,或非封鎖讀取和寫入,並明確支援流量控制,讓應用程式處理及遵循流量控制事件,以免用戶端或伺服器超載。
HTTP/1.1 需依賴 TCP 流量控制。
SPDY 和 HTTP/2 在串流層級有自己的流量控制,由於要求是在單一 TCP 連線上多工處理,因此在連線層級也受到 TCP 流量控制。
QUIC 在 UDP 上執行,因此完全自行管理流量控制。