502 閘道錯誤意外 EOF

您正在查看 Apigee Edge 說明文件。
查看 Apigee X 說明文件
資訊

問題

用戶端應用程式會取得 502 的 HTTP 狀態碼,以及訊息 Bad Gateway 做為 API 呼叫的回應。

HTTP 狀態碼 502 表示用戶端未收到來自後端伺服器的有效回應,但該回應應實際執行要求。

錯誤訊息

用戶端應用程式會取得以下回應代碼:

HTTP/1.1 502 Bad Gateway

此外,您可能會遇到以下錯誤訊息:

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

可能原因

其中一個導致 502 Bad Gateway Error 的常見原因為 Unexpected EOF 錯誤,可能原因如下:

原因 詳細說明 步入:
目標伺服器設定錯誤 目標伺服器未正確設定,因此無法支援 TLS/SSL 連線。 Edge Public and Private Cloud 使用者
後端伺服器的 EOFException 後端伺服器可能會突然傳送 EOF。 僅限 Edge Private Cloud 使用者
設定錯誤維持可用逾時 讓 Apigee 和後端伺服器的即時逾時設定保持錯誤。 Edge Public and Private Cloud 使用者

常見診斷步驟

您可以使用下列任一方法診斷錯誤:

API Monitoring

如何使用 API Monitoring 診斷錯誤:

使用 API 監控功能,即可調查 502 錯誤,請按照調查問題中所述的步驟操作。也就是:

  1. 前往「調查」資訊主頁。
  2. 在下拉式選單中選取「狀態碼」 ,並確認在 502 錯誤發生時已選取正確的時間範圍。
  3. 如果發現大量 502 錯誤,請按一下矩陣中的方塊。
  4. 找到右側的 502 錯誤,然後按一下「View Logs」(查看記錄檔),如下所示:
  5. 在這裡可以看到下列資訊:

    • 「Fault Source」為「target
    • 「Fault Code」messaging.adaptors.http.UnexpectedEOFAtTarget

這表示目標因非預期的 EOF 而造成 502 錯誤。

此外,請記下 502 錯誤的 Request Message ID,以便進一步調查。

追蹤工具

如何使用追蹤工具診斷錯誤:

  1. 啟用 追蹤工作階段,然後發出 API 呼叫來重現問題 502 Bad Gateway
  2. 請選取其中一個失敗的要求,然後檢查追蹤記錄。
  3. 瀏覽追蹤記錄的各個階段,找出發生錯誤的位置。
  4. 要求傳送至目標伺服器後,您應該會看到失敗,如下所示:

    alt_text

    alt_text

  5. 確定追蹤記錄中的 AX (Analytics (分析) 資料記錄) 階段中的 X-Apigee.fault-sourceX-Apigee.fault-code 值。

    如果 X-Apigee.fault-sourceX-Apigee.fault-code 的值符合下表顯示的值,您可以確認 502 錯誤來自目標伺服器:

    回應標頭
    X-Apigee.fault 來源 target
    X-Apigee.fault 程式碼 messaging.adaptors.http.flow.UnexpectedEOFAtTarget

    此外,請記下 502 錯誤的 X-Apigee.Message-ID,以便進一步調查。

NGINX 存取記錄檔

如何使用 NGINX 診斷錯誤:

您也可以參閱 NGINX 存取記錄檔,判斷出現 502 狀態碼的原因。如果問題過去發生,或是問題間歇發生,而且您無法在 UI 中擷取追蹤記錄,這個方法就特別實用。請使用下列步驟,從 NGINX 存取記錄檔判斷這項資訊:

  1. 查看 NGINX 存取記錄檔。
    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
  2. 搜尋特定 API Proxy 在特定時間範圍內 (如果問題在過去) 的任何 502 錯誤,或搜尋仍失敗且傳回 502 的任何要求。
  3. 如有任何 502 錯誤,請檢查該錯誤是否由目標傳送 Unexpected EOF 所導致。如果 X-Apigee.fault-sourceX- Apigee.fault-code 的值與下表顯示的值相符,表示目標因意外關閉連線而造成 502 錯誤:
    回應標頭
    X-Apigee.fault 來源 target
    X-Apigee.fault 程式碼 messaging.adaptors.http.flow.UnexpectedEOFAtTarget

    以下範例項目顯示目標伺服器造成的 502 錯誤:

此外,請記下 502 錯誤的郵件 ID,以利進一步調查。

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

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

診斷

  1. 使用 API 監控追蹤工具NGINX 存取記錄檔來判斷 502 錯誤的訊息 ID、錯誤代碼和錯誤來源。
  2. 在使用者介面中針對受影響的 API 啟用追蹤記錄。
  3. 如果 API 要求失敗的追蹤記錄顯示以下內容:
    1. 系統會在目標流程要求開始後,立即顯示 502 Bad Gateway 錯誤。
    2. error.class 會顯示 messaging.adaptors.http.UnexpectedEOF.

      這樣該問題很可能是目標伺服器設定不正確所致。

  4. 使用 Edge Management API 呼叫取得目標伺服器定義:
    1. 如果您是公開雲端使用者,請使用以下 API:
      curl -v https://api.enterprise.apigee.com/v1/organizations/<orgname>/environments/<envname>/targetservers/<targetservername> -u <username>
      
    2. 如果您是 Private Cloud 使用者,請使用以下 API:
      curl -v http://<management-server-host>:<port #>/v1/organizations/<orgname>/environments/<envname>/targetservers/<targetservername> -u <username>
      

      錯誤的 TargetServer 定義範例:

      <TargetServer  name="target1">
        <Host>mocktarget.apigee.net</Host>
        <Port>443</Port>
        <IsEnabled>true</IsEnabled>
      </TargetServer >
      
  5. 上述的 TargetServer 定義是其中一種一般設定錯誤的範例,相關說明如下:

    假設目標伺服器 mocktarget.apigee.net 已設為接受通訊埠 443安全 (HTTPS) 連線。不過,如果您查看目標伺服器定義,則不會看到其他用於安全連線的屬性/旗標。這會導致 Edge 將傳送至特定目標伺服器的 API 要求視為 HTTP (不安全的) 要求。因此 Edge 不會使用這個目標伺服器啟動安全資料傳輸層 (SSL) 握手程序。

    由於目標伺服器已設為在 443 上僅接受 HTTPS (SSL) 要求,因此會拒絕來自 Edge 的要求或關閉連線。因此,訊息處理器會收到 UnexpectedEOFAtTarget 錯誤。訊息處理器會將 502 Bad Gateway 做為回應傳送給用戶端。

解析度

請務必根據您的需求,正確設定目標伺服器。

以上述範例為例,如要向安全 (HTTPS/SSL) 目標伺服器發出要求,您必須加入 SSLInfo 屬性,並將 enabled 標記設為 true。雖然您可以在目標端點定義本身中新增目標伺服器的 SSLInfo 屬性,但建議您將 SSLInfo 屬性新增為目標伺服器定義的一部分,以免造成混淆。

  1. 如果後端服務需要單向安全資料傳輸層 (SSL) 通訊,則:
    1. 您需要在 TargetServer 定義中啟用 TLS/SSL,方法是在 enabled 標記設為 true 時加入 SSLInfo 屬性,如下所示:
      <TargetServer name="mocktarget">
        <Host>mocktarget.apigee.net</Host>
        <Port>443</Port>
        <IsEnabled>true</IsEnabled>
        <SSLInfo>
            <Enabled>true</Enabled>
        </SSLInfo>
      </TargetServer>
      
    2. 如果您要在 Edge 中驗證目標伺服器的憑證,我們也需要加入信任儲存庫 (包含目標伺服器的憑證),如下所示:
      <TargetServer  name="mocktarget">
          <Host>mocktarget.apigee.net</Host>
          <Port>443</Port>
          <IsEnabled>true</IsEnabled>
          <SSLInfo>
              <Ciphers/>
              <ClientAuthEnabled>false</ClientAuthEnabled>
              <Enabled>true</Enabled>
              <IgnoreValidationErrors>false</IgnoreValidationErrors>
              <Protocols/>
              <TrustStore>mocktarget-truststore</TrustStore>
          </SSLInfo>
      </TargetServer>
      
  2. 如果後端服務需要雙向安全資料傳輸層 (SSL) 通訊,則:
    1. 您需要正確設定 ClientAuthEnabledKeystoreKeyAliasTruststore 旗標的 SSLInfo 屬性,如下所示:
      <TargetServer  name="mocktarget">
           <IsEnabled>true</IsEnabled>
           <Host>www.example.com</Host>
           <Port>443</Port>
           <SSLInfo>
               <Ciphers/>
               <ClientAuthEnabled>true</ClientAuthEnabled>
               <Enabled>true</Enabled>
               <IgnoreValidationErrors>false</IgnoreValidationErrors>
               <KeyAlias>keystore-alias</KeyAlias>
               <KeyStore>keystore-name</KeyStore>
               <Protocols/>
               <TrustStore>truststore-name</TrustStore>
           </SSLInfo>
        </TargetServer >
      

參考資料

跨後端伺服器負載平衡

原因:後端伺服器的 EOFException

後端伺服器可能會突然傳送 EOF (檔案結尾)。

診斷

  1. 使用 API 監控追蹤工具NGINX 存取記錄檔來判斷 502 錯誤的訊息 ID、錯誤代碼和錯誤來源。
  2. 查看訊息處理器記錄檔 (/opt/apigee/var/log/edge-message-processor/logs/system.log),並搜尋特定 API 是否擁有 eof unexpected,或是具備該 API 要求的專屬 messageid,然後再搜尋。

    訊息處理器記錄中的例外狀況堆疊追蹤範例

    "message": "org:myorg env:test api:api-v1 rev:10 messageid:rrt-1-14707-63403485-19 NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context$3.onException() : SSLClientChannel[C:193.35.250.192:8443 Remote host:0.0.0.0:50100]@459069 useCount=6 bytesRead=0 bytesWritten=755 age=40107ms lastIO=12832ms .onExceptionRead exception: {}
    java.io.EOFException: eof unexpected
    at com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:45) ~[nio-1.0.0.jar:na]
    at com.apigee.nio.channels.InputChannel.read(InputChannel.java:103) ~[nio-1.0.0.jar:na]
    at com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:79) ~[http-1.0.0.jar:na]
    at com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(NIOSupport.java:51) [nio-1.0.0.jar:na]
    at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:123) [nio-1.0.0.jar:na]"
    

    在上述範例中,您可以看到訊息處理器嘗試讀取後端伺服器的回應時發生 java.io.EOFException: eof unexpected 錯誤。這個例外狀況表示檔案結束 (EOF),或是串流已意外觸及到結尾。

    也就是說,訊息處理器已將 API 要求傳送至後端伺服器,正在等候或讀取回應。不過,後端伺服器在訊息處理器收到回應前突然終止連線,或是讀取完整回應。

  3. 檢查後端伺服器記錄,確認是否有任何錯誤或資訊可能導致後端伺服器突然終止連線。如果發現任何錯誤/資訊,請前往「Resolution」,並在後端伺服器中適當修正問題。
  4. 如果在後端伺服器中找不到錯誤或資訊,請在訊息處理器上收集 tcpdump 輸出內容:
    1. 如果後端伺服器主機只有一個 IP 位址,請使用下列指令:
      tcpdump -i any -s 0 host IP_ADDRESS -w FILE_NAME
      
    2. 如果後端伺服器主機有多個 IP 位址,請使用下列指令:
      tcpdump -i any -s 0 host HOSTNAME -w FILE_NAME
      

      發生這項錯誤的原因通常是在訊息處理器傳送要求至後端伺服器後,後端伺服器會以 [FIN,ACK] 回應。

  5. 請參閱以下 tcpdump 範例。

    發生 502 Bad Gateway Error (UnexpectedEOFAtTarget) 時拍攝的 tcpdump 範例

  6. TCPDump 輸出內容中,您注意到下列事件順序如下:
    1. 在封包 985 中,訊息處理器會將 API 要求傳送至後端伺服器。
    2. 在封包 986 中,後端伺服器會立即以 [FIN,ACK] 回應。
    3. 在封包 987 中,訊息處理器會以 [FIN,ACK] 回應後端伺服器。
    4. 最終,連線雙方都會使用 [ACK][RST] 關閉連線。
    5. 由於後端伺服器傳送 [FIN,ACK],因此在訊息處理器上發生 java.io.EOFException: eof unexpected 例外狀況。
  7. 如果後端伺服器發生網路問題,就可能發生這種情況。請網路作業團隊進一步調查這個問題。

解析度

妥善修正後端伺服器上的問題。

如果問題仍未解決,您需要我們協助排解 502 Bad Gateway Error 問題,或懷疑問題在 Edge 中發生問題,請與 Apigee Edge 支援團隊聯絡。

原因:設定保持運作逾時設定不正確

在診斷這個原因是否為 502 錯誤的原因,請先詳閱下列概念。

Apigee 中的永久連線

根據預設,Apigee (且與 HTTP/1.1 標準相同) 會在與目標後端伺服器通訊時,使用永久連線。永久連線可以允許重複使用已建立的 TCP 和 (如適用) 的 TLS/SSL 連線,藉此提升效能,進而降低延遲負擔。連線持續時間的持續時間可透過屬性「保持運作逾時」 (keepalive.timeout.millis) 控制。

後端伺服器和 Apigee 訊息處理者都會使用即時逾時功能,以保持連線開啟。在保持運作逾時持續時間內收到任何資料後,後端伺服器或訊息處理者可以關閉彼此的連線。

根據預設,部署至 Apigee 中的訊息處理者的 API Proxy 會將保持運作逾時設為 60s,除非遭到覆寫。如果未收到 60s 的資料,Apigee 將會關閉與後端伺服器的連線。後端伺服器也會維持運作中的逾時時間,一旦過期,後端伺服器就會關閉與訊息處理器的連線。

不正確保持運作逾時設定的影響

如果 Apigee 或後端伺服器設定的保留有效逾時設定有誤,可能會導致競爭狀況,導致後端伺服器針對資源的要求傳送非預期的 End Of File (FIN)

舉例來說,如果在 API Proxy 或訊息處理器中設定保持運作逾時,且值大於或等於上游後端伺服器逾時,就可能會發生以下競爭狀況。也就是說,如果訊息處理器要到後端伺服器保持運作逾時的門檻非常接近時未收到任何資料,就會發出要求,並使用現有的連線將要求傳送至後端伺服器。這可能導致 502 Bad Gateway,因為非預期的 EOF 錯誤,如下所述:

  1. 假設訊息處理器和後端伺服器設定的保持有效逾時時間是 60 秒,且前一個訊息處理器提供前一個要求後的 59 秒內,都沒有收到新的要求。
  2. 訊息處理器會使用現有的連線 (因為保持運作逾時尚未經過),處理 59 秒內傳入的要求,並將要求傳送至後端伺服器。
  3. 不過,在要求抵達後端伺服器之前,後端伺服器的保持運作逾時門檻已超出上限。
  4. 訊息處理器對某項資源的要求正在傳輸中,但後端伺服器會傳送 FIN 封包至訊息處理器來嘗試關閉連線。
  5. 在訊息處理器等待接收資料時,訊息處理器會接收非預期的 FIN,並終止連線。
  6. 這會導致 Unexpected EOF,接著訊息處理器會傳回 502 給用戶端。

在本例中,我們發現 502 錯誤是因為訊息處理器和後端伺服器都設定了 60 秒的保持運作逾時值。同樣地,如果訊息處理器保持運作逾時設定的值高於後端伺服器上,就會發生這個問題。

診斷

  1. 如果您是公有雲使用者
    1. 使用 API 監控或追蹤記錄工具 (如常見診斷步驟所述),並確認您已完成以下這兩項設定:
      • 錯誤代碼: messaging.adaptors.http.flow.UnexpectedEOFAtTarget
      • 錯誤來源: target
    2. 詳情請參閱使用 tcpdump
  2. 如果您是 Private Cloud 使用者
    1. 使用追蹤工具NGINX 存取記錄檔,決定 502 錯誤的訊息 ID、錯誤代碼和錯誤來源。
    2. 在訊息處理器記錄
      (/opt/apigee/var/log/edge-message-processor/logs/system.log) 中搜尋郵件 ID。
    3. 您會看到 java.io.EOFEXception: eof unexpected,如下所示:
      2020-11-22 14:42:39,917 org:myorg env:prod api:myproxy rev:1 messageid:myorg-opdk-dc1-node2-17812-56001-1  NIOThread@1 ERROR HTTP.CLIENT - HTTPClient$Context$3.onException() :  ClientChannel[Connected: Remote:51.254.225.9:80 Local:10.154.0.61:35326]@12972 useCount=7 bytesRead=0 bytesWritten=159 age=7872ms  lastIO=479ms  isOpen=true.onExceptionRead exception: {}
              java.io.EOFException: eof unexpected
              at com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:45)
              at com.apigee.nio.channels.InputChannel.read(InputChannel.java:103)
              at com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:80)
              at com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(NIOSupport.java:51)
              at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:220)
      
    4. java.io.EOFException: eof unexpected 錯誤表示訊息處理器在等待從後端伺服器讀取回應時收到 EOF
    5. 上述錯誤訊息中的 useCount=7 屬性表示訊息處理器重複使用這個連線約七次,而 bytesWritten=159 屬性表示訊息處理者已將 159 個位元組的要求酬載傳送至後端伺服器。但在意外的 EOF 發生時,它收到了零位元組的資料。
    6. 這表示訊息處理器已多次重複使用相同的連線,在這種情況下,原因是在收到任何資料前就傳送資料,但之後不久才會收到 EOF。這表示後端伺服器的保持運作逾時時間很有可能短於或等於 API Proxy 中設定的即時逾時。

      您可以依照下方說明,使用 tcpdump 進一步調查問題。

使用 tcpdump

  1. 使用下列指令在後端伺服器擷取 tcpdump
    tcpdump -i any -s 0 host MP_IP_Address -w File_Name
    
  2. 分析擷取的 tcpdump

    以下是 tcpdump 輸出內容範例:

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

    1. 5992, 封包中,後端伺服器收到 GET 要求。
    2. 在「6064」封包中,它以 200 OK. 回應
    3. 在封包 6084 中,後端伺服器收到另一個 GET 要求。
    4. 在「6154」封包中,它以 200 OK 回應。
    5. 在封包 6228 中,後端伺服器收到第三個 GET 要求。
    6. 這次,後端伺服器會將 FIN, ACK 傳回至訊息處理器 (封包 6285),藉此關閉連線。

    在本例中,同一個連線已成功重複使用兩次,但在第三次要求中,後端伺服器會關閉連線,而訊息處理器正在等候後端伺服器的資料。這表示後端伺服器的保持運作逾時時間很可能較短或等於 API Proxy 中設定的值。如要驗證這一點,請參閱「比較 Apigee 和後端伺服器的保持運作逾時」。

比較 Apigee 和後端伺服器的保持運作逾時

  1. 根據預設,Apigee 的保持運作逾時屬性值預設為 60 秒。
  2. 不過,您可能已覆寫 API Proxy 中的預設值。您可以在失敗的 API Proxy 中查看造成 502 錯誤的特定 TargetEndpoint 定義,來確認這一點。

    TargetEndpoint 設定範例:

    <TargetEndpoint name="default">
      <HTTPTargetConnection>
        <URL>https://mocktarget.apigee.net/json</URL>
        <Properties>
          <Property name="keepalive.timeout.millis">30000</Property>
        </Properties>
      </HTTPTargetConnection>
    </TargetEndpoint>
    

    在上述範例中,系統以 30 秒 (30000 毫秒) 的值覆寫了保持運作逾時屬性。

  3. 接著,檢查後端伺服器上設定的「保持運作逾時」屬性。假設您將後端伺服器設為 25 seconds 的值。
  4. 如果您確定 Apigee 上的保持運作逾時屬性值高於後端伺服器上「保持運作逾時」屬性的值 (如上例所示),就是導致 502 錯誤的原因。

解析度

確保 Apigee (在 API Proxy 和訊息處理器元件中) 的保持運作逾時屬性一律低於後端伺服器上的值。

  1. 決定後端伺服器上保持運作逾時的值。
  2. 按照 設定訊息處理器的保持運作逾時步驟,在 API Proxy 或訊息處理器中,為保持運作逾時屬性設定適當的值,使保持運作逾時屬性低於後端伺服器設定的值。

如果問題仍未解決,請參閱「必須收集診斷資訊」。

最佳做法

強烈建議您將下游元件的即時逾時門檻一律低於上游伺服器所設定的有效逾時門檻,以免發生這類競爭狀況和 502 錯誤。每個下游躍點應低於每個上游躍點。在 Apigee Edge 中,建議您遵循下列準則:

  1. 用戶端保持運作逾時的時間應小於邊緣路由器的即時逾時。
  2. 邊緣路由器保持的運作逾時時間應小於訊息處理器維持運作逾時的時間。
  3. 訊息處理器保持運作逾時,應小於目標伺服器維持運作逾時。
  4. 如果您在 Apigee 的前或後方有其他躍點,則應套用相同的規則。您應一律將其保留為下游用戶端以關閉上游連線的工作。

必須收集診斷資訊

如果按照上述指示操作後仍無法解決問題,請收集下列診斷資訊,然後與 Apigee Edge 支援團隊聯絡。

如果您是公開雲端使用者,請提供下列資訊:

  • 機構名稱
  • 環境名稱
  • API Proxy 名稱
  • 完成 curl 指令以重現 502 錯誤
  • 內含 502 Bad Gateway - Unexpected EOF 錯誤要求的追蹤檔案
  • 如果目前未在 502 錯誤發生,請提供過去 502 錯誤發生時的時區資訊。

如果您是 Private Cloud 使用者,請提供下列資訊:

  • 觀察失敗要求的完整錯誤訊息
  • 您要觀察到 502 錯誤的機構、環境名稱和 API Proxy 名稱
  • API Proxy 套裝組合
  • 內含 502 Bad Gateway - Unexpected EOF 錯誤要求的追蹤檔案
  • NGINX 存取記錄檔
    /opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
  • 訊息處理器記錄
    /opt/apigee/var/log/edge-message-processor/logs/system.log
  • 發生 502 錯誤時,包含時區資訊的時間範圍
  • 系統會在訊息處理器或後端伺服器上收集 Tcpdumps,或在發生錯誤時收集兩者