502 閘道錯誤意外 EOF

您目前查看的是 Apigee Edge 說明文件。
前往 Apigee X 說明文件
info

問題

用戶端應用程式會收到 HTTP 狀態碼 502,以及訊息 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 公有和私有雲使用者
後端伺服器發生 EOFException 後端伺服器可能會突然傳送 EOF。 僅限 Edge Private Cloud 使用者
Keep-alive 超時設定有誤 Apigee 和後端伺服器上設定的 Keep-Alive 超時時間有誤。 Edge 公有和私有雲使用者

常見的診斷步驟

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

API Monitoring

如要使用 API 監控功能診斷錯誤,請按照下列步驟操作:

使用 API 監控功能,按照「調查問題」一文的步驟,調查 502 錯誤。也就是:

  1. 前往「調查」資訊主頁。
  2. 在下拉式選單中選取「狀態碼」 ,並確認選取發生 502 錯誤的正確時間範圍。
  3. 如果看到大量 502 錯誤,請點選矩陣中的方塊。
  4. 在右側,按一下 502 錯誤的「查看記錄」,這類錯誤看起來會像這樣:
  5. 這裡會顯示下列資訊:

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

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

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

追蹤工具

如要使用「追蹤」工具診斷錯誤,請按照下列步驟操作:

  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-source target
    X-Apigee.fault-code messaging.adaptors.http.flow.UnexpectedEOFAtTarget

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

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-source target
    X-Apigee.fault-code messaging.adaptors.http.flow.UnexpectedEOFAtTarget

    以下是目標伺服器導致 502 錯誤的範例項目:

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

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

目標伺服器未正確設定,無法支援傳輸層安全標準 (TLS)/安全資料傳輸層 (SSL) 連線。

診斷

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

      那麼這個問題很可能是目標伺服器設定錯誤所致。

  4. 使用 Edge 管理 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,方法是加入 SSLInfo 屬性,並將 enabled 旗標設為 true,如下所示:
      <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. 您需要設定適當的 SSLInfo 屬性,並使用 ClientAuthEnabledKeystoreKeyAliasTruststore 旗標,如下所示:
      <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]"

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

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

  3. 檢查後端伺服器記錄,看看是否有任何錯誤或資訊,可能導致後端伺服器突然終止連線。如果發現任何錯誤/資訊,請前往「解決方法」,並在後端伺服器中適當修正問題。
  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],因此您會在 Message Processor 上取得例外狀況 java.io.EOFException: eof unexpected 例外狀況。
  7. 如果後端伺服器發生網路問題,就可能發生這種情況。請與網路營運團隊聯絡,進一步調查這個問題。

解析度

在後端伺服器上適當修正問題。

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

原因:存活逾時設定有誤

在診斷 502 錯誤是否為此原因之前,請先瞭解下列概念。

Apigee 中的永久連線

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

後端伺服器和 Apigee 訊息處理器 都會使用保持連線逾時,彼此保持連線開啟。如果超過 keep-alive 逾時時間,後端伺服器或訊息處理器即可關閉與對方的連線。

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

不正確的保持連線逾時設定會造成什麼影響

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

舉例來說,如果 API Proxy 或訊息處理器內設定的 keep-alive 逾時值大於或等於上游後端伺服器的逾時值,則可能會發生下列競爭狀況。也就是說,如果訊息處理器在後端伺服器保持連線逾時的門檻附近才收到資料,系統會透過現有連線傳送要求至後端伺服器。這可能會導致 502 Bad Gateway,因為發生非預期的 EOF 錯誤,如下所述:

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

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

診斷

  1. 如果您是公有雲使用者
    1. 使用 API Monitoring 或 Trace 工具 (如「常見診斷步驟」所述),確認您已進行下列兩項設定:
      • 故障代碼: messaging.adaptors.http.flow.UnexpectedEOFAtTarget
      • 錯誤來源: target
    2. 如要進一步調查,請參閱「使用 tcpdump」。
  2. 如果您是 Private Cloud 使用者
    1. 使用追蹤工具NGINX 存取記錄,判斷 502 錯誤的訊息 ID、錯誤代碼和錯誤來源。
    2. 在訊息處理器記錄中搜尋郵件 ID(
      )。/opt/apigee/var/log/edge-message-processor/logs/system.log
    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 和後端伺服器上的 Keep-Alive 超時

  1. 根據預設,Apigee 會將「保持連線逾時」屬性的值設為 60 秒。
  2. 不過,您可能已在 API Proxy 中覆寫預設值。 如要確認這點,請檢查導致 502 錯誤的 API Proxy 中,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 或訊息處理器中,為 Keep-Alive 逾時屬性設定適當的值,使 Keep-Alive 逾時屬性低於後端伺服器上設定的值。如需相關步驟,請參閱「 在訊息處理器上設定 Keep-Alive 逾時」。

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

最佳做法

強烈建議下游元件的連線存留逾時門檻一律要低於上游伺服器設定的值,以免發生這類競爭條件和 502 錯誤。每個下游躍點應低於每個上游躍點。在 Apigee Edge 中,建議您遵循下列準則:

  1. 用戶端存留逾時時間應小於 Edge 路由器存留逾時時間。
  2. Edge 路由器保持連線逾時時間應小於訊息處理器保持連線逾時時間。
  3. 訊息處理器的連線存續逾時時間應小於目標伺服器的連線存續逾時時間。
  4. 如果 Apigee 前後有其他躍點,也應套用相同規則。 您應一律將關閉上游連線的責任留給下游用戶端。

必須收集診斷資訊

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

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

  • 機構名稱
  • 環境名稱
  • API Proxy 名稱
  • 完成 curl 指令,重現 502 錯誤
  • 包含要求和 502 Bad Gateway - Unexpected EOF 錯誤的追蹤記錄檔
  • 如果目前沒有發生 502 錯誤,請提供過去發生 502 錯誤的時間範圍和時區資訊。

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

  • 失敗要求顯示的完整錯誤訊息
  • 您觀察到錯誤的機構、環境和 API Proxy 名稱 502
  • 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收集的資料,或錯誤發生時訊息處理器和後端伺服器收集的資料。