錯誤回應

標準錯誤回應

如果 Reporting API 要求成功,API 就會傳回 200。如果要求發生錯誤,API 會根據錯誤類型在回應中傳回 HTTP 狀態碼、狀態和原因。此外,回應主體會詳細說明導致錯誤的原因。以下為錯誤回應的示例:

{
 "error": {
  "code": 403,
  "message": "User does not have sufficient permissions for this profile.",
  "status": "PERMISSION_DENIED"
 }
}

錯誤表

程式碼 狀態 說明 建議做法
400 INVALID_ARGUMENT 要求無效;必要的引數可能遺失、超過限制,或含有無效的值。 詳情請參閱錯誤訊息。如果用戶端重試,就會再次發生這個錯誤。
401 UNAUTHENTICATED 用戶端未正確驗證。 未修正問題前請勿重試。您必須取得新的驗證權杖。
403 PERMISSION_DENIED 指出使用者無權存取的資料要求。 未修正問題前請勿重試。您必須取得足夠的權限,才能對指定實體執行作業。
429 RESOURCE_EXHAUSTED AnalyticsDefaultGroupCLIENT_PROJECT-1d 表示每項專案的每日要求數 配額已耗盡。 未修正問題前請勿重試。你已用完每日配額。
429 RESOURCE_EXHAUSTEDAnalyticsDefaultGroupCLIENT_PROJECT-100 秒 表示每項專案每 100 秒的要求數配額已用盡。 使用指數輪詢重試。請降低傳送要求的速率。
429 RESOURCE_EXHAUSTEDAnalyticsDefaultGroupUSER-100 秒 表示每項專案每位使用者每 100 秒的要求配額已用盡。 使用指數輪詢重試。請降低傳送要求的速率。
429 RESOURCE_EXHAUSTED DiscoveryGroupCLIENT_PROJECT-100 秒 表示探索服務每 100 秒的要求數配額已用盡。 探索回應不會經常變更;在本機快取探索回應,或使用指數輪詢重試。您必須降低傳送要求的速率。
500 INTERNAL 發生非預期的內部伺服器錯誤。 這項查詢最多只能重試一次。
503 BACKEND_ERROR 伺服器傳回錯誤。 這項查詢最多只能重試一次。
503 UNAVAILABLE 服務無法處理這個要求。 這很有可能是暫時的狀況,並能透過指數輪詢重試。

實行指數輪詢

指數輪詢是指用戶端定期重試失敗要求的程序,且要求數量會隨時間增加。這是網路應用程式的標準錯誤處理策略。Reporting API 的設計宗旨,是讓用戶端選擇重試失敗的要求時,會以指數輪詢方式處理。使用指數輪詢不但可「必要」,還能提高頻寬用量、減少取得成功回應所需的要求數,並盡可能提高並行環境中的要求總處理量。

實作簡單指數輪詢的流程如下。

  1. 向 API 提出要求
  2. 接收包含可重試錯誤代碼的錯誤回應
  3. 等待 1 秒 + random_number_milliseconds
  4. 重試要求
  5. 接收包含可重試錯誤代碼的錯誤回應
  6. 等待 2 秒 + random_number_milliseconds
  7. 重試要求
  8. 接收包含可重試錯誤代碼的錯誤回應
  9. 等待 4 秒 + random_number_milliseconds
  10. 重試要求
  11. 接收包含可重試錯誤代碼的錯誤回應
  12. 等待 8 秒 + random_number_milliseconds
  13. 重試要求
  14. 接收包含可重試錯誤代碼的錯誤回應
  15. 等待 16 秒 + random_number_milliseconds
  16. 重試要求
  17. 如果持續發生錯誤,請停止並記錄錯誤。

在上述流程中,random_number_milliseconds 是小於或等於 1000 的隨機毫秒數。這是為了避免某些並行實作時發生特定鎖定錯誤。每次等待之後,都必須重新定義 random_number_milliseconds

注意:等待時間一律是 (2 ^ n) + random_number_milliseconds,其中 n 是最初定義為 0 的單調遞增整數。對於每次疊代 (每個要求),n 會遞增 1。

演算法已設定為會在 n 等於 5 時終止。此上限的用意只是防止用戶端無限重試,導致要求在總延遲時間達到約 32 秒之後,才會被視為「無法復原的錯誤」。

下列 Python 程式碼是上述流程的實作,用於從名為 makeRequest 的方法中發生的錯誤復原。

import random
import time
from apiclient.errors import HttpError

def makeRequestWithExponentialBackoff(analytics):
  """Wrapper to request Google Analytics data with exponential backoff.

  The makeRequest method accepts the analytics service object, makes API
  requests and returns the response. If any error occurs, the makeRequest
  method is retried using exponential backoff.

  Args:
    analytics: The analytics service object

  Returns:
    The API response from the makeRequest method.
  """
  for n in range(0, 5):
    try:
      return makeRequest(analytics)

    except HttpError, error:
      if error.resp.reason in ['userRateLimitExceeded', 'quotaExceeded',
                               'internalServerError', 'backendError']:
        time.sleep((2 ** n) + random.random())
      else:
        break

  print "There has been an error, the request never succeeded."