เอกสารนี้อธิบายวิธีขอฟังก์ชันพื้นหลังแบบไม่พร้อมกัน (ไม่ใช่ HTTPS) เพื่อลองอีกครั้งเมื่อล้มเหลว
เหตุใดฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์จึงทำงานไม่สำเร็จ
ในบางกรณีที่พบได้ไม่บ่อยนัก ฟังก์ชันอาจสิ้นสุดก่อนเวลาอันควรเนื่องจากข้อผิดพลาดภายใน และโดยค่าเริ่มต้น ฟังก์ชันอาจลองใหม่โดยอัตโนมัติหรือไม่ก็ได้
โดยปกติแล้ว ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์อาจทำงานไม่สำเร็จเนื่องจากข้อผิดพลาดที่เกิดขึ้นในโค้ดของฟังก์ชันเอง สาเหตุที่อาจทำให้เกิดเหตุการณ์นี้มีดังนี้
- ฟังก์ชันมีข้อบกพร่องและรันไทม์จะส่งข้อยกเว้น
- ฟังก์ชันเข้าถึงปลายทางบริการไม่ได้ หรือหมดเวลาขณะพยายามเข้าถึง
- ฟังก์ชันจะตั้งใจส่งข้อยกเว้น (เช่น เมื่อพารามิเตอร์ ไม่ผ่านการตรวจสอบ)
- ฟังก์ชัน Node.js จะแสดงผล Promise ที่ถูกปฏิเสธ หรือส่งค่าที่ไม่ใช่
null
ไปยัง Callback
ในกรณีใดก็ตามข้างต้น ฟังก์ชันจะหยุดการดำเนินการและแสดงข้อผิดพลาด ทริกเกอร์เหตุการณ์ที่สร้างข้อความมีนโยบายการลองใหม่ที่คุณปรับแต่งได้ เพื่อให้ตรงกับความต้องการของฟังก์ชัน
ความหมายของการลองใหม่
Cloud Functions ให้การเรียกใช้ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์อย่างน้อย 1 ครั้ง สําหรับแต่ละเหตุการณ์ที่แหล่งเหตุการณ์ปล่อยออกมา วิธีกำหนดค่าการลองใหม่จะขึ้นอยู่กับวิธีที่คุณสร้างฟังก์ชัน ดังนี้
- ฟังก์ชันที่สร้างในคอนโซล Google Cloud หรือด้วย Cloud RunAdmin API กำหนดให้คุณต้องสร้างและจัดการทริกเกอร์เหตุการณ์แยกต่างหาก ทริกเกอร์มี ลักษณะการทำงานของการลองใหม่เริ่มต้นที่คุณปรับแต่งให้เหมาะกับความต้องการของ ฟังก์ชันได้
- ฟังก์ชันที่สร้างด้วย Cloud Functions v2 API จะสร้างทริกเกอร์เหตุการณ์ที่จำเป็นโดยนัย เช่น หัวข้อ Pub/Sub หรือทริกเกอร์ Eventarc โดยค่าเริ่มต้น ระบบจะปิดใช้การลองใหม่สำหรับทริกเกอร์เหล่านี้ และเปิดใช้ใหม่ได้โดยใช้ Cloud Functions v2 API
ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ซึ่งสร้างด้วย Cloud Run
ฟังก์ชันที่สร้างในคอนโซล Google Cloud หรือด้วย Cloud Run Admin API จะกำหนดให้คุณสร้างและจัดการทริกเกอร์เหตุการณ์แยกกัน เราขอแนะนำเป็นอย่างยิ่ง ให้คุณตรวจสอบลักษณะการทำงานเริ่มต้นของทริกเกอร์แต่ละประเภท
- Eventarcนโยบายการลองใหม่มีการเก็บรักษาข้อความเริ่มต้นเป็นเวลา 24 ชั่วโมงโดยมีการหน่วงเวลา Exponential Backoff โปรดดูEventarcเอกสารประกอบเกี่ยวกับ เหตุการณ์ลองอีกครั้ง
- โดยค่าเริ่มต้น Pub/Sub จะใช้นโยบาย การนำส่งซ้ำทันที สำหรับการสมัครใช้บริการทั้งหมด โปรดดูPub/Subเอกสารประกอบเกี่ยวกับ การจัดการข้อความที่ไม่สำเร็จและ คำขอให้ลองอีกครั้ง
ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ซึ่งสร้างด้วย Cloud Functions v2 API
ฟังก์ชันที่สร้างขึ้นโดยใช้ Cloud Functions v2 API เช่น การใช้ Cloud Functions gcloud CLI, REST API หรือ Terraform จะสร้างและจัดการทริกเกอร์เหตุการณ์ในนามของคุณ โดยค่าเริ่มต้น หากการเรียกใช้ฟังก์ชัน สิ้นสุดลงด้วยข้อผิดพลาด ระบบจะไม่เรียกใช้ฟังก์ชันอีกครั้งและ จะทิ้งเหตุการณ์ เมื่อเปิดใช้การลองใหม่ในฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ Cloud Functions จะลองเรียกใช้ฟังก์ชันที่ล้มเหลวอีกครั้งจนกว่าจะเสร็จสมบูรณ์ สำเร็จหรือช่วงการลองใหม่หมดอายุ
เมื่อไม่ได้เปิดใช้การลองใหม่สำหรับฟังก์ชัน (ซึ่งเป็นค่าเริ่มต้น) ฟังก์ชันจะรายงานเสมอว่าทำงานสำเร็จ และ200 OK
โค้ดตอบกลับอาจปรากฏในบันทึก ซึ่งจะเกิดขึ้นแม้ว่าฟังก์ชันจะพบข้อผิดพลาดก็ตาม เพื่อให้ทราบอย่างชัดเจนเมื่อฟังก์ชันพบข้อผิดพลาด โปรดรายงานข้อผิดพลาดอย่างเหมาะสม
เปิดหรือปิดใช้การลองใหม่
กำหนดค่าการลองใหม่จากโค้ดฟังก์ชัน
Cloud Functions for Firebase ช่วยให้คุณเปิดใช้การลองใหม่ในโค้ดสำหรับฟังก์ชันได้ หากต้องการทำเช่นนี้สำหรับฟังก์ชันเบื้องหลัง เช่น
functions.foo.onBar(myHandler);
ให้ใช้
runWith
และกำหนดค่านโยบายความล้มเหลว ดังนี้
functions.runWith({failurePolicy: true}).foo.onBar(myHandler);
การตั้งค่า true
ตามที่แสดงจะกำหนดค่าฟังก์ชันให้ลองอีกครั้งเมื่อล้มเหลว
กรอบเวลาลองอีกครั้ง
สำหรับฟังก์ชันรุ่นที่ 2 หน้าต่างลองอีกครั้งนี้จะหมดอายุหลังจาก 24 ชั่วโมง สำหรับฟังก์ชันรุ่นที่ 1 ฟังก์ชันจะหมดอายุ หลังจาก 7 วัน Cloud Functions จะลองส่งฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ซึ่งสร้างขึ้นใหม่ซ้ำโดยใช้ กลยุทธ์ Exponential Backoff โดยจะเพิ่มระยะเวลา Backoff ระหว่าง 10 ถึง 600 วินาที นโยบายนี้จะมีผลกับฟังก์ชันใหม่ ในครั้งแรกที่คุณทําให้ฟังก์ชันดังกล่าวใช้งานได้ การเปลี่ยนแปลงนี้จะไม่มีผลย้อนหลังกับฟังก์ชันที่มีอยู่ ซึ่งได้รับการติดตั้งใช้งานครั้งแรกก่อนที่การเปลี่ยนแปลงที่อธิบายไว้ในบันทึกประจำรุ่นนี้ จะมีผล แม้ว่าคุณจะติดตั้งใช้งานฟังก์ชันอีกครั้งก็ตามแนวทางปฏิบัติแนะนำ
ส่วนนี้จะอธิบายแนวทางปฏิบัติแนะนำในการใช้การลองใหม่
ใช้การลองใหม่เพื่อจัดการข้อผิดพลาดแบบชั่วคราว
เนื่องจากระบบจะลองดำเนินการกับฟังก์ชันของคุณอีกครั้งอย่างต่อเนื่องจนกว่าจะดำเนินการสำเร็จ ข้อผิดพลาดถาวร เช่น บั๊ก ควรถูกกำจัดออกจากโค้ดผ่านการทดสอบ ก่อนที่จะเปิดใช้การลองใหม่ การลองใหม่เหมาะที่สุดสำหรับการจัดการข้อผิดพลาดที่เกิดขึ้นเป็นระยะๆ หรือชั่วคราว ซึ่งมีแนวโน้มสูงที่จะแก้ไขได้เมื่อลองใหม่ เช่น ปลายทางบริการที่ไม่เสถียรหรือหมดเวลา
กำหนดเงื่อนไขสิ้นสุดเพื่อหลีกเลี่ยงการวนซ้ำของการลองใหม่แบบไม่สิ้นสุด
แนวทางปฏิบัติแนะนำคือการป้องกันไม่ให้ฟังก์ชันวนซ้ำอย่างต่อเนื่องเมื่อใช้การลองใหม่ คุณทำได้โดยระบุเงื่อนไขสิ้นสุดที่ชัดเจน ก่อนที่ฟังก์ชันจะเริ่มประมวลผล โปรดทราบว่าเทคนิคนี้จะใช้ได้ก็ต่อเมื่อ ฟังก์ชันเริ่มต้นได้สำเร็จและประเมินเงื่อนไขสิ้นสุดได้
แนวทางที่เรียบง่ายแต่มีประสิทธิภาพคือการทิ้งเหตุการณ์ที่มีการประทับเวลาเก่ากว่า เวลาที่กำหนด ซึ่งจะช่วยหลีกเลี่ยงการดำเนินการมากเกินไปเมื่อเกิดข้อผิดพลาดที่คงอยู่หรือมีอายุการใช้งานนานกว่าที่คาดไว้
เช่น ข้อมูลโค้ดนี้จะทิ้งเหตุการณ์ทั้งหมดที่เก่ากว่า 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
กับ Promise
หากฟังก์ชันเปิดใช้การลองใหม่ไว้ ข้อผิดพลาดที่ไม่ได้จัดการจะทริกเกอร์การลองใหม่ ตรวจสอบว่าโค้ดจับข้อผิดพลาดที่ไม่ควรทำให้เกิดการลองใหม่
ตัวอย่างสิ่งที่คุณควรทำมีดังนี้
return doFooAsync().catch((err) => {
if (isFatal(err)) {
console.error(`Fatal error ${err}`);
}
return Promise.reject(err);
});
ทำให้ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ที่ลองใหม่ได้เป็นฟังก์ชันที่ทำงานซ้ำได้
ฟังก์ชันที่ขับเคลื่อนด้วยเหตุการณ์ซึ่งลองใหม่ได้ต้องเป็นฟังก์ชันที่ไม่มีผลข้างเคียง ต่อไปนี้เป็นหลักเกณฑ์ทั่วไปในการทำให้ฟังก์ชันดังกล่าวเป็นแบบ Idempotent
- API ภายนอกหลายรายการ (เช่น Stripe) อนุญาตให้คุณระบุคีย์การดำเนินการแบบไอดีมโปเทนซี เป็นพารามิเตอร์ หากคุณใช้ API ดังกล่าว คุณควรใช้รหัสเหตุการณ์เป็นคีย์การดำเนินการแบบไอดีมโปเทนซี
- การทำงานแบบ Idempotent จะทำงานได้ดีกับการนำส่งแบบ "อย่างน้อย 1 ครั้ง" เนื่องจากทำให้การลองใหม่ปลอดภัย ดังนั้นแนวทางปฏิบัติแนะนำทั่วไปในการเขียนโค้ดที่เชื่อถือได้คือการรวม การดำเนินการซ้ำกับความพยายามอีกครั้ง
- ตรวจสอบว่าโค้ดของคุณเป็น Idempotent ภายใน เช่น
- ตรวจสอบว่าการเปลี่ยนแปลงเกิดขึ้นได้มากกว่า 1 ครั้งโดยไม่เปลี่ยน ผลลัพธ์
- ค้นหาสถานะฐานข้อมูลในธุรกรรมก่อนที่จะเปลี่ยนสถานะ
- ตรวจสอบว่าผลข้างเคียงทั้งหมดเป็นแบบไอดีมโพเทนต์
- กำหนดการตรวจสอบธุรกรรมภายนอกฟังก์ชันโดยไม่ขึ้นอยู่กับโค้ด เช่น ให้บันทึกสถานะไว้ที่ใดที่หนึ่งเพื่อบันทึกว่ามีการประมวลผลรหัสเหตุการณ์ที่ระบุแล้ว
- จัดการการเรียกใช้ฟังก์ชันที่ซ้ำกันนอกแบนด์ เช่น มีกระบวนการล้างข้อมูลแยกต่างหาก ซึ่งจะล้างข้อมูลหลังจากมีการเรียกฟังก์ชันที่ซ้ำกัน
กำหนดค่านโยบายการลองใหม่
คุณอาจต้องกำหนดค่านโยบายการลองใหม่โดยตรง ทั้งนี้ขึ้นอยู่กับความต้องการของฟังก์ชัน ซึ่งจะช่วยให้คุณตั้งค่าการผสมผสานใดๆ ของรายการต่อไปนี้ได้
- ลดกรอบเวลาลองใหม่จาก 7 วันเหลือเพียง 10 นาที
- เปลี่ยนเวลาหยุดชั่วคราวขั้นต่ำและสูงสุดสำหรับกลยุทธ์การลองใหม่แบบหยุดชั่วคราวแบบทวีคูณ
- เปลี่ยนกลยุทธ์การลองใหม่เป็นการลองใหม่ทันที
- กำหนดค่าหัวข้อจดหมายที่ส่งไม่ได้
- กำหนดจำนวนครั้งสูงสุดและต่ำสุดในการพยายามนำส่ง
วิธีกำหนดค่านโยบายการลองใหม่
- เขียนฟังก์ชัน HTTP
- ใช้ Pub/Sub API เพื่อสร้างการสมัครใช้บริการ Pub/Sub โดยระบุ URL ของ ฟังก์ชันเป็นเป้าหมาย
ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่า Pub/Sub โดยตรงได้ในPub/Subเอกสารประกอบเกี่ยวกับการจัดการความล้มเหลว