502 EOF เกตเวย์ไม่ถูกต้อง

คุณกำลังดูเอกสารประกอบของ Apigee Edge
ไปที่เอกสารประกอบของ Apigee X
ข้อมูล

ลักษณะปัญหา

แอปพลิเคชันไคลเอ็นต์จะได้รับรหัสสถานะ 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 Public และ Private Cloud
EOFException จากเซิร์ฟเวอร์แบ็กเอนด์ เซิร์ฟเวอร์แบ็กเอนด์อาจส่ง EOF อย่างกะทันหัน ผู้ใช้ Edge Private Cloud เท่านั้น
กำหนดค่าไม่ถูกต้องสำหรับระยะหมดเวลาของ Keep Alive กำหนดค่าระยะหมดเวลาของ Apigee และเซิร์ฟเวอร์แบ็กเอนด์ไว้ไม่ถูกต้อง ผู้ใช้ Edge Public และ Private Cloud

ขั้นตอนการวินิจฉัยทั่วไป

ในการวินิจฉัยข้อผิดพลาด คุณสามารถใช้วิธีการใดก็ได้ต่อไปนี้

การตรวจสอบ API

วิธีวินิจฉัยข้อผิดพลาดโดยใช้ API Monitoring

เมื่อใช้การตรวจสอบ API คุณจะสามารถตรวจสอบข้อผิดพลาด 502 โดยทำตามขั้นตอนที่อธิบายไว้ในตรวจสอบปัญหา โดยการ

  1. ไปที่หน้าแดชบอร์ดตรวจสอบ
  2. เลือกรหัสสถานะ ในเมนูแบบเลื่อนลง แล้วตรวจสอบว่าได้เลือกช่วงเวลาที่ถูกต้องเมื่อเกิดข้อผิดพลาด 502 รายการ
  3. คลิกช่องในเมทริกซ์เมื่อคุณเห็นข้อผิดพลาด 502 จำนวนมาก
  4. ทางด้านขวา ให้คลิกดูบันทึกเพื่อหาข้อผิดพลาด 502 รายการที่อาจมีลักษณะดังต่อไปนี้
  5. เราเห็นข้อมูลต่อไปนี้

    • Fault Source คือ target
    • Fault Code คือ messaging.adaptors.http.UnexpectedEOFAtTarget

ซึ่งแสดงให้เห็นว่าข้อผิดพลาด 502 เกิดจากเป้าหมายเนื่องจาก EOF ที่ไม่คาดคิด

นอกจากนี้ ให้จดบันทึก Request Message ID สำหรับข้อผิดพลาด 502 เพื่อทำการตรวจสอบเพิ่มเติม

เครื่องมือการติดตาม

วิธีวินิจฉัยข้อผิดพลาดโดยใช้เครื่องมือติดตาม

  1. เปิดใช้ เซสชันการติดตามและเรียก API เพื่อจำลองปัญหา 502 Bad Gateway
  2. เลือกคำขอที่ล้มเหลว 1 รายการและตรวจสอบการติดตาม
  3. ไปยังระยะต่างๆ ของการติดตามและค้นหาตำแหน่งที่ความล้มเหลวเกิดขึ้น
  4. คุณควรเห็นการทำงานล้มเหลวหลังจากที่ส่งคำขอไปยังเซิร์ฟเวอร์ปลายทางดังที่แสดงด้านล่าง

    alt_text

    alt_text

  5. ระบุค่าของ X-Apigee.fault-source และ X-Apigee.fault-code ในระยะ AX (บันทึกข้อมูล Analytics) ในการติดตาม

    หากค่าของ X-Apigee.fault-source และ X-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. ค้นหาข้อผิดพลาด 502 สำหรับพร็อกซี API ที่ระบุในช่วงเวลาที่เจาะจง (หากปัญหาเกิดขึ้นในอดีต) หรือหาคำขอใดก็ตามที่ยังคงไม่สำเร็จโดยใช้ 502
  3. หากมีข้อผิดพลาด 502 ให้ตรวจสอบว่าข้อผิดพลาดดังกล่าวเกิดจากเป้าหมายที่ส่ง Unexpected EOF หรือไม่ หากค่าของ X-Apigee.fault-source และ X- Apigee.fault-code ตรงกับค่าที่แสดงในตารางด้านล่าง ข้อผิดพลาด 502 เกิดจากเป้าหมายปิดการเชื่อมต่อโดยไม่คาดคิด
    ส่วนหัวการตอบกลับ ค่า
    X-Apigee.fault-source target
    โค้ด X-Apigee.fault-code messaging.adaptors.http.flow.UnexpectedEOFAtTarget

    ต่อไปนี้คือรายการตัวอย่างที่แสดงข้อผิดพลาด 502 ที่เกิดจากเซิร์ฟเวอร์เป้าหมาย

นอกจากนี้ ให้จดรหัสข้อความสำหรับข้อผิดพลาด 502 ไว้เพื่อตรวจสอบเพิ่มเติม

สาเหตุ: เซิร์ฟเวอร์เป้าหมายกำหนดค่าไม่ถูกต้อง

ไม่ได้กำหนดค่าเซิร์ฟเวอร์เป้าหมายให้รองรับการเชื่อมต่อ TLS/SSL อย่างถูกต้อง

การวินิจฉัย

  1. ใช้การตรวจสอบ API, เครื่องมือติดตาม หรือบันทึกการเข้าถึง NGINX เพื่อระบุรหัสข้อความ โค้ดข้อผิดพลาด และแหล่งที่มาของข้อผิดพลาดสำหรับข้อผิดพลาด 502
  2. เปิดใช้การติดตามใน UI สำหรับ 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 ได้รับการกำหนดค่าให้ยอมรับการเชื่อมต่อ ที่ปลอดภัย (HTTPS) บนพอร์ต 443 อย่างไรก็ตาม หากคุณดูคำจำกัดความเซิร์ฟเวอร์เป้าหมาย จะไม่มีแอตทริบิวต์/แฟล็กอื่นๆ ที่ระบุว่าเป็นการกำหนดค่าสำหรับการเชื่อมต่อที่ปลอดภัย ซึ่งทำให้ Edge ถือว่าคำขอ API ที่ส่งไปยังเซิร์ฟเวอร์เป้าหมายที่เจาะจงเป็นคำขอ HTTP (ไม่ปลอดภัย) ดังนั้น Edge จะไม่เริ่มกระบวนการแฮนด์เชค SSL กับเซิร์ฟเวอร์เป้าหมายนี้

    เนื่องจากเซิร์ฟเวอร์เป้าหมายถูกกำหนดค่าให้ยอมรับเฉพาะคำขอ HTTPS (SSL) ใน 443 เซิร์ฟเวอร์จะปฏิเสธคำขอจาก Edge หรือปิดการเชื่อมต่อ ด้วยเหตุนี้ คุณจึงได้รับข้อผิดพลาด UnexpectedEOFAtTarget ในระบบประมวลผลข้อความ ผู้ประมวลผลข้อความจะส่ง 502 Bad Gateway เป็นการตอบกลับไปยังไคลเอ็นต์

ความละเอียด

ตรวจสอบให้แน่ใจเสมอว่าได้กำหนดค่าเซิร์ฟเวอร์เป้าหมายอย่างถูกต้องตามความต้องการของคุณ

สำหรับตัวอย่างที่แสดงให้เห็นด้านบน หากต้องการส่งคำขอไปยังเซิร์ฟเวอร์เป้าหมายที่ปลอดภัย (HTTPS/SSL) คุณต้องใส่แอตทริบิวต์ SSLInfo โดยตั้งค่าสถานะ enabled เป็น true แม้ว่าระบบจะได้รับอนุญาตให้เพิ่มแอตทริบิวต์ SSLInfo สำหรับเซิร์ฟเวอร์เป้าหมายในคำจำกัดความปลายทางเป้าหมาย แต่เราขอแนะนำให้เพิ่มแอตทริบิวต์ SSLInfo เป็นส่วนหนึ่งของคำจำกัดความเซิร์ฟเวอร์เป้าหมายเพื่อหลีกเลี่ยงความสับสน

  1. หากบริการแบ็กเอนด์ต้องใช้การสื่อสาร SSL ทางเดียว ให้ทําดังนี้
    1. คุณต้องเปิดใช้ TLS/SSL ในคำจำกัดความ TargetServer โดยรวมแอตทริบิวต์ SSLInfo ที่มีการตั้งค่าแฟล็ก enabled เป็น "จริง" ดังที่แสดงด้านล่าง
      <TargetServer name="mocktarget">
        <Host>mocktarget.apigee.net</Host>
        <Port>443</Port>
        <IsEnabled>true</IsEnabled>
        <SSLInfo>
            <Enabled>true</Enabled>
        </SSLInfo>
      </TargetServer>
      
    2. หากต้องการตรวจสอบใบรับรองของเซิร์ฟเวอร์เป้าหมายใน Edge เราจะต้องใส่ Truststore (ที่มีใบรับรองของเซิร์ฟเวอร์เป้าหมาย) ด้วยดังที่แสดงด้านล่าง
      <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 แบบ 2 ทาง ให้ทําดังนี้
    1. คุณต้องมีแอตทริบิวต์ SSLInfo ที่มีการตั้งค่าแฟล็ก ClientAuthEnabled, Keystore, KeyAlias และ Truststore อย่างเหมาะสมตามที่แสดงด้านล่าง
      <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
  2. ตรวจสอบบันทึกตัวประมวลผลข้อความ (/opt/apigee/var/log/edge-message-processor/logs/system.log) และค้นหาเพื่อดูว่าคุณมี eof unexpected สำหรับ API ที่เฉพาะเจาะจงหรือไม่ หรือคุณมี messageid ที่ไม่ซ้ำกันสำหรับคำขอ API ดังกล่าว คุณก็ค้นหาได้

    ตัวอย่างสแต็กเทรซข้อยกเว้นจากบันทึกของผู้ประมวลผลข้อความ

    "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. ตรวจสอบบันทึกเซิร์ฟเวอร์แบ็กเอนด์และดูว่ามีข้อผิดพลาดหรือข้อมูลที่อาจทําให้เซิร์ฟเวอร์แบ็กเอนด์ยุติการเชื่อมต่ออย่างกะทันหันหรือไม่ หากพบข้อผิดพลาด/ข้อมูล ให้ไปที่การแก้ปัญหาแล้วแก้ไขปัญหาที่เหมาะสมในเซิร์ฟเวอร์แบ็กเอนด์
  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 ต่อไปนี้

    ตัวอย่าง tcpdump ที่ถ่ายเมื่อ 502 Bad Gateway Error (UnexpectedEOFAtTarget) เกิดขึ้น

  6. จากเอาต์พุต TCPDump คุณจะสังเกตเห็นลําดับเหตุการณ์ต่อไปนี้
    1. ในแพ็กเก็ต 985 ตัวประมวลผลข้อความจะส่งคำขอ API ไปยังเซิร์ฟเวอร์แบ็กเอนด์
    2. ในแพ็กเก็ต 986 เซิร์ฟเวอร์แบ็กเอนด์จะตอบกลับด้วย [FIN,ACK] ทันที
    3. ในแพ็กเก็ต 987 ตัวประมวลผลข้อความจะตอบกลับด้วย [FIN,ACK] ไปยังเซิร์ฟเวอร์แบ็กเอนด์
    4. ในที่สุดก็ปิดการเชื่อมต่อด้วย [ACK] และ [RST] จากทั้ง 2 ฝั่ง
    5. เนื่องจากเซิร์ฟเวอร์แบ็กเอนด์ส่ง [FIN,ACK] คุณจึงได้รับข้อยกเว้น java.io.EOFException: eof unexpected ยกเว้นในเครื่องมือประมวลผลข้อความ
  7. ซึ่งอาจเกิดจากปัญหาเครือข่ายในเซิร์ฟเวอร์แบ็กเอนด์ ให้ทีมปฏิบัติการเครือข่ายของคุณตรวจสอบปัญหานี้เพิ่มเติม

ความละเอียด

แก้ไขปัญหาในเซิร์ฟเวอร์แบ็กเอนด์อย่างเหมาะสม

หากปัญหายังคงอยู่และคุณต้องการความช่วยเหลือในการแก้ปัญหา 502 Bad Gateway Error หรือสงสัยว่าเป็นปัญหาใน Edge โปรดติดต่อทีมสนับสนุนของ Apigee Edge

สาเหตุ: กำหนดค่า Keep ของระยะหมดเวลาไม่ถูกต้อง

ก่อนที่จะวิเคราะห์ว่านี่คือสาเหตุของข้อผิดพลาด 502 หรือไม่ โปรดอ่านแนวคิดต่อไปนี้อย่างละเอียด

การเชื่อมต่อถาวรใน Apigee

โดยค่าเริ่มต้น Apigee (และที่เป็นไปตามมาตรฐาน HTTP/1.1) จะใช้การเชื่อมต่อถาวรเมื่อสื่อสารกับเซิร์ฟเวอร์แบ็กเอนด์เป้าหมาย การเชื่อมต่อแบบถาวรช่วยเพิ่มประสิทธิภาพได้โดยการอนุญาตให้นำการเชื่อมต่อ TLS/SSL ที่สร้างขึ้นแล้วและ (หากมี) มาใช้ซ้ำ ซึ่งจะช่วยลดค่าใช้จ่ายของเวลาในการตอบสนอง ระยะเวลาในการคงการเชื่อมต่อจะต้องถูกควบคุมผ่านพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep Alive (keepalive.timeout.millis)

ทั้งเซิร์ฟเวอร์แบ็กเอนด์และ Apigee Message Processor จะใช้ระยะหมดเวลาแบบเก็บการทำงานไว้เพื่อเปิดการเชื่อมต่อระหว่างกัน เมื่อได้รับข้อมูลภายในระยะหมดเวลาของ Keep Alive แล้ว เซิร์ฟเวอร์แบ็กเอนด์หรือผู้ประมวลผลข้อมูลข้อความจะปิดการเชื่อมต่อกับอีกเซิร์ฟเวอร์หนึ่งได้

พร็อกซี API ที่ทำให้ใช้งานได้กับเครื่องมือประมวลผลข้อความใน Apigee ตามค่าเริ่มต้นแล้ว การตั้งค่าระยะหมดเวลาของ Keep จะเป็น 60s เว้นแต่จะมีการลบล้าง เมื่อไม่มีรับข้อมูลของ 60s แล้ว Apigee จะปิดการเชื่อมต่อกับเซิร์ฟเวอร์แบ็กเอนด์ เซิร์ฟเวอร์แบ็กเอนด์จะยังคงรักษาระยะหมดเวลาให้คงการทำงานไว้ และเมื่อหมดอายุ เซิร์ฟเวอร์แบ็กเอนด์จะปิดการเชื่อมต่อกับเครื่องมือประมวลผลข้อความ

ผลของการกำหนดค่าระยะหมดเวลาของ Keep Alive ที่ไม่ถูกต้อง

หากกำหนดค่า Apigee หรือเซิร์ฟเวอร์แบ็กเอนด์โดยมีระยะหมดเวลาของ Keep Alive ที่ไม่ถูกต้อง จะทําให้เกิดเงื่อนไขการแข่งซึ่งทำให้เซิร์ฟเวอร์แบ็กเอนด์ส่ง End Of File (FIN) ที่ไม่คาดคิดเพื่อตอบกลับคําขอทรัพยากร

ตัวอย่างเช่น หากมีการกำหนดค่าระยะหมดเวลาของ Keep alive ภายในพร็อกซี API หรือผู้ประมวลผลข้อมูลข้อความที่มีค่ามากกว่าหรือเท่ากับระยะหมดเวลาของเซิร์ฟเวอร์แบ็กเอนด์ของอัปสตรีม เงื่อนไขเชื้อชาติต่อไปนี้อาจเกิดขึ้นได้ กล่าวคือ หากผู้ประมวลผลข้อความไม่ได้รับข้อมูลใดๆ จนกว่าจะใกล้ถึงเกณฑ์ของเซิร์ฟเวอร์แบ็กเอนด์ที่จะคงระยะหมดเวลาไว้ คำขอจะผ่านเข้ามาและส่งไปยังเซิร์ฟเวอร์แบ็กเอนด์โดยใช้การเชื่อมต่อที่มีอยู่ ซึ่งอาจนำไปสู่ 502 Bad Gateway เนื่องจากข้อผิดพลาด EOF ที่ไม่คาดคิดตามที่อธิบายไว้ด้านล่าง

  1. สมมติว่าระยะหมดเวลาของ Keep alive ที่ตั้งค่าทั้งในตัวประมวลผลข้อความและเซิร์ฟเวอร์แบ็กเอนด์คือ 60 วินาที และไม่มีคำขอใหม่จนกว่าจะ 59 วินาทีหลังจากที่ผู้ประมวลผลข้อความที่ระบุส่งคำขอก่อนหน้า
  2. ตัวประมวลผลข้อความจะดำเนินการต่อและประมวลผลคำขอที่เข้ามาในวินาทีที่ 59 โดยใช้การเชื่อมต่อที่มีอยู่ (เนื่องจากยังไม่หมดเวลาของ Keep Alive) และส่งคำขอไปยังเซิร์ฟเวอร์แบ็กเอนด์
  3. แต่ก่อนที่คำขอจะมาถึงเซิร์ฟเวอร์แบ็กเอนด์ เกินเกณฑ์ระยะหมดเวลาของ Keep Alive ในเซิร์ฟเวอร์แบ็กเอนด์แล้ว
  4. คำขอทรัพยากรของผู้ประมวลผลข้อความอยู่ระหว่างดำเนินการ แต่เซิร์ฟเวอร์แบ็กเอนด์พยายามปิดการเชื่อมต่อโดยส่งแพ็กเก็ต FIN ไปยังผู้ประมวลผลข้อความ
  5. ขณะที่ผู้ประมวลผลข้อความกำลังรอรับข้อมูล แต่จะได้รับ FIN ที่ไม่คาดคิดแทนและการเชื่อมต่อจะสิ้นสุดลง
  6. ซึ่งส่งผลให้เกิด Unexpected EOF และจากนั้นผู้ประมวลผลข้อความจะส่ง 502 กลับไปยังไคลเอ็นต์

ในกรณีนี้ เราพบว่าเกิดข้อผิดพลาด 502 เนื่องจากมีการกำหนดค่าการหมดเวลาของ Keep Alive ซึ่งก็คือ 60 วินาทีเหมือนกันทั้งในเครื่องมือประมวลผลข้อความและเซิร์ฟเวอร์แบ็กเอนด์ ในทำนองเดียวกัน ปัญหานี้อาจเกิดขึ้นได้หากมีการกำหนดค่าค่าการหมดเวลาของ Keep Alive ในเครื่องประมวลผลข้อความสูงกว่าในเซิร์ฟเวอร์แบ็กเอนด์

การวินิจฉัย

  1. หากคุณเป็นผู้ใช้ระบบคลาวด์สาธารณะ ให้ทำดังนี้
    1. ใช้เครื่องมือ API Monitoring หรือ Trace (ตามที่อธิบายไว้ในขั้นตอนการวิเคราะห์ทั่วไป) และตรวจสอบว่าคุณมีการตั้งค่าทั้ง 2 อย่างต่อไปนี้แล้ว
      • รหัสข้อผิดพลาด: messaging.adaptors.http.flow.UnexpectedEOFAtTarget
      • แหล่งที่มาของข้อผิดพลาด: target
    2. โปรดไปที่การใช้ tcpdump เพื่อตรวจสอบเพิ่มเติม
  2. หากคุณเป็นผู้ใช้ Private Cloud ให้ทำดังนี้
    1. ใช้เครื่องมือติดตามหรือบันทึกการเข้าถึง NGINX เพื่อระบุรหัสข้อความ รหัสข้อผิดพลาด และแหล่งที่มาของข้อผิดพลาดสำหรับข้อผิดพลาด 502
    2. ค้นหารหัสข้อความในบันทึกของตัวประมวลผลข้อความ
      (/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 ในข้อความแสดงข้อผิดพลาดข้างต้นบ่งบอกว่าผู้ประมวลผลข้อความได้ใช้การเชื่อมต่อนี้ซ้ำประมาณ 7 ครั้ง และแอตทริบิวต์ bytesWritten=159 ระบุว่าผู้ประมวลผลข้อความได้ส่งเพย์โหลดคำขอขนาด 159 ไบต์ไปยังเซิร์ฟเวอร์แบ็กเอนด์ แต่ได้รับกลับมา 0 ไบต์เมื่อ EOF ที่ไม่คาดคิดเกิดขึ้น
    6. ซึ่งแสดงให้เห็นว่าผู้ประมวลผลข้อความได้ใช้การเชื่อมต่อเดิมซ้ำหลายครั้ง และในโอกาสนี้ระบบได้ส่งข้อมูล แต่หลังจากนั้นไม่นานก็ได้รับ EOF ก่อนที่จะได้รับข้อมูลใดๆ ซึ่งหมายความว่ามีโอกาสสูงที่ระยะหมดเวลา Keep-alive ของเซิร์ฟเวอร์แบ็กเอนด์จะสั้นกว่าหรือเท่ากับค่าที่ตั้งไว้ในพร็อกซี API

      คุณตรวจสอบเพิ่มเติมได้โดยใช้ 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 รายการที่ 3
    6. ในครั้งนี้ เซิร์ฟเวอร์แบ็กเอนด์จะส่ง FIN, ACK ไปยัง Message Processor (แพ็กเก็ต 6285) เพื่อเริ่มการปิดการเชื่อมต่อ

    ในตัวอย่างนี้มีการใช้การเชื่อมต่อเดียวกันซ้ำ 2 ครั้งสำเร็จ แต่ในคำขอที่ 3 เซิร์ฟเวอร์แบ็กเอนด์เริ่มปิดการเชื่อมต่อในขณะที่ผู้ประมวลผลข้อความกำลังรอข้อมูลจากเซิร์ฟเวอร์แบ็กเอนด์ ซึ่งแสดงให้เห็นว่าระยะหมดเวลาของ Keep-alive ของเซิร์ฟเวอร์แบ็กเอนด์มีแนวโน้มที่จะสั้นกว่าหรือเท่ากับค่าที่ตั้งไว้ในพร็อกซี API หากต้องการตรวจสอบความถูกต้องนี้ โปรดดูเปรียบเทียบระยะหมดเวลาของ Keep alive ใน Apigee และเซิร์ฟเวอร์แบ็กเอนด์

เปรียบเทียบระยะหมดเวลา Keep ใน Apigee และเซิร์ฟเวอร์แบ็กเอนด์

  1. โดยค่าเริ่มต้น Apigee จะใช้ค่า 60 วินาทีสำหรับพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep alive
  2. แต่คุณอาจลบล้างค่าเริ่มต้นในพร็อกซี API ไปแล้วก็ได้ คุณยืนยันได้โดยตรวจสอบคำจำกัดความ TargetEndpoint เฉพาะในพร็อกซี API ที่ล้มเหลวโดยมีข้อผิดพลาด 502 รายการ

    ตัวอย่างการกำหนดค่า TargetEndpoint

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

    ในตัวอย่างข้างต้น ระบบจะลบล้างพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep alive ด้วยค่า 30 วินาที (30000 มิลลิวินาที)

  3. ถัดไป ให้ตรวจสอบพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep Alive ที่กําหนดค่าไว้ในเซิร์ฟเวอร์แบ็กเอนด์ สมมติว่าเซิร์ฟเวอร์แบ็กเอนด์ได้รับการกําหนดค่าด้วยค่า 25 seconds
  4. หากคุณเห็นว่าค่าของพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep alive ใน Apigee สูงกว่าค่าของพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep alive ในเซิร์ฟเวอร์แบ็กเอนด์ตามตัวอย่างข้างต้น จึงเป็นสาเหตุที่ทําให้เกิดข้อผิดพลาด 502

ความละเอียด

ตรวจสอบว่าพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep alive ต่ำกว่าเสมอใน Apigee (ในพร็อกซี API และคอมโพเนนต์ตัวประมวลผลข้อความ) เมื่อเทียบกับเซิร์ฟเวอร์แบ็กเอนด์

  1. กำหนดค่าที่ตั้งค่าให้ระยะหมดเวลาของ Keep Alive ในเซิร์ฟเวอร์แบ็กเอนด์
  2. กำหนดค่าที่เหมาะสมสำหรับพร็อพเพอร์ตี้ระยะหมดเวลาของ Keep ในพร็อกซี API หรือตัวประมวลผลข้อความเพื่อให้พร็อพเพอร์ตี้ระยะหมดเวลาของ Keep alive ต่ำกว่าค่าที่ตั้งไว้ในเซิร์ฟเวอร์แบ็กเอนด์ โดยใช้ขั้นตอนที่อธิบายไว้ใน การกำหนดค่าระยะหมดเวลาของ Keep alive ในตัวประมวลผลข้อความ

หากยังพบปัญหาอยู่ ให้ไปที่ต้องรวบรวมข้อมูลการวินิจฉัย

แนวทางปฏิบัติแนะนำ

ขอแนะนำเป็นอย่างยิ่งว่าคอมโพเนนต์ที่ดาวน์สตรีมจะมีเกณฑ์การหมดเวลาของ Keep ต่ำกว่าที่กำหนดค่าไว้ในเซิร์ฟเวอร์อัปสตรีมเสมอ เพื่อหลีกเลี่ยงเงื่อนไขการแข่งขันและข้อผิดพลาด 502 ประเภทนี้ ฮอพดาวน์สตรีมแต่ละรายการควรต่ำกว่าอัปสตรีมฮอพแต่ละรายการ แนวทางปฏิบัติที่ดีใน Apigee Edge คือการใช้หลักเกณฑ์ต่อไปนี้

  1. ระยะหมดเวลาของ Keepalive ของไคลเอ็นต์ควรน้อยกว่าระยะหมดเวลาของเราเตอร์ Edge
  2. การหมดเวลาของเราเตอร์ Edge ที่ใช้งานอยู่ควรน้อยกว่าระยะหมดเวลาของโปรแกรมประมวลผลข้อความ
  3. การหมดเวลาของตัวประมวลผลข้อความควรต่ำกว่าระยะหมดเวลาปัจจุบันของเซิร์ฟเวอร์เป้าหมาย
  4. หากคุณมีการรับส่งข้อมูลอื่นๆ อยู่ด้านหน้าหรือด้านหลัง Apigee ควรใช้กฎเดียวกัน คุณควรปล่อยให้ไคลเอ็นต์เป็นความรับผิดชอบของไคลเอ็นต์ดาวน์สตรีมที่จะต้องปิดการเชื่อมต่อกับอัปสตรีมเสมอ

ต้องรวบรวมข้อมูลการวินิจฉัย

หากปัญหายังคงอยู่แม้ว่าจะทำตามวิธีการข้างต้นแล้ว ให้รวบรวมข้อมูลการวินิจฉัยต่อไปนี้ จากนั้นติดต่อฝ่ายสนับสนุนของ Apigee Edge

หากคุณเป็นผู้ใช้ระบบคลาวด์สาธารณะ โปรดระบุข้อมูลต่อไปนี้

  • ชื่อองค์กร
  • ชื่อสภาพแวดล้อม
  • ชื่อพร็อกซี API
  • ใช้คำสั่ง curl ให้เสร็จสมบูรณ์เพื่อจำลองข้อผิดพลาด 502 ซ้ำ
  • ไฟล์การย้ายข้อมูลที่มีคำขอซึ่งมีข้อผิดพลาด 502 Bad Gateway - Unexpected EOF รายการ
  • หากข้อผิดพลาด 502 ไม่ได้เกิดขึ้นในขณะนี้ ให้ระบุระยะเวลาพร้อมข้อมูลเขตเวลาเมื่อเกิดข้อผิดพลาด 502 ในอดีต

หากคุณเป็นผู้ใช้ Private Cloud โปรดระบุข้อมูลต่อไปนี้

  • สังเกตข้อความแสดงข้อผิดพลาดสำหรับคำขอที่ไม่สำเร็จ
  • ชื่อองค์กร ชื่อสภาพแวดล้อม และชื่อพร็อกซี API ที่คุณพบข้อผิดพลาด 502 รายการ
  • กลุ่มพร็อกซี API
  • ไฟล์การย้ายข้อมูลที่มีคำขอซึ่งมีข้อผิดพลาด 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 รวบรวมไว้ในตัวประมวลผลข้อความหรือเซิร์ฟเวอร์แบ็กเอนด์ หรือทั้ง 2 อย่างเมื่อเกิดข้อผิดพลาด