שדרג את פונקציות הדור הראשון של Node.js לדור השני

אפליקציות המשתמשות כעת בפונקציות של דור ראשון צריכות לשקול מעבר לדור שני באמצעות ההוראות במדריך זה. פונקציות דור שני משתמשות ב-Cloud Run כדי לספק ביצועים טובים יותר, תצורה טובה יותר, ניטור טוב יותר ועוד.

הדוגמאות בדף זה מניחות שאתה משתמש ב-JavaScript עם מודולי CommonJS ( require ייבוא ​​סגנון), אך אותם עקרונות חלים על JavaScript עם ESM ( import … from מייבוא ​​סגנונות) ו- TypeScript.

תהליך ההגירה

פונקציות דור 1 ודור 2 יכולות להתקיים זה לצד זה באותו קובץ. זה מאפשר הגירה קלה חלק אחר חלק, כפי שאתה מוכן. אנו ממליצים להעביר פונקציה אחת בכל פעם, לבצע בדיקות ואימות לפני שתמשיך.

אמת את גרסאות Firebase CLI ו- firebase-function

ודא שאתה משתמש לפחות בגרסה 12.00 של Firebase CLI ובגרסה 4.3.0 firebase-functions . כל גרסה חדשה יותר תתמוך בדור השני כמו גם בדור הראשון.

עדכן יבוא

ייבוא ​​של פונקציות דור 2 מתת-חבילת v2 ב-SDK של firebase-functions . נתיב הייבוא ​​השונה הזה הוא כל מה ש-Firebase CLI צריך כדי לקבוע אם לפרוס את קוד הפונקציה שלך כפונקציה של דור ראשון או שני.

תת-חבילת v2 היא מודולרית, ואנו ממליצים לייבא רק את המודול הספציפי שאתה צריך.

לפני: דור 1

const functions = require("firebase-functions");

אחרי: דור שני

// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

עדכן הגדרות טריגר

מכיוון שה-SDK של הדור השני מעדיף יבוא מודולרי, עדכן את הגדרות הטריגרים כדי לשקף את הייבוא ​​שהשתנה מהשלב הקודם.

הטיעונים שהועברו ל-callback עבור כמה טריגרים השתנו. בדוגמה זו, שים לב שהארגומנטים להתקשרות חוזרת של onDocumentCreated אוחדו לאובייקט event בודד. בנוסף, לכמה טריגרים יש תכונות תצורה חדשות ונוחות, כמו אפשרות ה- cors של onRequest trigger.

לפני: דור 1

const functions = require("firebase-functions");

exports.date = functions.https.onRequest((req, res) => {
  // ...
});

exports.uppercase = functions.firestore
  .document("my-collection/{docId}")
  .onCreate((change, context) => {
    // ...
  });

אחרי: דור שני

const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

exports.date = onRequest({cors: true}, (req, res) => {
  // ...
});

exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
  /* ... */
});

השתמש בתצורה עם פרמטרים

פונקציות דור 2 מורידות את התמיכה ב- functions.config לטובת ממשק מאובטח יותר להגדרת פרמטרי תצורה באופן הצהרתי בתוך בסיס הקוד שלך. עם מודול params החדש, ה-CLI חוסם את הפריסה אלא אם לכל הפרמטרים יש ערך חוקי, מה שמבטיח שפונקציה לא נפרסת עם תצורה חסרה.

העבר אל תת-חבילת params

אם השתמשת בתצורת סביבה עם functions.config , אתה יכול להעביר את התצורה הקיימת שלך לתצורה עם פרמטרים .

לפני: דור 1

const functions = require("firebase-functions");

exports.date = functions.https.onRequest((req, res) => {
  const date = new Date();
  const formattedDate =
date.toLocaleDateString(functions.config().dateformat);

  // ...
});

אחרי: דור שני

const {onRequest} = require("firebase-functions/v2/https");
const {defineString} = require("firebase-functions/params");

const dateFormat = defineString("DATE_FORMAT");

exports.date = onRequest((req, res) => {
  const date = new Date();
  const formattedDate = date.toLocaleDateString(dateFormat.value());

  // ...
});

הגדר ערכי פרמטרים

בפעם הראשונה שתפרוס, ה-CLI של Firebase יבקש את כל הערכים של הפרמטרים ושומר את הערכים בקובץ dotenv. כדי לייצא את ערכי functions.config, הפעל את firebase functions:config:export .

לבטיחות נוספת, תוכל גם לציין סוגי פרמטרים וכללי אימות .

מקרה מיוחד: מפתחות API

מודול ה- params משתלב עם Cloud Secret Manager, המספק בקרת גישה עדינה לערכים רגישים כמו מפתחות API. ראה פרמטרים סודיים למידע נוסף.

לפני: דור 1

const functions = require("firebase-functions");

exports.getQuote = functions.https.onRequest(async (req, res) => {
  const quote = await fetchMotivationalQuote(functions.config().apiKey);
  // ...
});

אחרי: דור שני

const {onRequest} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");

// Define the secret parameter
const apiKey = defineSecret("API_KEY");

exports.getQuote = onRequest(
  // make the secret available to this function
  { secrets: [apiKey] },
  async (req, res) => {
    // retrieve the value of the secret
    const quote = await fetchMotivationalQuote(apiKey.value());
    // ...
  }
);

הגדר אפשרויות זמן ריצה

התצורה של אפשרויות זמן הריצה השתנתה בין הדור הראשון לדור השני. דור שני גם מוסיף יכולת חדשה להגדיר אפשרויות עבור כל הפונקציות.

לפני: דור 1

const functions = require("firebase-functions");

exports.date = functions
  .runWith({
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  })
  // locate function closest to users
  .region("asia-northeast1")
  .https.onRequest((req, res) => {
    // ...
  });

exports.uppercase = functions
  // locate function closest to users and database
  .region("asia-northeast1")
  .firestore.document("my-collection/{docId}")
  .onCreate((change, context) => {
    // ...
  });

אחרי: דור שני

const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions/v2");

// locate all functions closest to users
setGlobalOptions({ region: "asia-northeast1" });

exports.date = onRequest({
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  }, (req, res) => {
  // ...
});

exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
  /* ... */
});

השתמש במקביל

יתרון משמעותי של פונקציות דור 2 הוא היכולת של מופע פונקציה בודד לשרת יותר מבקשה אחת בבת אחת. זה יכול להפחית באופן דרמטי את מספר ההתחלות הקרות שחווים משתמשי קצה. כברירת מחדל, מקבילות מוגדרת ל-80, אך ניתן להגדיר אותה לכל ערך מ-1 עד 1000:

const {onRequest} = require("firebase-functions/v2/https");

exports.date = onRequest({
    // set concurrency value
    concurrency: 500
  },
  (req, res) => {
    // ...
});

כוונון במקביל יכול לשפר את הביצועים ולהפחית את עלות הפונקציות. למידע נוסף על מקבילות ב'אפשר בקשות במקביל .

ביקורת על שימוש במשתנה גלובלי

פונקציות מהדור הראשון שנכתבו ללא מחשבה במקביל עשויות להשתמש במשתנים גלובליים המוגדרים ונקראים בכל בקשה. כאשר מקביליות מופעלת ומופע בודד מתחיל לטפל במספר בקשות בו-זמנית, הדבר עלול להכניס באגים בפונקציה שלך כאשר בקשות במקביל מתחילות להגדיר ולקרוא משתנים גלובליים בו-זמנית.

בזמן השדרוג, אתה יכול להגדיר את ה-CPU של הפונקציה שלך ל- gcf_gen1 ולהגדיר concurrency ל-1 כדי לשחזר את התנהגות הדור הראשון:

const {onRequest} = require("firebase-functions/v2/https");

exports.date = onRequest({
    // TEMPORARY FIX: remove concurrency
    cpu: "gcf_gen1",
    concurrency: 1
  },
  (req, res) => {
    // ...
});

עם זאת, זה לא מומלץ כתיקון לטווח ארוך, מכיוון שהוא מאבד את יתרונות הביצועים של פונקציות מהדור השני. במקום זאת, בדוק את השימוש במשתנים גלובליים בפונקציות שלך, והסר את ההגדרות הזמניות הללו כשתהיה מוכן.

העבר תעבורה לפונקציות החדשות של הדור השני

בדיוק כמו בעת שינוי אזור או סוג טריגר של פונקציה , תצטרך לתת לפונקציה מהדור השני שם חדש ולהעביר אליה לאט תנועה.

לא ניתן לשדרג פונקציה מדור 1 לדור שני עם אותו שם ולהפעיל firebase deploy . פעולה זו תגרום לשגיאה:

Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.

לפני שתבצע את השלבים האלה, תחילה ודא שהפונקציה שלך אינה חזקה , מכיוון שגם הגרסה החדשה וגם הגרסה הישנה של הפונקציה שלך יפעלו בו-זמנית במהלך השינוי. לדוגמה, אם יש לך פונקציה מדור ראשון המגיבה לאירועי כתיבה ב-Firestore, ודא שהגיב לכתיבה פעמיים, פעם אחת על ידי פונקציית הדור הראשון ופעם אחת על ידי פונקציית הדור השני, בתגובה לאותם אירועים יוצאת מהאפליקציה שלך ב- מצב עקבי.

  1. שנה את שם הפונקציה בקוד הפונקציות שלך. לדוגמה, שנה את שם resizeImage ל- resizeImageSecondGen .
  2. פרוס את הפונקציה, כך שגם הפונקציה המקורית של הדור הראשון וגם הפונקציה של הדור השני פועלות.
    1. במקרה של מפעילים ניתנים להתקשרות, תור משימות ו-HTTP, התחל להפנות את כל הלקוחות לפונקציית הדור השני על ידי עדכון קוד הלקוח בשם או כתובת האתר של פונקציית הדור השני.
    2. עם טריגרים ברקע, הן הפונקציות של הדור הראשון והן הדור השני יגיבו לכל אירוע מיד עם הפריסה.
  3. כאשר כל התעבורה מועברת, מחק את פונקציית הדור הראשון באמצעות פקודת firebase functions:delete Firebase CLI.
    1. לחלופין, שנה את שם פונקציית הדור השני כך שתתאים לשם של פונקציית הדור הראשון.