Zarządzaj funkcjami


Funkcje można wdrażać, usuwać i modyfikować za pomocą poleceń interfejsu wiersza poleceń Firebase lub ustawiając opcje środowiska wykonawczego w kodzie źródłowym funkcji.

Wdrażanie funkcji

Aby wdrożyć funkcje, uruchom to polecenie interfejsu wiersza poleceń Firebase:

firebase deploy --only functions

Domyślnie interfejs wiersza poleceń Firebase wdraża wszystkie funkcje w źródle w tym samym czasie. Jeśli Twój projekt zawiera więcej niż 5 funkcji, zalecamy użycie flagi --only z określonymi nazwami funkcji, aby wdrożyć tylko te, które były edytowane. Wdrożenie określonych funkcji przyspiesza proces wdrażania i pomaga uniknąć przekroczenia limitów wdrożenia. Przykład:

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

W przypadku wdrażania dużej liczby funkcji możesz przekroczyć limit standardowy i wyświetlać komunikaty o błędach HTTP 429 lub 500. Aby rozwiązać ten problem, wdrażaj funkcje w grupach po maksymalnie 10 osób.

Pełną listę dostępnych poleceń znajdziesz w dokumentacji wiersza poleceń Firebase.

Domyślnie interfejs wiersza poleceń Firebase szuka kodu źródłowego w folderze functions/. Jeśli wolisz, możesz uporządkować funkcje w bazach kodu lub w wielu zestawach plików.

Usuwanie funkcji

Oto sposoby usunięcia wcześniej wdrożonych funkcji:

  • wyraźnie w interfejsie wiersza poleceń Firebase za pomocą functions:delete.
  • wyraźnie w konsoli Google Cloud.
  • domyślnie przez usunięcie funkcji ze źródła przed wdrożeniem.

Wszystkie operacje usuwania wymagają potwierdzenia przed usunięciem funkcji ze środowiska produkcyjnego.

Jawne usuwanie funkcji w interfejsie wiersza poleceń Firebase obsługuje wiele argumentów oraz grup funkcji oraz pozwala wskazać funkcję działającą w konkretnym regionie. Monit z potwierdzeniem możesz też zastąpić.

# 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

Dzięki niejawnemu usuwaniu funkcji firebase deploy analizuje źródło i usuwa z produkcji wszystkie funkcje usunięte z pliku.

Modyfikowanie nazwy, regionu i aktywatora funkcji

Jeśli zmieniasz nazwę regionu lub aktywator dla funkcji, które obsługują ruch produkcyjny, wykonaj czynności opisane w tej sekcji, aby uniknąć utraty zdarzeń podczas modyfikacji. Zanim wykonasz te czynności, upewnij się, że funkcja jest idempotentna, ponieważ w trakcie wprowadzania zmian będzie działać w tym samym czasie zarówno nowa, jak i stara wersja funkcji.

Zmienianie nazwy funkcji

Aby zmienić nazwę funkcji, utwórz w źródle nową wersję funkcji o nowej nazwie, a następnie uruchom 2 osobne polecenia wdrożenia. Pierwsze polecenie wdraża funkcję o nowej nazwie, a drugie usuwa wcześniej wdrożoną wersję. Jeśli np. masz funkcję Node.js o nazwie webhook, którą chcesz zmienić na webhookNew, zmień kod w ten sposób:

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

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

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

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

Następnie uruchom te polecenia, aby wdrożyć nową funkcję:

# 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

Zmienianie regionu lub regionów funkcji

Jeśli zmieniasz wskazane regiony funkcji, która obsługuje ruch produkcyjny, możesz zapobiec utracie zdarzeń, wykonując te czynności po kolei:

  1. Zmień nazwę funkcji i odpowiednio zmień jej region lub regiony.
  2. Wdróż funkcję o zmienionej nazwie, co spowoduje tymczasowe uruchamianie tego samego kodu w obu zestawach regionów.
  3. Usuń poprzednią funkcję.

Jeśli np. masz funkcję o nazwie webhook, która obecnie znajduje się w domyślnym regionie funkcji us-central1 i chcesz ją przenieść do asia-northeast1, musisz najpierw zmodyfikować kod źródłowy, aby zmienić nazwę tej funkcji i poprawić region.

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

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

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

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

Następnie wdróż, uruchamiając polecenie:

firebase deploy --only functions:webhookAsia

Teraz uruchomione są 2 identyczne funkcje: webhook – w us-central1, a webhookAsia – w asia-northeast1.

Następnie usuń webhook:

firebase functions:delete webhook

Teraz jest tylko jedna funkcja – webhookAsia, która jest uruchomiona w asia-northeast1.

Zmienianie typu aktywatora funkcji

W miarę rozwoju wdrożenia Cloud Functions dla Firebase w trakcie tworzenia wdrożenia Cloud Functions dla Firebase może być konieczna zmiana typu aktywatora funkcji z różnych powodów. Możesz na przykład zmienić jeden typ zdarzenia w Bazie danych czasu rzeczywistego Firebase lub Cloud Firestore na inny.

Nie można zmienić typu zdarzenia funkcji przez zmianę kodu źródłowego i uruchomienie firebase deploy. Aby uniknąć błędów, zmień typ aktywatora funkcji w ten sposób:

  1. Zmodyfikuj kod źródłowy, aby uwzględnić nową funkcję z wybranym typem aktywatora.
  2. Wdrożenie funkcji, co spowoduje tymczasowe uruchomienie zarówno starej, jak i nowej funkcji.
  3. Wyraźnie usuń starą funkcję ze środowiska produkcyjnego za pomocą interfejsu wiersza poleceń Firebase.

Jeśli na przykład masz funkcję Node.js o nazwie objectChanged ze starszym typem zdarzenia onChange i chcesz zmienić ją na onFinalize, najpierw zmień nazwę tej funkcji i wyedytuj ją, tak aby przyjmował typ zdarzenia onFinalize.

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

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

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

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

Następnie uruchom te polecenia, aby najpierw utworzyć nową funkcję, a dopiero potem usunąć starą:

# 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

Ustawianie opcji środowiska wykonawczego

Cloud Functions dla Firebase pozwala wybrać opcje środowiska wykonawczego, takie jak wersja środowiska wykonawczego Node.js i czas oczekiwania na poszczególne funkcje, przydział pamięci oraz minimalna i maksymalna liczba instancji funkcji.

Sprawdzoną metodą jest ustawienie tych opcji (oprócz wersji Node.js) w obiekcie konfiguracji w kodzie funkcji. Ten obiekt RuntimeOptions jest źródłem wiarygodnych opcji środowiska wykonawczego Twojej funkcji i zastąpi opcje ustawione inną metodą (np. za pomocą konsoli Google Cloud lub interfejsu wiersza poleceń gcloud).

Jeśli Twój przepływ pracy programisty obejmuje ręczne ustawianie opcji środowiska wykonawczego za pomocą konsoli Google Cloud lub interfejsu wiersza poleceń gcloud i nie chcesz zastępować tych wartości przy każdym wdrożeniu, ustaw opcję preserveExternalChanges na true. Gdy ta opcja jest ustawiona na true, Firebase scala opcje środowiska wykonawczego ustawione w kodzie z ustawieniami aktualnie wdrożonej wersji funkcji i ma następujący priorytet:

  1. Opcja jest ustawiona w kodzie funkcji: zastąp zmiany zewnętrzne.
  2. Opcja ma wartość RESET_VALUE w kodzie funkcji: zastąp zmiany zewnętrzne wartością domyślną.
  3. Opcja nie jest ustawiona w kodzie funkcji, ale jest ustawiona w obecnie wdrożonej funkcji: użyj opcji określonej we wdrożonej funkcji.

Korzystanie z opcji preserveExternalChanges: true nie jest zalecane w większości scenariuszy, ponieważ Twój kod nie będzie już pełnym źródłem informacji o opcjach środowiska wykonawczego dla funkcji. Jeśli go używasz, sprawdź konsolę Google Cloud lub użyj interfejsu wiersza poleceń gcloud, aby wyświetlić pełną konfigurację funkcji.

Ustaw wersję Node.js

Pakiet SDK Firebase dla Cloud Functions umożliwia wybór środowiska wykonawczego Node.js. Możesz uruchomić wszystkie funkcje w projekcie wyłącznie w środowisku wykonawczym odpowiadającym jednej z tych obsługiwanych wersji Node.js:

  • Node.js 20 (wersja przedpremierowa)
  • Node.js 18
  • Node.js 16
  • Node.js 14

Aby ustawić wersję Node.js:

Wersję możesz ustawić w polu engines w pliku package.json, który został utworzony w katalogu functions/ podczas inicjowania. Na przykład aby użyć tylko wersji 18, edytuj ten wiersz w pliku package.json:

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

Jeśli korzystasz z menedżera pakietów Yarn lub masz inne wymagania dotyczące pola engines, możesz zamiast tego ustawić środowisko wykonawcze pakietu SDK Firebase dla Cloud Functions w firebase.json:

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

Interfejs wiersza poleceń używa wartości ustawionej w firebase.json zamiast wartości lub zakresu ustawionych oddzielnie w package.json.

Uaktualnij środowisko wykonawcze Node.js

Aby uaktualnić środowisko wykonawcze Node.js:

  1. Sprawdź, czy Twój projekt jest objęty abonamentem Blaze.
  2. Upewnij się, że używasz interfejsu wiersza poleceń Firebase w wersji 11.18.0 lub nowszej.
  3. Zmień wartość engines w pliku package.json, który został utworzony w katalogu functions/ podczas inicjowania. Jeśli na przykład aktualizujesz wersję 16 do 18, wpis powinien wyglądać tak: "engines": {"node": "18"}
  4. Opcjonalnie przetestuj zmiany za pomocą Pakietu emulatorów lokalnych Firebase.
  5. Wdróż ponownie wszystkie funkcje.

Kontroluj zachowanie skalowania

Domyślnie Cloud Functions dla Firebase skaluje liczbę działających instancji na podstawie liczby żądań przychodzących, potencjalnie skalując ją w dół do zera w okresach ograniczonego ruchu. Jeśli jednak aplikacja wymaga krótszego czasu oczekiwania i chcesz ograniczyć liczbę uruchomień „na zimno”, możesz zmienić to domyślne działanie, określając minimalną liczbę instancji kontenera, które mają być utrzymywane w trybie gotowości do obsługi żądań.

Możesz też ustawić maksymalną liczbę, aby ograniczyć skalowanie instancji w odpowiedzi na żądania przychodzące. Dzięki temu ustawieniu możesz kontrolować koszty lub ograniczyć liczbę połączeń do usługi backendu, na przykład z bazą danych.

Zmniejsz liczbę uruchomień „na zimno”

Aby ustawić minimalną liczbę instancji funkcji w kodzie źródłowym, użyj metody runWith. Ta metoda akceptuje obiekt JSON zgodny z interfejsem RuntimeOptions, który określa wartość minInstances. Na przykład ta funkcja ustawia co najmniej 5 instancji do utrzymania ciepła:

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
    });

Oto kilka kwestii, które warto wziąć pod uwagę podczas ustawiania wartości parametru minInstances:

  • Jeśli Cloud Functions dla Firebase skaluje Twoją aplikację powyżej ustawienia minInstances, nastąpi uruchomienie „na zimno” każdej instancji powyżej tego progu.
  • Największy wpływ na aplikacje o dużym natężeniu ruchu mają opóźnienia z zimna. Jeśli ruch w aplikacji jest duży i ustawisz wartość minInstances na tyle wysoką, by przy każdym wzroście ruchu liczba uruchomień „na zimno” była ograniczana, czas oczekiwania będzie znacznie zmniejszony. W przypadku aplikacji o ciągłym ruchu uruchamianie „na zimno” nie powinno znacząco wpłynąć na wydajność.
  • Ustawianie minimalnej liczby instancji może być przydatne w środowiskach produkcyjnych, ale w środowiskach testowych zwykle należy tego unikać. Aby w projekcie testowym skalować się do zera, a jednocześnie ograniczyć uruchomienia „na zimno” w projekcie produkcyjnym, możesz ustawić minInstances na podstawie zmiennej środowiskowej 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
        });
    

Ogranicz maksymalną liczbę instancji funkcji

Aby ustawić maksymalną liczbę instancji w kodzie źródłowym funkcji, użyj metody runWith. Ta metoda akceptuje obiekt JSON zgodny z interfejsem RuntimeOptions, który określa wartości w maxInstances. Na przykład ta funkcja ustawia limit 100 instancji, aby nie przeciążyć hipotetycznej starszej bazy danych:

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

Jeśli funkcja HTTP zostanie skalowana do limitu maxInstances, nowe żądania będą umieszczane w kolejce przez 30 sekund, a następnie odrzucane z kodem odpowiedzi 429 Too Many Requests, jeśli do tego czasu nie będzie dostępna żadna instancja.

Aby dowiedzieć się więcej o sprawdzonych metodach korzystania z ustawień maksymalnej liczby instancji, zapoznaj się z tymi sprawdzonymi metodami korzystania z maxInstances.

Ustaw limit czasu i alokację pamięci

W niektórych przypadkach funkcje mogą mieć specjalne wymagania dotyczące długiego limitu czasu lub dużej ilości pamięci. Te wartości możesz ustawić w konsoli Google Cloud lub w kodzie źródłowym funkcji (tylko w Firebase).

Aby ustawić przydział pamięci i czas oczekiwania w kodzie źródłowym funkcji, użyj parametru runWith wprowadzonego w pakiecie SDK Firebase dla Cloud Functions 2.0.0. Ta opcja środowiska wykonawczego akceptuje obiekt JSON zgodny z interfejsem RuntimeOptions, który określa wartości dla timeoutSeconds i memory. Na przykład ta funkcja pamięci masowej wykorzystuje 1 GB pamięci, a limit czasu oczekiwania wynosi 300 sekund:

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
    });

Maksymalna wartość parametru timeoutSeconds to 540, czyli 9 minut. Ilość pamięci przyznanej funkcji odpowiada procesorowi przydzielonemu do tej funkcji, zgodnie z tą listą prawidłowych wartości funkcji memory:

  • 128MB – 200 MHz
  • 256MB – 400 MHz
  • 512MB – 800 MHz
  • 1GB – 1,4 GHz
  • 2GB – 2,4 GHz
  • 4GB – 4,8 GHz
  • 8GB – 4,8 GHz

Aby ustawić przydział pamięci i czas oczekiwania w konsoli Google Cloud:

  1. W konsoli Google Cloud wybierz Cloud Functions w menu po lewej stronie.
  2. Wybierz funkcję, klikając jej nazwę na liście funkcji.
  3. W menu u góry kliknij ikonę Edytuj.
  4. Wybierz alokację pamięci z menu Przydzielona pamięć.
  5. Kliknij Więcej, aby wyświetlić opcje zaawansowane, i wpisz liczbę sekund w polu tekstowym Limit czasu.
  6. Kliknij Zapisz, aby zaktualizować funkcję.