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

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

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

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

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

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