本章節概略說明 Google Distributed Cloud 實體隔離環境 (GDC) API 的錯誤模型。並提供一般指南來協助開發人員正確產生及處理錯誤。
GDC API 使用各通訊協定通用的簡易錯誤模型,可讓我們在不同的 API、API 通訊協定 (例如 gRPC 或 HTTP),以及錯誤情境 (例如非同步、批次或工作流程錯誤) 中提供一致的體驗。
錯誤模型
GDC API 的錯誤模型是由 google.rpc.Status
以符合邏輯的方式定義,系統會在發生 API 錯誤時向用戶端傳回其例項。以下程式碼片段顯示錯誤模型的整體設計:
package google.rpc;
// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs.
message Status {
// A simple error code that can be easily handled by the client. The
// actual error code is defined by `google.rpc.Code`.
int32 code = 1;
// A developer-facing human-readable error message in English. It should
// both explain the error and offer an actionable resolution to it.
string message = 2;
// Additional error information that the client code can use to handle
// the error, such as retry info or a help link.
repeated google.protobuf.Any details = 3;
}
由於大部分的 Google API 是使用資源導向的 API 設計,因此錯誤處理方式會遵循相同的設計原則,也就是使用少量固定的標準錯誤來對應大量的資源。舉例來說,伺服器不會定義不同種類的「找不到」錯誤,而會使用一個標準 google.rpc.Code.NOT_FOUND
錯誤代碼,並告訴用戶端找不到哪個特定資源。較小的錯誤空間可降低說明文件的複雜度、在用戶端程式庫中提供更佳的慣用對應關係,並降低用戶端邏輯的複雜度,同時仍可提供豐富的實用資訊。
錯誤代碼
GDC API 必須使用 google.rpc.Code
定義的標準錯誤代碼。個別 API 不得定義其他錯誤代碼,因為開發人員不太可能會編寫邏輯來處理大量的錯誤代碼。舉個例子做參考,如果每個 API 呼叫平均要處理三個錯誤代碼,就表示大部分的應用程式邏輯都只是用來處理錯誤,這對開發人員而言並非良好的體驗。
錯誤訊息
錯誤訊息應協助使用者輕鬆快速地瞭解並解決 API 錯誤。一般來說,建議您在撰寫錯誤訊息時遵循下列準則:
- 不要假設使用者對您的 API 瞭若指掌。使用者可能是用戶端開發人員、作業人員、IT 員工或應用程式的使用者。
- 不要假設使用者對您的服務實作機制有任何瞭解,或是能夠掌握錯誤的背景資訊 (舉例來說,不要假設對方有能力分析記錄檔的內容)。
- 如果可能的話,錯誤訊息的設計應該要讓熟悉相關技術的使用者 (但不一定是您 API 的開發人員) 能夠回應錯誤並進行修正。
- 錯誤訊息要保持精簡。請視需要提供連結,讓困惑的讀者能夠提問、提供意見,或取得無法在錯誤訊息中精簡呈現的其他資訊。如不提供連結,請使用詳細資料欄位來擴展錯誤訊息。
錯誤詳細資料
GDC API 會定義一組標準錯誤酬載以用於錯誤詳細資料 (您可以前往 google/rpc/error_details.proto 查看)。這些詳細資料可涵蓋大部分常見的 API 錯誤需求,例如配額錯誤和無效參數。如同錯誤代碼,開發人員應盡可能使用這些標準酬載。
除非有助於協助應用程式程式碼處理錯誤,否則請不要導入其他錯誤詳細資料類型。如果錯誤資訊只能由人工處理,請依賴錯誤訊息內容並讓開發人員手動處理,而不要導入其他錯誤詳細資料類型。
以下是一些 error_details
酬載範例:
ErrorInfo
:提供穩定且可擴充的結構化錯誤資訊。RetryInfo
:說明用戶端可重試失敗要求的時機,可在出現Code.UNAVAILABLE
或Code.ABORTED
時傳回QuotaFailure
:說明配額檢查失敗的原因,可在出現以下情形時傳回:Code.RESOURCE_EXHAUSTED
BadRequest
:說明用戶端要求中的違規事項,可在出現以下情形時傳回:Code.INVALID_ARGUMENT
錯誤資訊
ErrorInfo
是一種特殊的錯誤酬載。這項功能提供穩定且可擴充的錯誤資訊,可供使用者和應用程式參考。每個 ErrorInfo
都有三項資訊:錯誤網域、錯誤原因和一組錯誤中繼資料。詳情請參閱ErrorInfo
定義。
對於 GDC API,主要錯誤網域為 googleapis.com
,而對應的錯誤原因則由 google.api.ErrorReason
列舉定義。詳情請參閱google.api.ErrorReason
定義。
錯誤本地化
google.rpc.Status
中的 message
欄位會向開發人員顯示,且必須以英文呈現。
如果需要向使用者顯示的錯誤訊息,請使用google.rpc.LocalizedMessage
做為詳細資料欄位。雖然 google.rpc.LocalizedMessage
中的訊息欄位可以本地化,但請確保 google.rpc.Status
中的訊息欄位使用英文。
根據預設,API 服務應使用已驗證使用者的語言代碼或 HTTP Accept-Language
標頭,或要求中的 language_code
參數,判斷本地化語言。
錯誤對應
您可以在不同的程式設計環境中存取 GDC API。每個環境通常都有自己的錯誤處理方式。以下各節說明如何在常用環境中對應錯誤模型。
HTTP 對應
雖然 proto3 訊息有原生 JSON 編碼,但基於回溯相容性因素,GDC API 平台是使用其他 GDC JSON HTTP API 錯誤結構定義。
結構定義:
// This message defines the error schema for GDC JSON HTTP APIs.
message Error {
// Deprecated. This message is only used by error format v1.
message ErrorProto {}
// This message has the same semantics as `google.rpc.Status`. It uses HTTP
// status code instead of gRPC status code. It has extra fields `status` and
// `errors` for backward compatibility with [GDC API Client
// Libraries](https://developers.google.com/api-client-library).
message Status {
// The HTTP status code that corresponds to `google.rpc.Status.code`.
int32 code = 1;
// This corresponds to `google.rpc.Status.message`.
string message = 2;
// Deprecated. This field is only used by error format v1.
repeated ErrorProto errors = 3;
// This is the enum version for `google.rpc.Status.code`.
google.rpc.Code status = 4;
// This corresponds to `google.rpc.Status.details`.
repeated google.protobuf.Any details = 5;
}
// The actual error payload. The nested message structure is for backward
// compatibility with [GDC API Client
// Libraries](https://developers.google.com/api-client-library). It also
// makes the error more readable to developers.
Status error = 1;
}
範例:
{
"error": {
"code": 400,
"message": "API key not valid. Please pass a valid API key.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "API_KEY_INVALID",
"domain": "googleapis.com",
"metadata": {
"service": "translate.googleapis.com"
}
}
]
}
}
gRPC 對應
不同的 RPC 通訊協定會以不同的方式對應到錯誤模型。如果是 gRPC,產生的代碼和各種支援語言的執行階段程式庫都對錯誤模型提供原生支援。詳情請參閱 gRPC 的 API 說明文件。例如,請參閱 gRPC Java 的 io.grpc.Status
。
用戶端程式庫對應
GDC 用戶端程式庫可選擇依語言以不同方式顯示錯誤,藉此與既定的用語保持一致。舉例來說,google-cloud-go 程式庫會傳回與 google.rpc.Status
實作相同介面的錯誤,而 google-cloud-java 則會引發例外狀況。
處理錯誤
下表包含 google.rpc.Code
中定義的所有 gRPC 錯誤代碼,並大致說明出錯的原因。如要處理錯誤,您可以針對傳回的狀態代碼查看相關說明,並根據說明修改呼叫。
HTTP | gRPC | 說明 |
---|---|---|
200 | OK |
未發生錯誤。 |
400 | INVALID_ARGUMENT |
用戶端指定的引數無效。請檢查錯誤訊息和錯誤詳細資料以瞭解詳情。 |
400 | FAILED_PRECONDITION |
無法在目前的系統狀態中執行要求,例如刪除非空白的目錄。 |
400 | OUT_OF_RANGE |
用戶端指定的範圍無效。 |
401 | UNAUTHENTICATED |
要求因 OAuth 憑證遺漏、無效或過期而未通過驗證。 |
403 | PERMISSION_DENIED |
用戶端權限不足。這可能是因為 OAuth 憑證的範圍不正確、用戶端沒有權限,或 API 尚未啟用所致。 |
404 | NOT_FOUND |
找不到指定的資源。 |
409 | ABORTED |
並行衝突,例如「讀取、修改、寫入」衝突。 |
409 | ALREADY_EXISTS |
用戶端嘗試建立的資源已存在。 |
429 | RESOURCE_EXHAUSTED |
資源配額用盡或到到達頻率上限。用戶端應查看 google.rpc.QuotaFailure 錯誤詳細資料以瞭解詳情。 |
499 | CANCELLED |
用戶端已取消要求。 |
500 | DATA_LOSS |
發生無法復原的資料遺失或資料毀損情形。用戶端應向使用者回報錯誤。 |
500 | UNKNOWN |
發生不明的伺服器錯誤。通常是伺服器的錯誤。 |
500 | INTERNAL |
發生內部伺服器錯誤。通常是伺服器的錯誤。 |
501 | NOT_IMPLEMENTED |
伺服器未執行 API 方法。 |
502 | 不適用 | 連線至伺服器前發生網路錯誤,通常是網路中斷或設定有誤。 |
503 | UNAVAILABLE |
服務無法使用。通常是因伺服器停止運作所致。 |
504 | DEADLINE_EXCEEDED |
已超出要求期限。只有在呼叫者設定的期限短於方法的預設期限 (即要求的期限不夠讓伺服器處理要求),且要求未在期限內完成時,才會發生這項錯誤。 |
重試時發生錯誤
用戶端可以在發生 503 UNAVAILABLE 錯誤時,以指數輪詢方式重試。除非另有說明,否則最短延遲時間應為 1 秒。除非另有說明,否則預設的重試次數應為一次。
如果是 429 RESOURCE_EXHAUSTED 錯誤,用戶端重試的最短延遲時間可為 30 秒。這類重試機制僅適用於長時間執行的背景工作。
如果是任何其他錯誤,重試可能不適用。請先確認要求是冪等的,然後查看google.rpc.RetryInfo
以取得相關指示。
傳播錯誤
如果您的 API 服務必須依賴其他服務,請不要盲目地從那些服務將錯誤傳播到您的用戶端。翻譯錯誤時,建議您採取下列做法:
- 隱藏實作詳細資料和機密資訊。
- 調整負責處理錯誤的一方。例如,伺服器收到來自其他服務的
INVALID_ARGUMENT
錯誤時,應向其呼叫者傳播INTERNAL
。
重現錯誤
如果無法透過分析記錄和監控解決錯誤,請嘗試以簡單且可重複的測試重現錯誤。您可以透過這項測試收集更多資訊,以利排解問題,並在與技術支援團隊聯絡時提供這些資訊。
建議您使用 oauth2l
、curl -v
和系統參數,重現 GDC API 的錯誤。兩者可共同重現幾乎所有 GDC API 要求,並提供詳細的偵錯資訊。詳情請參閱所呼叫 API 的相關說明文件頁面。
產生錯誤
如果您是伺服器開發人員,則應產生包含充足資訊的錯誤訊息,以協助用戶端開發人員瞭解及解決問題。同時,由於錯誤往往會記錄下來並可由他人存取,因此您必須注意使用者資料的安全和隱私,並避免在錯誤訊息和錯誤詳細資料中揭露機密資訊。舉例來說,如果使用者可存取記錄檔,則「用戶端 IP 位址不在 128.0.0.0/8 允許清單中」這類錯誤訊息,可能會揭露使用者不可存取的伺服器端政策相關資訊。
如要產生適當的錯誤訊息,您必須先熟悉 google.rpc.Code
,才能針對各種錯誤情況選擇最適合的錯誤代碼。伺服器應用程式可並行檢查多個錯誤情況並傳回第一個情況。
下表列出各個錯誤代碼,並提供適當錯誤訊息的範例。
HTTP | gRPC | 錯誤訊息範例 |
---|---|---|
400 | INVALID_ARGUMENT |
要求欄位 x.y.z 為 xxx,但應為 [yyy, zzz]。 |
400 | FAILED_PRECONDITION |
資源 xxx 是非空白目錄,因此無法刪除。 |
400 | OUT_OF_RANGE |
「age」參數超出 [0, 125] 的範圍。 |
401 | UNAUTHENTICATED |
驗證憑證無效。 |
403 | PERMISSION_DENIED |
「xxx」權限遭拒,無法存取「yyy」資源。 |
404 | NOT_FOUND |
找不到「xxx」資源。 |
409 | ABORTED |
無法取得「xxx」資源的鎖。 |
409 | ALREADY_EXISTS |
「xxx」資源已存在。 |
429 | RESOURCE_EXHAUSTED |
超出「xxx」配額限制。 |
499 | CANCELLED |
用戶端已取消要求。 |
500 | DATA_LOSS |
請參閱附註。 |
500 | UNKNOWN |
請參閱附註。 |
500 | INTERNAL |
請參閱附註。 |
501 | NOT_IMPLEMENTED |
未實作「xxx」方法。 |
503 | UNAVAILABLE |
請參閱附註。 |
504 | DEADLINE_EXCEEDED |
請參閱附註。 |
錯誤酬載
google.rpc
套件會定義一組標準錯誤酬載,建議您使用這組酬載,而不使用自訂錯誤酬載。下表列出各個錯誤代碼,以及其對應的標準錯誤酬載 (如適用)。建議進階應用程式在處理錯誤時,於 google.rpc.Status
中尋找這些錯誤酬載。
HTTP | gRPC | 建議的錯誤詳細資料 |
---|---|---|
400 | INVALID_ARGUMENT |
google.rpc.BadRequest |
400 | FAILED_PRECONDITION |
google.rpc.PreconditionFailure |
400 | OUT_OF_RANGE |
google.rpc.BadRequest |
401 | UNAUTHENTICATED |
google.rpc.ErrorInfo |
403 | PERMISSION_DENIED |
google.rpc.ErrorInfo |
404 | NOT_FOUND |
google.rpc.ResourceInfo |
409 | ABORTED |
google.rpc.ErrorInfo |
409 | ALREADY_EXISTS |
google.rpc.ResourceInfo |
429 | RESOURCE_EXHAUSTED |
google.rpc.QuotaFailure |
499 | CANCELLED |
|
500 | DATA_LOSS |
google.rpc.DebugInfo |
500 | UNKNOWN |
google.rpc.DebugInfo |
500 | INTERNAL |
google.rpc.DebugInfo |
501 | NOT_IMPLEMENTED |
|
503 | UNAVAILABLE |
google.rpc.DebugInfo |
504 | DEADLINE_EXCEEDED |
google.rpc.DebugInfo |