เอกสารนี้อธิบายวิธีที่คุณสามารถขอฟังก์ชันพื้นหลังแบบอะซิงโครนัส (ไม่ใช่ HTTPS) เพื่อลองอีกครั้งเมื่อเกิดความล้มเหลว
ความหมายของการลองใหม่
Cloud Functions รับประกันการดำเนินการฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์อย่างน้อยหนึ่งครั้งสำหรับแต่ละเหตุการณ์ที่ปล่อยออกมาโดยแหล่งเหตุการณ์ ตามค่าเริ่มต้น หากการเรียกใช้ฟังก์ชันสิ้นสุดลงโดยมีข้อผิดพลาด ฟังก์ชันจะไม่ถูกเรียกใช้อีกครั้งและเหตุการณ์จะหายไป เมื่อคุณเปิดใช้งานการลองใหม่บนฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ ฟังก์ชันคลาวด์จะพยายามเรียกใช้ฟังก์ชันที่ล้มเหลวอีกครั้งจนกว่าจะเสร็จสมบูรณ์หรือหน้าต่างการลองใหม่หมดลง
สำหรับฟังก์ชันรุ่นที่ 2 หน้าต่างลองใหม่นี้จะหมดอายุหลังจาก 24 ชั่วโมง สำหรับฟังก์ชันรุ่นที่ 1 จะหมดอายุหลังจากผ่านไป 7 วัน Cloud Functions ลองใช้ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ที่สร้างขึ้นใหม่อีกครั้งโดยใช้กลยุทธ์แบ็คออฟแบบเอ็กซ์โปเนนเชียล โดยมีแบ็คออฟเพิ่มขึ้นระหว่าง 10 ถึง 600 วินาที นโยบายนี้จะนำไปใช้กับฟังก์ชันใหม่ในครั้งแรกที่คุณใช้งาน จะไม่มีผลย้อนหลังกับฟังก์ชันที่มีอยู่ซึ่งมีการใช้งานครั้งแรกก่อนที่การเปลี่ยนแปลงที่อธิบายไว้ใน บันทึกประจำรุ่นนี้ จะมีผล แม้ว่าคุณจะปรับใช้ฟังก์ชันใหม่ก็ตาม
เมื่อไม่ได้เปิดใช้งานการลองใหม่สำหรับฟังก์ชันซึ่งเป็นค่าเริ่มต้น ฟังก์ชันจะรายงานเสมอว่าดำเนินการสำเร็จ และรหัสตอบกลับ 200 OK
รหัสอาจปรากฏในบันทึก สิ่งนี้จะเกิดขึ้นแม้ว่าฟังก์ชันจะพบข้อผิดพลาดก็ตาม เพื่อให้ชัดเจนเมื่อฟังก์ชันของคุณพบข้อผิดพลาด โปรด รายงานข้อผิดพลาด อย่างเหมาะสม
เหตุใดฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์จึงล้มเหลว
ในโอกาสที่เกิดขึ้นไม่บ่อยนัก ฟังก์ชันอาจออกก่อนเวลาอันควรเนื่องจากข้อผิดพลาดภายใน และตามค่าเริ่มต้น ฟังก์ชันอาจจะหรืออาจจะไม่ลองใหม่โดยอัตโนมัติ
โดยทั่วไปแล้ว ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์อาจล้มเหลวในการดำเนินการให้เสร็จสมบูรณ์เนื่องจากมีข้อผิดพลาดเกิดขึ้นในโค้ดฟังก์ชันเอง สาเหตุที่อาจเกิดขึ้น ได้แก่:
- ฟังก์ชันนี้มีจุดบกพร่องและรันไทม์ส่งข้อยกเว้น
- ฟังก์ชันไม่สามารถเข้าถึงจุดสิ้นสุดของบริการ หรือหมดเวลาขณะพยายามทำเช่นนั้น
- ฟังก์ชันจงใจส่งข้อยกเว้น (เช่น เมื่อพารามิเตอร์ไม่ผ่านการตรวจสอบ)
- ฟังก์ชัน Node.js ส่งคืนสัญญาที่ถูกปฏิเสธหรือส่งผ่านค่าที่ไม่ใช่
null
ไปยังการโทรกลับ
ในกรณีใดๆ ข้างต้น ฟังก์ชันจะหยุดดำเนินการตามค่าเริ่มต้นและเหตุการณ์จะถูกละทิ้ง หากต้องการลองฟังก์ชันใหม่เมื่อมีข้อผิดพลาดเกิดขึ้น คุณสามารถเปลี่ยนนโยบายการลองใหม่เริ่มต้นได้โดย การตั้งค่าคุณสมบัติ "ลองใหม่เมื่อล้มเหลว" ซึ่งทำให้เหตุการณ์ต้องลองซ้ำหลายครั้งจนกว่าฟังก์ชันจะเสร็จสมบูรณ์หรือหมดเวลาการลองใหม่อีกครั้ง
เปิดหรือปิดการลองใหม่
กำหนดค่าการลองใหม่จากคอนโซล GCP
หากคุณกำลังสร้างฟังก์ชันใหม่:
- จากหน้าจอ สร้างฟังก์ชัน ให้เลือก เพิ่มทริกเกอร์ และเลือกประเภทของเหตุการณ์ที่จะทำหน้าที่เป็นทริกเกอร์สำหรับฟังก์ชันของคุณ
- ในบานหน้าต่าง ทริกเกอร์ Eventarc ให้เลือกกล่องกาเครื่องหมาย ลองอีกครั้งเมื่อล้มเหลว เพื่อเปิดใช้งานการลองใหม่
หากคุณกำลังอัปเดตฟังก์ชันที่มีอยู่:
- จากหน้า ภาพรวมฟังก์ชันคลาวด์ คลิกชื่อฟังก์ชันที่คุณกำลังอัปเดตเพื่อเปิดหน้าจอ รายละเอียดฟังก์ชัน จากนั้นเลือก แก้ไข จากแถบเมนูเพื่อแสดงบานหน้าต่างทริกเกอร์ HTTPS และ Eventarc
- ในบานหน้าต่าง ทริกเกอร์ Eventarc คลิกไอคอน แก้ไข เพื่อแก้ไขการตั้งค่าทริกเกอร์ของคุณ
- ในบานหน้าต่าง ทริกเกอร์ 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 นาที
- เปลี่ยนเวลาถอยกลับขั้นต่ำและสูงสุดสำหรับกลยุทธ์การลองถอยกลับแบบเอกซ์โปเนนเชียล
- เปลี่ยนกลยุทธ์การลองใหม่เพื่อลองอีกครั้งทันที
- กำหนด ค่าหัวข้อจดหมายที่ส่งไม่ถึง
- กำหนดจำนวนครั้งในการส่งสูงสุดและต่ำสุด
ในการกำหนดค่านโยบายการลองใหม่:
- เขียนฟังก์ชัน HTTP
- ใช้ Pub/Sub API เพื่อสร้างการสมัครสมาชิก Pub/Sub โดยระบุ URL ของฟังก์ชันเป็นเป้าหมาย
ดู เอกสาร Pub/Sub เกี่ยวกับการจัดการความล้มเหลว สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่า Pub/Sub โดยตรง