Firebase 将于 5 月 10 日重返 Google I/O 大会!立即报名

Tips & Tricks

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

ความถูกต้อง

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

เขียนฟังก์ชัน idempotent

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

อย่าเริ่มกิจกรรมเบื้องหลัง

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

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

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

ลบไฟล์ชั่วคราวเสมอ

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

คุณสามารถดูหน่วยความจำที่ใช้โดยแต่ละฟังก์ชันโดยเลือกใน รายการฟังก์ชัน ในคอนโซล GCP และเลือกแผนภาพ การใช้หน่วยความจำ

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

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

เครื่องมือ

ส่วนนี้ให้แนวทางเกี่ยวกับวิธีการใช้เครื่องมือเพื่อใช้งาน ทดสอบ และโต้ตอบกับ Cloud Functions

การพัฒนาท้องถิ่น

การปรับใช้ฟังก์ชันใช้เวลาเล็กน้อย ดังนั้นมักจะเร็วกว่าในการทดสอบโค้ดของฟังก์ชันของคุณในเครื่อง

นักพัฒนา Firebase สามารถใช้ Firebase CLI Cloud Functions Emulator

ใช้ Sendgrid เพื่อส่งอีเมล

Cloud Functions ไม่อนุญาตให้มีการเชื่อมต่อขาออกบนพอร์ต 25 ดังนั้นคุณจึงไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ SMTP ที่ไม่ปลอดภัยได้ วิธีการส่งอีเมลที่แนะนำคือใช้ SendGrid คุณสามารถค้นหาตัวเลือกอื่นๆ สำหรับการส่งอีเมลได้ในบทแนะนำ การส่งอีเมลจากอินสแตนซ์ สำหรับ Google Compute Engine

ผลงาน

ส่วนนี้อธิบายแนวทางปฏิบัติที่ดีที่สุดสำหรับการเพิ่มประสิทธิภาพ

ใช้การพึ่งพาอย่างชาญฉลาด

เนื่องจากฟังก์ชันไม่มีสถานะ สภาพแวดล้อมการดำเนินการจึงมักเริ่มต้นจากศูนย์ (ในระหว่างที่เรียกว่า การเริ่มเย็น ) เมื่อเกิด Cold Start บริบทส่วนกลางของฟังก์ชันจะได้รับการประเมิน

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

ใช้ตัวแปรส่วนกลางเพื่อนำวัตถุกลับมาใช้ใหม่ในการเรียกใช้ในอนาคต

ไม่มีการรับประกันว่าสถานะของ Cloud Function จะถูกรักษาไว้สำหรับการเรียกใช้ในอนาคต อย่างไรก็ตาม Cloud Functions มักจะรีไซเคิลสภาพแวดล้อมการดำเนินการของการเรียกใช้ครั้งก่อน หากคุณประกาศตัวแปรในขอบเขตร่วม ค่าของตัวแปรสามารถนำมาใช้ใหม่ในการเรียกใช้ครั้งต่อไปโดยไม่ต้องคำนวณใหม่

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

console.log('Global scope');
const perInstance = heavyComputation();
const functions = require('firebase-functions');

exports.function = functions.https.onRequest((req, res) => {
    console.log('Function invocation');
    const perFunction = lightweightComputation();

    res.send(`Per instance: ${perInstance}, per function: ${perFunction}`);
});

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

เริ่มต้นขี้เกียจของตัวแปรส่วนกลาง

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

const functions = require('firebase-functions');
let myCostlyVariable;

exports.function = functions.https.onRequest((req, res) => {
    doUsualWork();
    if(unlikelyCondition()){
        myCostlyVariable = myCostlyVariable || buildCostlyVariable();
    }
    res.status(200).send('OK');
});

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

ลดการเริ่มเย็นโดยกำหนดจำนวนอินสแตนซ์ขั้นต่ำ

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

ดู การควบคุมพฤติกรรมการปรับสเกล สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกรันไทม์เหล่านี้

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพในวิดีโอ "Google Cloud Performance Atlas" Cloud Functions Cold Boot Time