API 要求失敗,並顯示 502 Bad Gateway「Unexpected EOF at target」錯誤

本頁內容適用於 ApigeeApigee Hybrid

查看 Apigee Edge 說明文件。

這本劇本可用於診斷及解決 Apigee 和 Apigee Hybrid 的 502 Bad Gateway Unexpected EOF 錯誤。

問題

用戶端應用程式會收到 HTTP 狀態碼 502,以及「Bad Gateway」訊息,做為 API 呼叫的回應。HTTP 狀態碼 502 表示用戶端 (在本例中為 Apigee) 未從後端伺服器收到有效回應,而後端伺服器實際上應滿足要求。

錯誤訊息

用戶端應用程式 API 呼叫遇到下列回應代碼:

HTTP/1.1 502 Bad Gateway

此外,您可能會看到下列錯誤訊息:

{ 
    "fault": { 
        "faultstring": "Unexpected EOF at target", 
        "detail": { 
            "errorcode":"messaging.adaptors.http.flow.UnexpectedEOFAtTarget", 
            "reason":"TARGET_READ_UNEXPECTED_EOF" 
          } 
      } 
}

常見的診斷步驟

如要診斷錯誤,可以使用下列任一方法:

  • API Monitoring
  • 偵測工作階段錯誤
  • 輸入記錄
  • 執行階段記錄檔

API Monitoring

使用 API 監控功能診斷錯誤。

在 Google Cloud 控制台中,前往「Apigee」>「Proxy 開發」>「API 監控」頁面。

前往 API 監控頁面

在「API monitoring」(API 監控) 頁面中,按照下列步驟調查 502 錯誤:

  1. 在客戶專案的 Apigee UI 中,前往「Investigate」資訊主頁。
  2. 在頂端的「圖表」下拉式選單中,確認已選取「依狀態碼顯示錯誤代碼」和「依 Proxy 顯示錯誤來源」,並確認選取 502 錯誤發生時的正確時間範圍。
  3. 如果看到大量 502 錯誤,請按一下矩陣中的方塊。
  4. 右側會顯示 502 錯誤的詳細資料,如下所示:
API 監控資訊主頁顯示 502 錯誤,並醒目顯示錯誤代碼和錯誤來源。
API 監控檢視畫面,醒目顯示錯誤代碼和錯誤來源。

這裡會顯示以下資訊:

  • 故障代碼messaging.adaptors.http.flow.UnexpectedEOFAtTarget
  • 故障來源target

這表示目標發生非預期的 EOF,導致 502 錯誤。

偵測工作階段錯誤

使用偵錯工作階段診斷錯誤:

  1. 在進行 API 呼叫時執行新的偵錯工作階段,重現 502 Bad Gateway 錯誤。
  2. 選取其中一個失敗的要求,然後檢查追蹤記錄。
  3. 瀏覽追蹤記錄的各個階段,找出發生失敗的位置。
  4. 要求傳送至目標伺服器後,您應該會看到失敗訊息,如下所示 (請注意,螢幕截圖是偵錯 v1):
偵錯工作階段追蹤記錄,顯示目標發生非預期的 EOF 錯誤,並醒目顯示屬性。
偵錯工作階段追蹤記錄,其中醒目顯示錯誤詳細資料。

如上圖所示,請在發生錯誤的階段檢查 error 屬性。值應包含「Unexpected EOF at target」訊息。

您也可以在追蹤記錄的 AX (Analytics Data Recorded) 階段中,判斷 X-Apigee.fault-sourceX-Apigee.fault-code 的值。如果 X-Apigee.fault-sourceX-Apigee.fault-code 的值與下表顯示的值相符,則可確認 502 錯誤來自目標伺服器:

回應標頭
fault-source target
錯誤碼 messaging.adaptors.http.flow.UnexpectedEOFAtTarget

Istio Ingressgateway 記錄 (僅限混合式)

如要診斷 502 Unexpected EOF at target 錯誤,另一種方法是檢查 Ingress 記錄中的 502 錯誤。傳入記錄應顯示 x_apigee_fault_code 的值為 messaging.adaptors.http.flow.UnexpectedEOFAtTarget,而 x_apigee_fault_source 的值為 target

可能原因

502 Bad Gateway 錯誤的常見原因是 Unexpected EOF 錯誤,可能原因如下:

原因 說明
目標伺服器設定有誤 目標伺服器未正確設定,無法在 Apigee 中支援傳輸層安全標準 (TLS)/安全資料傳輸層 (SSL) 連線
後端突然關閉連線 Apigee 傳送資料或等待後端伺服器回應時,後端伺服器可能會突然關閉連線
Keep-alive 超時設定有誤 Apigee 和後端伺服器上的 Keep-Alive 超時設定有誤
搭配使用 NAT 與 AWS NLB 目標,並啟用跨可用區負載平衡和 IP 保留功能 (僅限 Apigee X) 使用 NAT 搭配 AWS NLB 目標,並啟用跨可用區負載平衡和 IP 保留功能。

原因:目標伺服器設定錯誤

目標伺服器未正確設定,無法支援 TLS/SSL 連線。

診斷

  1. 如果失敗的 API 要求的偵錯工作階段顯示以下內容,很可能是目標伺服器設定有誤導致這個問題:
    • 目標流程要求啟動後,隨即出現 502 Bad Gateway 錯誤
    • error.class 會顯示 messaging.adaptors.http.flow.UnexpectedEOF
    {
      "properties": {
        "error.class": "messaging.adaptors.http.flow.UnexpectedEOF",
        "error.cause": "java.io.EOFException: eof unexpected"
      }
    }
    
    {
      "properties": {
        "error.class": "messaging.adaptors.http.flow.UnexpectedEOF",
        "error.cause": "java.io.EOFException: eof unexpected"
      }
    }
    
  2. 使用 Apigee 管理 API 呼叫取得目標伺服器定義
export TOKEN=$(gcloud auth print-access-token); 
curl -s -H "Authorization: Bearer $TOKEN" https://apigee.googleapis.com/v1/organizations/{org_name}/environments/{env_name}/targetservers/{target_server}

錯誤的 TargetServer 定義範例:

{ 
  "name": "bad-targetserver", 
  "host": "my-apigee-example.sample.appspot.com", 
  "port": 443, 
  "isEnabled": true, 
  "protocol": "HTTP" 
}

圖示 TargetServer 定義是常見的設定錯誤範例,說明如下:

假設目標伺服器 my-apigee-example.sample.appspot.com 已設為接受通訊埠 443 的安全 (HTTPS) 連線。不過,如果您查看目標伺服器定義,會發現沒有其他屬性/旗標指出該伺服器適用於安全連線。這會導致 Apigee X 將傳送至特定目標伺服器的 API 要求視為 HTTP (不安全) 要求。因此 Apigee X 不會啟動與這個目標伺服器的 TLS/SSL 握手程序。

由於目標伺服器已設定為僅接受通訊埠 443 上的 HTTPS (TLS/SSL) 要求,因此會拒絕 Apigee X 的要求或關閉連線。因此 apigee-runtime 會顯示 UnexpectedEOFAtTarget 錯誤。apigee-runtime 會將 502 Bad Gateway 做為回應傳送給用戶端。

解析度

請務必根據需求正確設定目標伺服器。以上圖示範例中,如要向安全 (HTTPS TLS/SSL) 目標伺服器發出要求,您需要加入 sSLInfo 屬性,並將 enabled 旗標設為 true。雖然可以在目標端點定義中新增目標伺服器的 sSLInfo 屬性,但建議您將 SSLInfo 屬性新增為目標伺服器定義的一部分,以免造成混淆。您可以直接在目標伺服器上啟用所有必要屬性,如下所示:

更新「目標伺服器」使用者介面,並開啟「啟用 SSL」切換按鈕 「更新目標伺服器」對話方塊,並開啟「啟用 SSL」切換按鈕。

如果後端服務需要單向 SSL 通訊,您必須在目標伺服器定義中啟用 TLS/SSL,方法是加入 sSLInfo 屬性,並將 enabled 旗標設為 true。用來取得目標伺服器的 API 呼叫應會傳回如下所示的資料:

{
    "name": "bad-targetserver",
    "host": "my-apigee-example.sample.appspot.com",
    "port": 443,
    "isEnabled": true,
    "sSLInfo": {
        "enabled": true
    },
    "protocol": "HTTP"
}

如果需要在 Apigee X 中驗證目標伺服器的憑證,則必須一併加入包含目標伺服器憑證的 truststore,如下所示:

{
    "name": "bad-targetserver",
    "host": "my-apigee-example.sample.appspot.com",
    "port": 443,
    "isEnabled": true,
    "sSLInfo": {
        "enabled": true,
        "trustStore": "ref://my-reference"
    },
    "protocol": "HTTP"
}

如果後端服務需要雙向 SSL 通訊,則您需要適當設定 sSLInfo 屬性的 clientAuthEnabledkeystorekeyAliastruststore 旗標,如下所示:

{
    "name": "bad-targetserver",
    "host": "my-apigee-example.sample.appspot.com",
    "port": 443,
    "isEnabled": true,
    "sSLInfo": {
        "enabled": true,
        "clientAuthEnabled": true,
        "keyStore": "ref://test-ref",
        "keyAlias": "my-alias-2",
        "trustStore": "ref://my-reference"
    },
    "protocol": "HTTP"
}

原因:後端突然關閉連線

建立 TCP 連線後,後端伺服器可能會在 Apigee 傳送資料或等待回應時突然關閉連線,進而觸發 Apigee 執行階段的 EOF 例外狀況。

診斷

如「常見診斷步驟」所示,使用 API 監控、偵錯工作階段或 Ingress 記錄,判斷 502 錯誤的訊息 ID、錯誤代碼和錯誤來源。

以下記錄是 Istio Gateway 記錄的範例 (僅限混合式),當後端突然關閉連線時就會建立這類記錄 (範例已稍微縮短)。請特別注意例外狀況 x_apigee_fault_codetarget 和包含 HTTP 502 狀態碼的 statusUnexpectedEOFAtTargetx_apigee_fault_source

{ 
    "dynamic_data": { 
      "x_apigee_fault_flag": "false", 
      "x_apigee_target_latency": "3335", 
      "x_apigee_dp_color": "1-11-0-apigee-8", 
      "x_apigee_fault_revision": "/organizations/test-org/environments/test-env/apiproxies/eof-test/revisions/5", 
      "x_apigee_fault_code": "messaging.adaptors.http.flow.UnexpectedEOFAtTarget", 
      "x_apigee_tracking_id": "b65eb01ec690656918d39cc767eb6aad", 
      "x_apigee_organization": "test-org", 
      "x_apigee_fault_source": "target", 
      "x_apigee_message_id": "123abc45-6def-789a-bc1-23def456abc78", 
      "x_envoy_upstream_service_time": "3558", 
      "x_apigee_region": "us-east1", 
      "x_apigee_fault_policy": "null/null", 
      "x_apigee_environment": "test-env", 
      "x_apigee_proxy": "/organizations/test-org/environments/test-env/apiproxies/eof-test/revisions/5", 
      "x_apigee_proxy_basepath": "/eof-test" 
    }, 
    "start_time": "2023-12-13T07:08:03.054Z", 
    "request_time": 3562, 
    "host": "203.0.113.10.nip.io", 
    "request_method": "GET", 
    "apigee_tracking_id": "b65eb01ec690656918d39cc767eb6aad", 
    "upstream_address": "10.1.1.2:8443", 
    "status": 502, 
    "upstream_response_time": 3560, 
    "x_forwarded_for": "198.51.100.10,203.0.113.10,198.51.100.11", 
    "request_protocol": "HTTP/1.1", 
    "status_details": "via_upstream", 
    "remote_address": "192.0.2.10:45752", 
    "tls_protocol": "TLSv1.2", 
    "request_id": "ce871b05-e62d-44a9-b15d-cb2f3553fd7f", 
    "bytes_received": 0, 
    "upstream_response_flags": "-" 
}

記下 Istio Gateway 記錄中的 x_apigee_message_id( 僅限 Hybrid),或從其他來源 (例如偵錯工作階段) 取得 message_id,然後檢查 apigee-runtime 記錄( 僅限 Hybrid) 中的 502 Istio 記錄。

顯示 EOF 例外的記錄檔探索工具
記錄檔探索工具檢視畫面,顯示 apigee-runtime 記錄檔中的 EOF 例外狀況。

下列範例記錄顯示 java.io.EOFException

{
  "insertId": "2xo6ibes68n88g38",
  "jsonPayload": {
    "level": "SEVERE",
    "logger": "HTTP.CLIENT",
    "className": "com.apigee.protocol.http.HTTPClient$Context$3",
    "message": "ClientChannel[Connected: Remote:203.0.113.20:8080 Local:10.1.1.2:25480]@148915 useCount=0 bytesRead=0 bytesWritten=1303 age=3334ms lastIO=3163ms isOpen=true.onExceptionRead",
…
    "thread": "NIOThread@0",
    "exceptionStackTrace": "java.io.EOFException: eof unexpected\n\tat com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:31)\n\tat com.apigee.nio.channels.InputChannel.read(InputChannel.java:95)\n\tat com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:87)\n\tat com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(DefaultNIOSupport.java:44)\n\tat com.apigee.nio.handlers.NIOThread.run(NIOThread.java:195)\n",
    "method": "onException"
  },
…
}

在上述範例中,您可以看到 apigee-runtime 嘗試從後端伺服器讀取回應時發生 java.io.EOFException: eof unexpected 錯誤。這項例外狀況表示檔案結尾 (EOF),或意外達到串流結尾。

這表示 apigee-runtime 已成功連線至後端伺服器,且正在傳送 API 要求,或正在等待或讀取後端的回應。不過,後端伺服器因某種原因突然終止連線,導致 apigee-runtime 無法取得預期回應或讀取完整回應。

如要取得後端伺服器突然終止連線的最終證明,請執行下列操作:

  1. 通常,當 apigee-runtime 將要求傳送至後端伺服器時,後端伺服器會立即以 [FIN,ACK] 回應,因而導致這項錯誤。查看後端伺服器記錄,瞭解是否有任何錯誤或資訊,導致後端伺服器突然終止連線。如果發現任何錯誤/資訊,請前往「解決方法」,並在後端伺服器中適當修正問題。如果後端伺服器中沒有任何錯誤或資訊,請在 Apigee 之後的第一個躍點收集封包擷取。
  2. (僅限混合式) 您可能也想在 apigee-runtime 上收集封包擷取內容,請參閱「如何擷取 tcpdump」一文。如果是 GKE,請參閱 https://cloud.google.com/container-optimized-os/docs/how-to/toolbox
  3. 請參考以下 tcpdump 範例。以下是發生 502 Bad Gateway Error UnexpectedEOFAtTarget 時擷取的 tcpdump 範例:
    TCPDump 顯示來自後端伺服器的早期 FIN、ACK,早於完整回應。
    後端過早傳送 FIN、ACK 的 tcpdump 範例。
  4. 從 TCPDump 輸出內容中,您會發現下列事件順序:
    • 封包 2354 到 2372 成功建立 apigee-runtime 與後端伺服器之間的連線。
    • 在封包 2512 中,後端伺服器會以 [FIN,ACK] 回應 (封包 2372 從 Apigee 傳送至封包 2512 的 [FIN, ACK] 之間經過 3 秒,是因為這個範例是在後端休眠 3 秒後建構,之後就會關閉連線)。
    • 在封包 2516 中,apigee-runtime 會以 [FIN,ACK] 回應後端伺服器。
    • 最終,連線會由 Apigee 以 [RST] 關閉。
    • 由於 Apigee 仍在傳送要求,或等待 / 讀取後端伺服器的回應,因此後端伺服器突然傳送 [FIN,ACK] 時,Apigee 會擲回 java.io.EOFException: eof unexpected 例外狀況,因為 Apigee 預期不會收到這類訊息。

解析度

請注意,這並非一般的連線逾時錯誤 (狀態碼 503),因為 TCP 連線已成功建立,也不是服務無法使用錯誤 (狀態碼 504),因為連線已透過後端的 [FIN, ACK] 成功關閉 (雖然 apigee-runtime 此時並未預期收到 [FIN, ACK])。如果後端伺服器發生網路問題,或是後端程式碼有錯誤,就可能發生這種情況。顧客需要請網路營運團隊和後端伺服器團隊進一步調查這個問題,並在後端伺服器或網路躍點上適當修正問題。

原因:存留逾時設定有誤

在判斷 502 錯誤是否由這個原因造成之前,請先詳閱下列概念。

Apigee 中的永久連線

根據預設,Apigee X 會遵循 HTTP/1.1 標準,並在與目標後端伺服器通訊時使用持續性連線。持續性連線可重複使用已建立的 TCP 和 (如適用) TLS/SSL 連線,藉此減少延遲負擔,進而提升效能。連線需要保留的時間長度,是透過存留時間逾時屬性 (在 Apigee 的目標端點設定中,這個屬性稱為 keepalive.timeout.millis) 控制。

後端伺服器和 Apigee apigee-runtime 都會使用保持連線逾時,彼此保持連線。如果超過存留時間逾時期間未收到任何資料,後端伺服器或 apigee-runtime 即可關閉與對方的連線。

根據預設,部署至 Apigee X 中 apigee-runtime 的 API Proxy 會將連線存留逾時設為 60 秒,除非遭到覆寫。如果 60 秒內未收到任何資料,Apigee 就會關閉與後端伺服器的連線。後端伺服器也會維持保持連線逾時,一旦逾時,後端伺服器就會關閉與 apigee-runtime 的連線。

Keepalive 超時設定有誤的影響

如果 Apigee 或後端伺服器設定的保持連線逾時時間不正確,就會導致競爭條件,後端伺服器會傳送非預期的檔案結尾 (FIN),以回應資源要求。

舉例來說,如果 API Proxy 或 apigee-runtime 內設定的連線存留逾時值大於或等於上游後端伺服器的逾時值,則可能會發生下列競爭條件。也就是說,如果 apigee-runtime 在後端伺服器保持連線逾時的門檻附近才收到資料,但要求會透過現有連線傳送至後端伺服器,則可能因非預期的 EOF 錯誤而導致 502 Bad Gateway,說明如下:

  • 假設在 apigee-runtime 和後端伺服器上設定的連線存續逾時時間為 60 秒,且特定 apigee-runtime 處理上一個要求後,59 秒內沒有收到任何新要求。
  • apigee-runtime 會繼續使用現有連線處理第 59 秒傳入的要求 (因為保持連線逾時尚未經過),並將要求傳送至後端伺服器。
  • 不過,要求抵達後端伺服器之前,後端伺服器已超過連線存留逾時門檻。
  • apigee-runtime 對資源的要求正在傳輸中,但後端伺服器嘗試傳送 FIN 封包至 apigee-runtime,藉此關閉連線。
  • apigee-runtime 等待接收資料時,卻收到非預期的 FIN,因此連線遭到終止。
  • 這會導致 Unexpected EOF,隨後 apigee-runtime 會將 502 錯誤傳回給用戶端。

在本例中,我們發現發生 502 錯誤的原因是 apigee-runtime 和後端伺服器都設定了相同的 60 秒存留時間逾時值。同樣地,如果 apigee-runtime 上設定的連線存留逾時值高於後端伺服器,也可能發生這個問題。

診斷

如「常見診斷步驟」所示,使用 API 監控、偵錯工作階段或 Ingress 記錄,判斷 502 錯誤的訊息 ID、錯誤代碼和錯誤來源。

以下記錄是 Istio Gateway 記錄的範例 (僅限混合式),當後端突然關閉連線時就會建立這類記錄 (範例已稍微縮短)。請特別注意例外狀況 x_apigee_fault_codetarget 和包含 HTTP 502 狀態碼的 statusUnexpectedEOFAtTargetx_apigee_fault_source

{
...
    "dynamic_data": {
      "x_apigee_fault_flag": "false",
      "x_apigee_target_latency": "3335",
      "x_apigee_dp_color": "1-11-0-apigee-8",
      "x_apigee_fault_revision": "/organizations/my-org/environments/test-env/apiproxies/eof-test/revisions/5",
      "x_apigee_fault_code": "messaging.adaptors.http.flow.UnexpectedEOFAtTarget",
      "x_apigee_tracking_id": "b65eb01ec690656918d39cc767eb6aad",
      "x_apigee_organization": "my-org",
      "x_apigee_fault_source": "target",
      "x_apigee_message_id": "951a6d91-1c83-4cd0-bd0d-5d69d0310b1e1",
      "x_envoy_upstream_service_time": "3558",
      "x_apigee_region": "us-east1",
      "x_apigee_fault_policy": "null/null",
      "x_apigee_environment": "test-env",
      "x_apigee_proxy": "/organizations/my-org/environments/test-env/apiproxies/eof-test/revisions/5",
      "x_apigee_proxy_basepath": "/eof-test"
    },
    "start_time": "2023-12-13T07:08:03.054Z",
    "request_time": 3562,
    "host": "203.0.113.10.nip.io",
    "request_method": "GET",
    "apigee_tracking_id": "b65eb01ec690656918d39cc767eb6aad",
    "upstream_address": "10.1.1.2:8443",
    "status": 502,
    "upstream_response_time": 3560,
    "x_forwarded_for": "198.51.100.10,203.0.113.10,198.51.100.11",
    "request_protocol": "HTTP/1.1",
    "status_details": "via_upstream",
    "remote_address": "192.0.2.10:45752",
    "tls_protocol": "TLSv1.2",
    "request_id": "ce871b05-e62d-44a9-b15d-cb2f3553fd7f",
"bytes_received": 0,
    "upstream_response_flags": "-"
  },
  "resource": {
...
    }
  },
  "timestamp": "2023-12-13T07:08:06.867811686Z",
  "severity": "INFO",
  "labels": {
..
  },
...
}

記下 Istio Gateway 記錄中的 x_apigee_message_id( 僅限 Hybrid),或從其他來源 (例如偵錯工作階段) 取得 message_id,然後檢查 apigee-runtime 記錄( 僅限 Hybrid) 中的 502 Istio 記錄。您可以將 Istio 記錄檔與 apigee-runtime 記錄檔比對。對 Apigee Runtime 的查詢會顯示類似下列內容的記錄:

顯示 EOF 例外的記錄檔探索工具
記錄檔探索工具檢視畫面,顯示 apigee-runtime 記錄檔中的 EOF 例外狀況。

下列記錄範例顯示 java.io.EOFException

{
  "insertId": "2xo6ibes68n88g38",
  "jsonPayload": {
    "level": "SEVERE",
    "logger": "HTTP.CLIENT",
    "className": "com.apigee.protocol.http.HTTPClient$Context$3",
    "message": "ClientChannel[Connected: Remote:203.0.113.20:8080 Local:10.1.1.2:25480]@148915 useCount=7 bytesRead=0 bytesWritten=1303 age=3334ms lastIO=3163ms isOpen=true.onExceptionRead",
…
    "thread": "NIOThread@0",
    "exceptionStackTrace": "java.io.EOFException: eof unexpected\n\tat com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:31)\n\tat com.apigee.nio.channels.InputChannel.read(InputChannel.java:95)\n\tat com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:87)\n\tat com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(DefaultNIOSupport.java:44)\n\tat com.apigee.nio.handlers.NIOThread.run(NIOThread.java:195)\n",
    "method": "onException"
  },
…
}

}

錯誤 java.io.EOFException: eof unexpected 表示 apigee-runtime 收到 EOF,但仍在等待讀取後端伺服器的回應。

錯誤訊息中的 useCount=7 屬性表示 apigee-runtime 已重複使用此連線約七次,而 bytesWritten=1303 屬性則表示 apigee-runtime 已將 1303 位元組的要求酬載傳送至後端伺服器。但發生非預期的 EOF 錯誤時,系統會收到零位元組。

這表示 apigee-runtime 多次重複使用相同連線,且這次傳送資料後不久,就收到 EOF,但未收到任何資料。這表示後端伺服器的連線存續逾時時間,很可能短於或等於 API Proxy 中設定的時間。

您可以按照下文說明,使用 tcpdump 進一步調查。

  1. 如果後端伺服器中沒有任何錯誤或資訊,請在 Apigee 之後的第一個躍點上收集封包擷取,方法是執行下列指令:
    tcpdump -i any -s 0 host <BACKEND_HOSTNAME> -w <FILENAME>
  2. (僅限混合式) 您可能也想在 apigee-runtime 上收集封包擷取內容,請參閱「如何擷取 tcpdump」一文。如果是 GKE,請參閱 https://cloud.google.com/container-optimized-os/docs/how-to/toolbox
  3. 分析擷取的 tcpdump:
  4. TCPDump 顯示成功的要求,隨後在連線重複使用時顯示 FIN 和 ACK。
    顯示連線逾時問題的 tcpdump 範例。

在上述 tcpdump 範例中,您可以看到下列內容:

  • 在封包 5992 中,後端伺服器收到 GET 要求。
  • 在封包 6064 中,伺服器會以 200 OK 回應。
  • 在封包 6084 中,後端伺服器收到另一個 GET 要求。
  • 在封包 6154 中,伺服器會以 200 OK 回應。
  • 在封包 6228 中,後端伺服器收到第三個 GET 要求。
  • 這次,後端伺服器會將 FIN、ACK 傳回 apigee-runtime (封包 6285),啟動連線關閉程序。

在本範例中,同一個連線成功重複使用兩次,但在第三個要求中,後端伺服器啟動連線關閉程序,而 apigee-runtime 正在等待後端伺服器的資料。這表示後端伺服器的連線存留逾時時間,很可能短於或等於 API Proxy 中設定的值。

比較 Apigee 和後端伺服器上的 Keep-Alive 超時

  1. 根據預設,Apigee X 會將連線存留逾時屬性的值設為 60 秒。
  2. 不過,客戶可能已在 API Proxy 中覆寫預設值。如要確認這項問題,請檢查發生 502 錯誤的 API Proxy 中,特定 TargetEndpoint 的定義。以下是 TargetEndpoint 設定範例,其中「keep alive timeout」屬性已覆寫為 30 秒 (30000 毫秒):
  3. <TargetEndpoint name="default"> 
     <HTTPTargetConnection> 
        <URL>https://mocktarget.apigee.net/json</URL> 
        <Properties> 
          <Property name="keepalive.timeout.millis">30000</Property> 
        </Properties> 
      </HTTPTargetConnection> 
    </TargetEndpoint>
  4. 接著,請檢查後端伺服器上設定的「保持連線逾時」屬性。假設後端伺服器設定的值為 25 秒。
  5. 如果您判斷 Apigee 的保持連線逾時屬性值高於後端伺服器的保持連線逾時屬性值 (如上例所示),這就是導致 502 錯誤的原因。

解析度

請務必確保 Apigee (在 API Proxy 和 apigee-runtime 元件中) 的連線存留逾時屬性,一律低於後端伺服器上的屬性。

  1. 判斷後端伺服器上設定的連線存留逾時值。
  2. 在 API Proxy 或 apigee-runtime 中,為保持運作逾時屬性設定適當的值,使保持運作逾時屬性低於後端伺服器上設定的值,方法請參閱「反模式:停用 HTTP 持續性 (可重複使用的保持運作) 連線」一文。

原因:搭配使用 NAT 與 AWS NLB 目標,並啟用跨區域負載平衡和 IP 保留功能

(僅限 Apigee X) 如果您使用 AWS NLB 做為目標,可能會遇到下列問題:

假設 AWS NLB 有 3 個 IP:

203.0.113.1:443 (可用區 1)
203.0.113.2:443 (可用區 2)
203.0.113.3:443 (可用區 3)

Apigee X 會建立下列連線:

  • 192.0.2.10:30009 -> 203.0.113.1:443
  • 192.0.2.10:30009 -> 203.0.113.1:443 (現有)
  • 192.0.2.10:30009 -> 203.0.113.2:443 (new)

這是正常現象。

如果 203.0.113.1:443 和 203.0.113.2:443 指向相同的 NLB 後端,就會發生問題。如果是,後端會收到來自相同來源,但屬於兩個不同連線的封包。這會導致兩項連結都中斷。

第一次連線可能會失敗,並出現相同的 EOF 錯誤,但也有可能出現其他錯誤。

診斷

確認是否符合所有下列條件:

如果是這樣,問題應該會間歇性發生。由於上述條件可診斷問題,因此不需要 .pcap。不過,您可以在目標網路擷取中發現,但無法在 Apigee 擷取中發現。

目標 .pcap 診斷

如要在 Wireshark 的目標擷取畫面中找出這項資訊,請按照下列步驟操作:

  1. 依受影響連線的通訊埠篩選,例如 tcp.port == 30009
  2. 在「資料欄」上按一下滑鼠右鍵 ->「資料欄偏好設定」。新增「自訂」類型的欄。欄位:tcp.seq_raw。系統會顯示原始序號。
  3. 找出具有 Apigee 來源 IP 的封包是否有任何新的序號。舉例來說,如果看到以 384 開頭的原始序號,但突然切換為 376,且沒有有效的連接埠重複使用案例,就是連線衝突。

解析度

停用跨區域負載平衡保留用戶端 IP

Cloud NAT 在這裡的行為正確,這是 NLB 架構的問題。Apigee 無法進行任何變更。

必須收集診斷資訊

如果按照上述指示操作後問題仍未解決,請收集下列診斷資訊,然後與 Google Cloud 客服團隊聯絡

  • Google Cloud 專案 ID
  • Apigee 組織
  • API Proxy 和修訂版本
  • 下載失敗 API 呼叫的偵錯工作階段檔案。
  • 與失敗時間相應的後端伺服器記錄。
  • 失敗期間,從訊息處理器或後端伺服器擷取的 tcpdump 封包。