ลองฟังก์ชันอะซิงโครนัสอีกครั้ง

เอกสารนี้อธิบายวิธีที่คุณสามารถขอฟังก์ชันพื้นหลังแบบอะซิงโครนัส (ไม่ใช่ HTTPS) เพื่อลองอีกครั้งเมื่อเกิดความล้มเหลว

ความหมายของการลองใหม่

Cloud Functions รับประกันการดำเนินการฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์อย่างน้อยหนึ่งครั้งสำหรับแต่ละเหตุการณ์ที่ปล่อยออกมาโดยแหล่งเหตุการณ์ ตามค่าเริ่มต้น หากการเรียกใช้ฟังก์ชันสิ้นสุดลงโดยมีข้อผิดพลาด ฟังก์ชันจะไม่ถูกเรียกใช้อีกครั้งและเหตุการณ์จะหายไป เมื่อคุณเปิดใช้งานการลองใหม่บนฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ ฟังก์ชันคลาวด์จะพยายามเรียกใช้ฟังก์ชันที่ล้มเหลวอีกครั้งจนกว่าจะเสร็จสมบูรณ์หรือหน้าต่างการลองใหม่หมดลง

สำหรับฟังก์ชันรุ่นที่ 2 หน้าต่างลองใหม่นี้จะหมดอายุหลังจาก 24 ชั่วโมง สำหรับฟังก์ชันรุ่นที่ 1 จะหมดอายุหลังจากผ่านไป 7 วัน Cloud Functions ลองใช้ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ที่สร้างขึ้นใหม่อีกครั้งโดยใช้กลยุทธ์แบ็คออฟแบบเอ็กซ์โปเนนเชียล โดยมีแบ็คออฟเพิ่มขึ้นระหว่าง 10 ถึง 600 วินาที นโยบายนี้จะนำไปใช้กับฟังก์ชันใหม่ในครั้งแรกที่คุณใช้งาน จะไม่มีผลย้อนหลังกับฟังก์ชันที่มีอยู่ซึ่งมีการใช้งานครั้งแรกก่อนที่การเปลี่ยนแปลงที่อธิบายไว้ใน บันทึกประจำรุ่นนี้ จะมีผล แม้ว่าคุณจะปรับใช้ฟังก์ชันใหม่ก็ตาม

เมื่อไม่ได้เปิดใช้งานการลองใหม่สำหรับฟังก์ชันซึ่งเป็นค่าเริ่มต้น ฟังก์ชันจะรายงานเสมอว่าดำเนินการสำเร็จ และรหัสตอบกลับ 200 OK รหัสอาจปรากฏในบันทึก สิ่งนี้จะเกิดขึ้นแม้ว่าฟังก์ชันจะพบข้อผิดพลาดก็ตาม เพื่อให้ชัดเจนเมื่อฟังก์ชันของคุณพบข้อผิดพลาด โปรด รายงานข้อผิดพลาด อย่างเหมาะสม

เหตุใดฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์จึงล้มเหลว

ในโอกาสที่เกิดขึ้นไม่บ่อยนัก ฟังก์ชันอาจออกก่อนเวลาอันควรเนื่องจากข้อผิดพลาดภายใน และตามค่าเริ่มต้น ฟังก์ชันอาจจะหรืออาจจะไม่ลองใหม่โดยอัตโนมัติ

โดยทั่วไปแล้ว ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์อาจล้มเหลวในการดำเนินการให้เสร็จสมบูรณ์เนื่องจากมีข้อผิดพลาดเกิดขึ้นในโค้ดฟังก์ชันเอง สาเหตุที่อาจเกิดขึ้น ได้แก่:

  • ฟังก์ชันนี้มีจุดบกพร่องและรันไทม์ส่งข้อยกเว้น
  • ฟังก์ชันไม่สามารถเข้าถึงจุดสิ้นสุดของบริการ หรือหมดเวลาขณะพยายามทำเช่นนั้น
  • ฟังก์ชันจงใจส่งข้อยกเว้น (เช่น เมื่อพารามิเตอร์ไม่ผ่านการตรวจสอบ)
  • ฟังก์ชัน Node.js ส่งคืนสัญญาที่ถูกปฏิเสธหรือส่งผ่านค่าที่ไม่ใช่ null ไปยังการโทรกลับ

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

เปิดหรือปิดการลองใหม่

กำหนดค่าการลองใหม่จากคอนโซล GCP

หากคุณกำลังสร้างฟังก์ชันใหม่:

  1. จากหน้าจอ สร้างฟังก์ชัน ให้เลือก เพิ่มทริกเกอร์ และเลือกประเภทของเหตุการณ์ที่จะทำหน้าที่เป็นทริกเกอร์สำหรับฟังก์ชันของคุณ
  2. ในบานหน้าต่าง ทริกเกอร์ Eventarc ให้เลือกกล่องกาเครื่องหมาย ลองอีกครั้งเมื่อล้มเหลว เพื่อเปิดใช้งานการลองใหม่

หากคุณกำลังอัปเดตฟังก์ชันที่มีอยู่:

  1. จากหน้า ภาพรวมฟังก์ชันคลาวด์ คลิกชื่อฟังก์ชันที่คุณกำลังอัปเดตเพื่อเปิดหน้าจอ รายละเอียดฟังก์ชัน จากนั้นเลือก แก้ไข จากแถบเมนูเพื่อแสดงบานหน้าต่างทริกเกอร์ HTTPS และ Eventarc
  2. ในบานหน้าต่าง ทริกเกอร์ Eventarc คลิกไอคอน แก้ไข เพื่อแก้ไขการตั้งค่าทริกเกอร์ของคุณ
  3. ในบานหน้าต่าง ทริกเกอร์ Eventarc ให้เลือกหรือล้างกล่องกาเครื่องหมาย ลองอีกครั้งเมื่อล้มเหลว เพื่อเปิดหรือปิดใช้งานการลองใหม่

กำหนดค่าการลองใหม่จากโค้ดฟังก์ชันของคุณ

ด้วย Cloud Functions สำหรับ Firebase คุณจะเปิดใช้การลองใหม่ในโค้ดสำหรับฟังก์ชันได้ เมื่อต้องการทำเช่นนี้สำหรับฟังก์ชันพื้นหลัง เช่น functions.foo.onBar(myHandler); ให้ใช้ runWith และกำหนดค่านโยบายความล้มเหลว:

functions.runWith({failurePolicy: true}).foo.onBar(myHandler);

การตั้งค่า true ดังที่แสดงไว้จะกำหนดค่าฟังก์ชันให้ลองอีกครั้งเมื่อเกิดความล้มเหลว

ปฏิบัติที่ดีที่สุด

ส่วนนี้อธิบายแนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้การลองใหม่

ใช้การลองอีกครั้งเพื่อจัดการกับข้อผิดพลาดชั่วคราว

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

กำหนดเงื่อนไขการสิ้นสุดเพื่อหลีกเลี่ยงการวนซ้ำแบบไม่มีที่สิ้นสุด

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

แนวทางที่เรียบง่ายแต่มีประสิทธิภาพคือการละทิ้งเหตุการณ์ที่มีการประทับเวลาที่เก่ากว่าเวลาที่กำหนด ซึ่งจะช่วยหลีกเลี่ยงการดำเนินการที่มากเกินไปเมื่อความล้มเหลวเกิดขึ้นอย่างต่อเนื่องหรือมีอายุการใช้งานนานกว่าที่คาดไว้

ตัวอย่างเช่น ข้อมูลโค้ดนี้จะละทิ้งกิจกรรมทั้งหมดที่เก่ากว่า 10 วินาที:

const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
  console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
  callback();
  return;
}

ใช้ catch กับสัญญา

หากฟังก์ชันของคุณเปิดใช้งานการลองใหม่ ข้อผิดพลาดที่ไม่สามารถจัดการได้จะทำให้เกิดการลองใหม่ ตรวจสอบให้แน่ใจว่าโค้ดของคุณบันทึกข้อผิดพลาดใดๆ ที่ไม่ควรส่งผลให้เกิดการลองใหม่

นี่คือตัวอย่างสิ่งที่คุณควรทำ:

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

ทำให้ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ที่ลองใหม่ได้เป็น idempotent

ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ที่สามารถลองใหม่ได้จะต้องเป็น idempotent ต่อไปนี้เป็นแนวทางทั่วไปบางประการในการสร้างฟังก์ชัน idempotent:

  • API ภายนอกจำนวนมาก (เช่น Stripe) ช่วยให้คุณสามารถระบุคีย์ idempotency เป็นพารามิเตอร์ได้ หากคุณใช้ API ดังกล่าว คุณควรใช้รหัสเหตุการณ์เป็นคีย์ idempotency
  • Idempotency ทำงานได้ดีกับการนำส่งอย่างน้อยหนึ่งครั้ง เนื่องจากทำให้ปลอดภัยในการลองอีกครั้ง ดังนั้นแนวทางปฏิบัติที่ดีที่สุดโดยทั่วไปในการเขียนโค้ดที่เชื่อถือได้คือการรวมค่าเดิมเข้ากับการลองใหม่
  • ตรวจสอบให้แน่ใจว่าโค้ดของคุณเป็นแบบ idempotent ภายใน ตัวอย่างเช่น:
    • ตรวจสอบให้แน่ใจว่าการกลายพันธุ์สามารถเกิดขึ้นได้มากกว่าหนึ่งครั้งโดยไม่เปลี่ยนแปลงผลลัพธ์
    • ค้นหาสถานะฐานข้อมูลในธุรกรรมก่อนที่จะเปลี่ยนสถานะ
    • ตรวจสอบให้แน่ใจว่าผลข้างเคียงทั้งหมดนั้นไม่มีประสิทธิภาพ
  • กำหนดการตรวจสอบธุรกรรมนอกฟังก์ชัน โดยไม่ขึ้นกับโค้ด ตัวอย่างเช่น คงสถานะการบันทึกไว้ว่ามีการประมวลผลรหัสเหตุการณ์ที่กำหนดแล้ว
  • จัดการกับการเรียกฟังก์ชันที่ซ้ำกันนอกแบนด์ ตัวอย่างเช่น มีกระบวนการล้างข้อมูลแยกต่างหากที่จะล้างข้อมูลหลังจากการเรียกใช้ฟังก์ชันที่ซ้ำกัน

กำหนดค่านโยบายการลองใหม่

คุณอาจต้องการกำหนดค่านโยบายการลองใหม่โดยตรง ทั้งนี้ขึ้นอยู่กับความต้องการของฟังก์ชันคลาวด์ของคุณ ซึ่งจะช่วยให้คุณสามารถตั้งค่าชุดค่าผสมต่อไปนี้ได้:

  • ลดระยะเวลาการลองใหม่จาก 7 วันเหลือเพียง 10 นาที
  • เปลี่ยนเวลาถอยกลับขั้นต่ำและสูงสุดสำหรับกลยุทธ์การลองถอยกลับแบบเอกซ์โปเนนเชียล
  • เปลี่ยนกลยุทธ์การลองใหม่เพื่อลองอีกครั้งทันที
  • กำหนด ค่าหัวข้อจดหมายที่ส่งไม่ถึง
  • กำหนดจำนวนครั้งในการส่งสูงสุดและต่ำสุด

ในการกำหนดค่านโยบายการลองใหม่:

  1. เขียนฟังก์ชัน HTTP
  2. ใช้ Pub/Sub API เพื่อสร้างการสมัครสมาชิก Pub/Sub โดยระบุ URL ของฟังก์ชันเป็นเป้าหมาย

ดู เอกสาร Pub/Sub เกี่ยวกับการจัดการความล้มเหลว สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่า Pub/Sub โดยตรง