ניהול פונקציות


אפשר לפרוס, למחוק ולשנות פונקציות באמצעות פקודות CLI של Firebase או על ידי הגדרת אפשרויות של זמן ריצה בקוד המקור של הפונקציות.

פריסת פונקציות

כדי לפרוס את הפונקציות, מריצים את הפקודה Firebase ב-CLI:

firebase deploy --only functions

כברירת מחדל, ה-CLI של Firebase פורס את כל הפונקציות שבתוכו במקור שלכם בו-זמנית. אם הפרויקט מכיל יותר מ-5 פונקציות, מומלץ להשתמש בדגל --only עם שמות פונקציות ספציפיים כדי לפרוס רק את הפונקציות שערכתם. פריסה של פונקציות ספציפיות בדרך הזו מזרזת את תהליך הפריסה ומונעת מצב שבו תגיעו למכסות הפריסה. לדוגמה:

firebase deploy --only functions:addMessage,functions:makeUppercase

כשפורסים מספר גדול של פונקציות, יכול להיות שתחרגו מהמכסה הרגילה ותקבלו הודעות שגיאה מסוג HTTP 429 או 500. כדי לפתור את הבעיה לפרוס פונקציות בקבוצות של 10 לכל היותר.

אפשר לעיין בחומר העזר בנושא CLI של Firebase כדי לעיין ברשימה המלאה של הכלים הזמינים. פקודות.

כברירת מחדל, ה-CLI של Firebase מחפש בתיקייה functions/ את קוד המקור. אם מעדיפים, אפשר לארגן פונקציות בבסיסי קוד או בכמה קבוצות של קבצים.

מחיקת פונקציות

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

  • באופן מפורש ב-CLI של Firebase עם functions:delete
  • באופן מפורש במסוף Google Cloud.
  • במרומז על ידי הסרת הפונקציה מהמקור לפני הפריסה.

כל פעולות המחיקה תופיע הנחיה לאשר לפני הסרת הפונקציה מתהליך הייצור.

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

# Delete all functions that match the specified name in all regions.
firebase functions:delete myFunction
# Delete a specified function running in a specific region.
firebase functions:delete myFunction --region us-east-1
# Delete more than one function
firebase functions:delete myFunction myOtherFunction
# Delete a specified functions group.
firebase functions:delete groupA
# Bypass the confirmation prompt.
firebase functions:delete myFunction --force

במחיקה משתמעת של פונקציה, firebase deploy מנתח את המקור שלך מסירה מהייצור פונקציות שהוסרו מהקובץ.

שינוי השם, האזור או הטריגר של פונקציה

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

שינוי שם של פונקציה

כדי לשנות שם של פונקציה, צריך ליצור גרסה חדשה עם השם החדש של הפונקציה בקוד המקור ולאחר מכן מריצים שתי פקודות פריסה נפרדות. הפקודה הראשונה פורסת את הפונקציה עם השם החדש, והפקודה השנייה מסירה את הגרסה שפרסמתם בעבר. לדוגמה, אם יש לכם פונקציית Node.js שנקרא webhook, שרוצים משנים ל-webhookNew, משנים את הקוד באופן הבא:

// before
const functions = require('firebase-functions/v1');

exports.webhook = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

// after
const functions = require('firebase-functions/v1');

exports.webhookNew = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

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

# Deploy new function called webhookNew
firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both webhookNew and webhook are running

# Delete webhook
firebase functions:delete webhook

שינוי האזור או האזורים של פונקציה

אם אתם משנים את האזורים שצוינו עבור שמטפל בתנועה לסביבת הייצור, אפשר למנוע אובדן אירועים באמצעות ביצוע השלבים הבאים לפי הסדר:

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

לדוגמה, אם יש לכם פונקציה בשם webhook שנמצאת כרגע באזור ברירת המחדל של הפונקציות, us-central1, ואתם רוצים להעביר אותה ל-asia-northeast1, קודם צריך לשנות את קוד המקור כדי לשנות את שם הפונקציה ולעדכן את האזור.

// before
const functions = require('firebase-functions/v1');

exports.webhook = functions
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

// after
const functions = require('firebase-functions/v1');

exports.webhookAsia = functions
    .region('asia-northeast1')
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

לאחר מכן פורסים את הקוד באמצעות הפקודה:

firebase deploy --only functions:webhookAsia

עכשיו יש שתי פונקציות זהות שפועלות: webhook פועלת ב-us-central1, ו-webhookAsia פועל ב-asia-northeast1.

לאחר מכן, מוחקים את webhook:

firebase functions:delete webhook

עכשיו יש רק פונקציה אחת – webhookAsia, שפועלת ב-asia-northeast1.

שינוי סוג הטריגר של פונקציה

ככל שמפתחים את הפריסה של Cloud Functions for Firebase לאורך זמן, אפשר צריכים לשנות את סוג הטריגר של פונקציה מסיבות שונות. לדוגמה, יכול להיות שתרצו לשנות סוג של אירוע Firebase Realtime Database או Cloud Firestore לסוג אחר.

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

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

לדוגמה, אם יש לכם פונקציית Node.js בשם objectChanged עם סוג האירוע הקודם onChange, ואתם רוצים לשנות אותו ל-onFinalize, קודם צריך לשנות את שם הפונקציה ולערוך אותה כך שתכלול את סוג האירוע onFinalize.

// before
const functions = require('firebase-functions/v1');

exports.objectChanged = functions.storage.object().onChange((object) => {
    return console.log('File name is: ', object.name);
});

// after
const functions = require('firebase-functions/v1');

exports.objectFinalized = functions.storage.object().onFinalize((object) => {
    return console.log('File name is: ', object.name);
});

לאחר מכן, מריצים את הפקודות הבאות כדי ליצור את הפונקציה החדשה לפני שמוחקים את הפונקציה הישנה:

# Create new function objectFinalized
firebase deploy --only functions:objectFinalized

# Wait until deployment is done; now both objectChanged and objectFinalized are running

# Delete objectChanged
firebase functions:delete objectChanged

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

בעזרת Cloud Functions for Firebase אפשר לבחור אפשרויות בסביבת זמן הריצה, כמו גרסת סביבת זמן הריצה של Node.js, זמן קצוב לתפוגה לכל פונקציה, הקצאת זיכרון ומספר המכונות המינימלי/מקסימלי של הפונקציה.

מומלץ להגדיר את האפשרויות האלה (למעט גרסת Node.js) אובייקט של הגדרה בתוך קוד הפונקציה. הזה RuntimeOptions הוא מקור האמת לאפשרויות זמן הריצה של הפונקציה, לשנות אפשרויות שהוגדרו בכל שיטה אחרת (למשל דרך מסוף Google Cloud). או ב-CLI של gcloud).

אם תהליך הפיתוח שלך כולל הגדרה ידנית של אפשרויות זמן ריצה דרך במסוף Google Cloud או ב-CLI של gcloud אתם לא רוצים שהערכים האלה יהיו תבוטל בכל פריסה, צריך להגדיר את האפשרות preserveExternalChanges ל-true. כשהאפשרות הזו מוגדרת ל-true, מערכת Firebase משלבת את אפשרויות סביבת זמן הריצה שמוגדרות בקוד עם ההגדרות של הגרסה הנוכחית של הפונקציה שנפרסה, לפי סדר העדיפויות הבא:

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

לא מומלץ להשתמש באפשרות preserveExternalChanges: true ברוב התרחישים, כבר לא יהיו המקור המלא לאימות לאפשרויות זמן הריצה למשימות ספציפיות. אם אתם משתמשים בה, תוכלו לבדוק את ההגדרה המלאה של הפונקציה במסוף Google Cloud או באמצעות ה-CLI של gcloud.

הגדרת גרסת Node.js

ערכת ה-SDK של Firebase ל-Cloud Functions מאפשרת לבחור סביבת זמן ריצה של Node.js. אפשר להריץ את כל הפונקציות בפרויקט רק בזמן הריצה שתואמת לאחת מהגרסאות הנתמכות הבאות של Node.js:

  • Node.js 20 (גרסת תצוגה מקדימה)
  • Node.js 18
  • Node.js 16
  • Node.js 14

כדי להגדיר את גרסת Node.js:

אפשר להגדיר את הגרסה בשדה engines בממשק package.json שנוצר בספרייה functions/ במהלך האתחול. לדוגמה, כדי להשתמש רק גרסה 18, אפשר לערוך את השורה הזו בpackage.json:

  "engines": {"node": "18"}

אם אתם משתמשים במנהל החבילות Yarn או שיש לכם דרישות ספציפיות אחרות לשדה engines, תוכלו להגדיר את סביבת זמן הריצה של ה-SDK של Firebase עבור Cloud Functions ב-firebase.json במקום זאת:

  {
    "functions": {
      "runtime": "nodejs18" // or nodejs14, nodejs16 or nodejs20
    }
  }

ה-CLI משתמש בערך שמוגדר ב-firebase.json במקום בערך או בטווח שתגדירו בנפרד ב-package.json.

שדרוג זמן הריצה של Node.js

כדי לשדרג את זמן הריצה של Node.js:

  1. צריך לוודא שהפרויקט נמצא תוכנית תמחור ותשלומים מפולפלת.
  2. חשוב לוודא שאתם משתמשים ב-Firebase CLI בגרסה 11.18.0 ואילך.
  3. שינוי הערך engines בקובץ package.json שנוצר ב- ספריית functions/ במהלך האתחול. לדוגמה, אם משדרגים מגרסה 16 לגרסה 18, הרשומה צריכה להיראות כך: "engines": {"node": "18"}
  4. אפשר גם לבדוק את השינויים באמצעות Firebase Local Emulator Suite
  5. פורסים מחדש את כל הפונקציות.

שליטה בהתנהגות של שינוי קנה מידה

כברירת מחדל, Cloud Functions for Firebase משתנה בהתאם למספר הבקשות הנכנסות, כך שיכול להיות שהוא יגיע לאפס מכונות בזמנים של תנועה מופחתת. עם זאת, אם האפליקציה מחייבת כדי להגביל את מספר ההפעלות במצב התחלתי (cold start), אפשר לשנות את ההגדרה הזו את התנהגות ברירת המחדל באמצעות ציון מספר מינימלי של מופעי קונטיינרים להישאר חמים ומוכן לקבל בקשות.

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

צמצום מספר ההפעלות הקרות

כדי להגדיר את מספר המכונות המינימלי של פונקציה בקוד המקור, משתמשים ב-method‏ runWith. השיטה הזו מקבלת אובייקט JSON שתואם לממשק RuntimeOptions, שמגדיר את הערך של minInstances. לדוגמה, הפונקציה הזו מגדירה לפחות 5 מופעים כדי להתחמם:

exports.getAutocompleteResponse = functions
    .runWith({
      // Keep 5 instances warm for this latency-critical function
      minInstances: 5,
    })
    .https.onCall((data, context) => {
      // Autocomplete a user's search term
    });

יש כמה נקודות שכדאי להביא בחשבון כשמגדירים ערך ל-minInstances:

  • אם Cloud Functions for Firebase יעלה את גודל האפליקציה מעל ההגדרה של minInstances, תתבצע הפעלה במצב התחלתי (cold start) בכל אחד מהמופעים מעל הסף הזה.
  • הפעלה במצב התחלתי (cold start) משפיעה בצורה הכי חמורה על אפליקציות עם תנועה קוצנית. אם באפליקציה יש עליות חדות בנפח התנועה, והגדרתם ערך גבוה מספיק של minInstances כדי לצמצם את מספר הפעמים שהאפליקציה מופעלת מחדש בכל עלייה בנפח התנועה, זמן האחזור יצומצם באופן משמעותי. באפליקציות עם תנועה קבועה, סביר להניח שהפעלות ראשוניות לא ישפיעו באופן משמעותי על הביצועים.
  • הגדרת מספר מינימלי של מכונות יכולה להיות הגיונית בסביבות ייצור, אבל בדרך כלל כדאי להימנע מכך בסביבות בדיקה. כדי לשנות את קנה המידה לאפס בפרויקט הבדיקה, אבל עדיין לצמצם את ההפעלה במצב התחלתי בפרויקט הייצור, אפשר להגדיר את minInstances על סמך משתנה הסביבה FIREBASE_CONFIG:

    // Get Firebase project id from `FIREBASE_CONFIG` environment variable
    const envProjectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
    
    exports.renderProfilePage = functions
        .runWith({
          // Keep 5 instances warm for this latency-critical function
          // in production only. Default to 0 for test projects.
          minInstances: envProjectId === "my-production-project" ? 5 : 0,
        })
        .https.onRequest((req, res) => {
          // render some html
        });
    

הגבלת מספר המופעים המקסימלי של פונקציה

כדי להגדיר מספר מקסימלי של מכונות בקוד המקור של הפונקציה, משתמשים בפונקציה runWith . השיטה הזו מקבלת אובייקט JSON שתואם לממשק RuntimeOptions, שמגדיר ערכים ל-maxInstances. לדוגמה, הפונקציה הזו מגדירה מגבלה של 100 מכונות כדי לא להעמיס על מסד נתונים היפותטי מדור קודם:

exports.mirrorOrdersToLegacyDatabase = functions
    .runWith({
      // Legacy database only supports 100 simultaneous connections
      maxInstances: 100,
    })
    .firestore.document("orders/{orderId}")
    .onWrite((change, context) => {
      // Connect to legacy database
    });

אם פונקציית HTTP מתאימה למגבלה של maxInstances, בקשות חדשות הועבר לתור למשך 30 שניות ולאחר מכן נדחה עם קוד תגובה 429 Too Many Requests אם לא תהיה אף מכונה זמינה עד אז.

למידע נוסף על שיטות מומלצות לשימוש בהגדרות של מספר המכונות המקסימלי, תוכלו לעיין בשיטות המומלצות לשימוש ב-maxInstances.

הגדרת זמן קצוב להמתנה והקצאת זיכרון

במקרים מסוימים, יכול להיות שלפונקציות שלכם יהיו דרישות מיוחדות למתן זמן קצוב ארוך או להקצאת כמות גדולה של זיכרון. אפשר להגדיר את הערכים האלה במסוף Google Cloud או בקוד המקור של הפונקציה (Firebase בלבד).

כדי להגדיר הקצאת זיכרון וטיימר תפוגה בקוד המקור של הפונקציות, משתמשים בפרמטר runWith שהוצג ב-Firebase SDK עבור Cloud Functions 2.0.0. האפשרות הזו של סביבת זמן הריצה מקבלת באובייקט JSON שתואם RuntimeOptions שמגדיר את הערכים של timeoutSeconds ושל memory. לדוגמה, פונקציית האחסון הזו משתמשת ב-1GB של זיכרון ותקופת הקצוב לתפוגה שלה היא 300 שניות:

exports.convertLargeFile = functions
    .runWith({
      // Ensure the function has enough memory and time
      // to process large files
      timeoutSeconds: 300,
      memory: "1GB",
    })
    .storage.object()
    .onFinalize((object) => {
      // Do some complicated things that take a lot of memory and time
    });

הערך המקסימלי של timeoutSeconds הוא 540, או 9 דקות. כמות הזיכרון שמוענקת לפונקציה תואמת למעבד שהוקצה לפונקציה, כפי שמפורט ברשימת הערכים החוקיים של הפונקציה memory:

  • 128MB – 200MHz
  • 256MB — 400MHz
  • 512MB — 800MHz
  • 1GB — 1.4 GHz
  • 2GB — 2.4 GHz
  • 4GB — 4.8 GHz
  • 8GB — 4.8 GHz

כדי להגדיר הקצאת זיכרון וזמן קצוב לתפוגה במסוף Google Cloud:

  1. במסוף Google Google Cloud, בוחרים באפשרות Cloud Functions מתוך תפריט שמאלי.
  2. לוחצים על השם של הפונקציה ברשימה כדי לבחור אותה.
  3. לוחצים על הסמל עריכה בתפריט העליון.
  4. בוחרים הקצאת זיכרון מהתפריט הנפתח Memory allocated.
  5. לוחצים על עוד כדי להציג את האפשרויות המתקדמות, ומזינים מספר שניות בתיבת הטקסט זמן קצוב לתפוגה.
  6. כדי לעדכן את הפונקציה, לוחצים על Save.