Mengelola fungsi


Anda dapat men-deploy, menghapus, dan mengubah fungsi menggunakan perintah Firebase CLI atau dengan menyetel opsi runtime dalam kode sumber fungsi Anda.

Men-deploy fungsi

Untuk men-deploy fungsi, jalankan perintah Firebase CLI ini:

firebase deploy --only functions

Secara default, Firebase CLI men-deploy semua fungsi di dalam sumber Anda secara bersamaan. Jika project Anda berisi lebih dari 5 fungsi, sebaiknya gunakan flag --only dengan nama fungsi tertentu untuk men-deploy fungsi yang sudah diedit saja. Men-deploy fungsi tertentu dengan cara ini akan mempercepat proses deployment dan membantu agar Anda tidak melampaui kuota deployment. Contoh:

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

Saat men-deploy fungsi dalam jumlah besar, Anda mungkin melebihi kuota standar dan menerima pesan error HTTP 429 atau 500. Untuk mengatasi hal ini, deploy fungsi secara berkelompok, yang setiap kelompoknya berisi maksimal 10 fungsi.

Baca referensi Firebase CLI untuk melihat daftar lengkap perintah yang tersedia.

Secara default, Firebase CLI akan mencari kode sumber di folder functions/. Jika ingin, Anda dapat mengatur fungsi di codebase atau beberapa kumpulan file.

Menghapus fungsi

Anda dapat menghapus fungsi yang telah di-deploy sebelumnya dengan cara berikut:

  • secara eksplisit di Firebase CLI dengan functions:delete
  • secara eksplisit di Google Cloud Console.
  • secara implisit dengan menghapus fungsi dari sumber sebelum deployment.

Semua operasi penghapusan akan meminta Anda untuk mengonfirmasi sebelum menghapus fungsi dari production.

Penghapusan fungsi secara eksplisit di Firebase CLI mendukung banyak argumen serta grup fungsi, dan dapat Anda gunakan untuk menentukan fungsi yang dijalankan di region tertentu. Selain itu, Anda juga dapat mengabaikan permintaan konfirmasi.

# 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

Dengan penghapusan fungsi secara implisit, firebase deploy akan mengurai sumber Anda dan menghapus dari production semua fungsi yang telah dihapus dari file.

Mengubah nama, region, atau pemicu fungsi

Jika Anda mengganti nama atau mengubah region atau pemicu untuk fungsi yang menangani traffic lingkungan production, ikuti langkah-langkah di bagian ini untuk menghindari hilangnya peristiwa selama modifikasi. Sebelum mengikuti langkah-langkah ini, pastikan fungsi Anda idempoten, karena versi baru dan versi lama fungsi akan berjalan pada waktu yang sama selama perubahan.

Mengganti nama fungsi

Untuk mengganti nama fungsi, buat versi baru fungsi dengan nama yang baru di sumber Anda, lalu jalankan dua perintah deployment yang berbeda. Perintah pertama men-deploy fungsi dengan nama yang baru, dan perintah kedua menghapus versi yang di-deploy sebelumnya. Misalnya, jika Anda memiliki fungsi Node.js bernama webhook yang ingin diganti namanya menjadi webhookNew, revisi kode sebagai berikut:

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

Lalu, jalankan perintah berikut untuk men-deploy fungsi yang baru:

# 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

Mengganti region fungsi

Jika Anda mengganti region yang ditentukan untuk fungsi yang menangani traffic lingkungan production, Anda dapat mencegah kehilangan peristiwa dengan melakukan langkah-langkah berikut secara berurutan:

  1. Ubah nama fungsi, dan ubah regionnya sesuai keinginan.
  2. Deploy fungsi dengan nama yang baru, sehingga untuk sementara kode yang sama akan dijalankan di kedua region.
  3. Hapus fungsi sebelumnya.

Misalnya, jika Anda memiliki fungsi bernama webhook yang saat ini berada di region fungsi default us-central1, dan Anda ingin memigrasikannya ke asia-northeast1, Anda harus terlebih dahulu mengubah kode sumber untuk mengganti nama fungsi dan merevisi region tersebut.

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

Kemudian deploy dengan menjalankan:

firebase deploy --only functions:webhookAsia

Sekarang terdapat dua fungsi identik yang berjalan: webhook berjalan di us-central1, dan webhookAsia berjalan di asia-northeast1.

Selanjutnya, hapus webhook:

firebase functions:delete webhook

Sekarang hanya ada satu fungsi - webhookAsia, yang berjalan di asia-northeast1.

Mengganti jenis pemicu fungsi

Selama pengembangan deployment Cloud Functions for Firebase dari waktu ke waktu, Anda mungkin perlu mengganti jenis pemicu fungsi karena berbagai alasan. Misalnya, Anda mungkin ingin beralih dari satu jenis peristiwa Firebase Realtime Database atau Cloud Firestore ke jenis lainnya.

Anda tidak dapat mengganti jenis peristiwa fungsi hanya dengan mengganti kode sumber dan menjalankan firebase deploy. Untuk menghindari error, ganti jenis pemicu fungsi dengan prosedur ini:

  1. Ubah kode sumber untuk menyertakan fungsi baru dengan jenis pemicu yang diinginkan.
  2. Deploy fungsi, sehingga untuk sementara fungsi lama dan fungsi baru akan dijalankan bersama-sama.
  3. Hapus fungsi lama secara eksplisit dari production menggunakan Firebase CLI.

Misalnya, jika Anda memiliki fungsi Node.js bernama objectChanged yang memiliki jenis peristiwa onChange lama dan ingin menggantinya menjadi onFinalize, ganti nama fungsi terlebih dahulu dan edit agar memiliki jenis peristiwa 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);
});

Lalu, jalankan perintah berikut untuk membuat fungsi baru terlebih dahulu, sebelum menghapus fungsi lama:

# 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

Menetapkan opsi runtime

Cloud Functions for Firebase dapat Anda gunakan untuk memilih opsi runtime, misalnya versi runtime Node.js, serta waktu tunggu per fungsi, alokasi memori, dan instance fungsi minimum/maksimum.

Sebagai praktik terbaik, opsi ini (kecuali untuk versi Node.js) harus ditetapkan pada objek konfigurasi di dalam kode fungsi tersebut. Objek RuntimeOptions ini merupakan sumber tepercaya untuk opsi runtime fungsi Anda, dan akan mengganti opsi yang ditetapkan melalui metode lain (seperti melalui Google Cloud Console atau gcloud CLI).

Jika alur kerja pengembangan Anda melibatkan penetapan opsi runtime secara manual melalui Google Cloud Console atau gcloud CLI dan Anda tidak ingin nilai ini diganti pada setiap deployment, tetapkan preserveExternalChanges ke true. Jika opsi ini ditetapkan ke true, Firebase akan menggabungkan opsi runtime yang ditetapkan dalam kode Anda dengan setelan versi fungsi yang saat ini di-deploy dengan prioritas berikut:

  1. Opsi ditetapkan dalam kode fungsi: mengganti perubahan eksternal.
  2. Opsi ditetapkan ke RESET_VALUE dalam kode fungsi: mengganti perubahan eksternal dengan nilai default.
  3. Opsi tidak ditetapkan dalam kode fungsi, tetapi ditetapkan dalam fungsi yang saat ini di-deploy: menggunakan opsi yang ditentukan dalam fungsi yang di-deploy.

Penggunaan opsi preserveExternalChanges: true tidak direkomendasikan untuk sebagian besar skenario karena kode Anda tidak akan lagi menjadi sumber tepercaya penuh untuk opsi runtime fungsi Anda. Jika Anda menggunakannya, periksa Google Cloud Console atau gunakan gcloud CLI untuk melihat konfigurasi lengkap fungsi.

Menetapkan versi Node.js

Firebase SDK untuk Cloud Functions memungkinkan pemilihan runtime Node.js. Anda dapat memilih untuk menjalankan semua fungsi dalam project secara eksklusif di lingkungan runtime yang terkait dengan salah satu versi Node.js yang didukung ini:

  • Node.js 20 (pratinjau)
  • Node.js 18
  • Node.js 16
  • Node.js 14

Untuk menetapkan versi Node.js:

Anda dapat menetapkan versi di kolom engines pada file package.json yang dibuat dalam direktori functions/ selama inisialisasi. Misalnya, agar hanya menggunakan versi 18, edit baris berikut di package.json:

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

Jika menggunakan pengelola paket Yarn atau memiliki persyaratan khusus lainnya untuk kolom engines, Anda dapat menetapkan runtime untuk Firebase SDK untuk Cloud Functions di firebase.json:

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

CLI menggunakan nilai yang ditetapkan di firebase.json sebagai preferensi untuk nilai atau rentang apa pun yang Anda tetapkan secara terpisah di package.json.

Mengupgrade runtime Node.js Anda

Untuk mengupgrade runtime Node.js:

  1. Pastikan project Anda menggunakan paket harga Blaze.
  2. Pastikan Anda menggunakan Firebase CLI v11.18.0 atau yang lebih baru.
  3. Ubah nilai engines pada file package.json yang dibuat dalam direktori functions/ selama inisialisasi. Misalnya, jika Anda melakukan upgrade dari versi 16 ke versi 18, entrinya akan terlihat seperti ini: "engines": {"node": "18"}
  4. Jika ingin, Anda dapat menguji perubahan menggunakan Firebase Local Emulator Suite.
  5. Deploy ulang semua fungsi.

Menetapkan versi Python

Firebase SDK untuk Cloud Functions versi 12.0.0 dan yang lebih baru memungkinkan pemilihan runtime Python (untuk fungsi pratinjau publik). Tetapkan versi runtime di firebase.json seperti yang ditunjukkan berikut ini:

  {
    "functions": {
      "runtime": "python310" // or python311
    }
  }

Mengontrol perilaku penskalaan

Secara default, Cloud Functions for Firebase menskalakan jumlah instance yang berjalan berdasarkan jumlah permintaan masuk, dan berpotensi untuk memperkecil skala hingga nol instance pada saat traffic berkurang. Namun, jika aplikasi Anda memerlukan latensi yang lebih rendah dan Anda ingin membatasi jumlah cold start, perilaku default ini dapat diubah dengan menentukan jumlah minimum instance container yang harus tetap aktif dan siap untuk melayani permintaan.

Demikian pula, Anda dapat menetapkan jumlah maksimum untuk membatasi penskalaan instance sebagai respons terhadap permintaan masuk. Gunakan setelan ini sebagai salah satu cara untuk mengontrol biaya Anda atau untuk membatasi jumlah koneksi ke layanan pendukung seperti ke database.

Dengan menggunakan setelan ini bersama dengan setelan serentak per instance (baru di generasi ke-2), Anda dapat mengontrol dan menyesuaikan perilaku penskalaan untuk fungsi Anda. Sifat aplikasi dan fungsi Anda akan menentukan setelan mana yang paling hemat biaya dan akan menghasilkan performa terbaik.

Untuk beberapa aplikasi dengan traffic rendah, opsi CPU yang lebih rendah tanpa multi konkurensi akan optimal. Untuk aplikasi lain di mana cold start merupakan masalah yang sangat penting, penetapan instance minimum dan konkurensi yang tinggi akan membuat sekumpulan instance selalu siap untuk menangani lonjakan traffic yang besar.

Untuk aplikasi berskala lebih kecil yang menerima traffic sangat sedikit, penetapan instance maksimum yang rendah dengan konkurensi yang tinggi akan membuat aplikasi tersebut dapat menangani burst traffic tanpa menimbulkan biaya yang berlebihan. Namun, perlu diingat bahwa jika instance maksimum ditetapkan terlalu rendah, permintaan dapat dihapus saat batas maksimum tercapai.

Mengizinkan permintaan serentak

Di Cloud Functions for Firebase (generasi ke-1), setiap instance dapat menangani satu permintaan dalam satu waktu, sehingga perilaku penskalaan ditetapkan hanya dengan setelan instance minimum dan maksimum. Selain mengontrol jumlah instance, di Cloud Functions for Firebase (generasi ke-2), Anda dapat mengontrol jumlah permintaan yang dapat dilayani oleh setiap instance secara bersamaan dengan opsi concurrency. Nilai default untuk konkurensi adalah 80, tetapi Anda dapat menetapkannya ke bilangan bulat apa pun antara 1 dan 1000.

Karena setiap instance mungkin memiliki kapasitas tambahan, fungsi dengan setelan konkurensi yang lebih tinggi dapat menyerap lonjakan traffic tanpa adanya cold start. Jika instance dikonfigurasi untuk menangani hingga 50 permintaan serentak, tetapi saat ini hanya menangani 25 permintaan, instance tersebut dapat menangani lonjakan 25 permintaan tambahan tanpa memerlukan instance baru untuk melakukan cold start. Sebaliknya, dengan setelan konkurensi hanya 1, lonjakan permintaan tersebut dapat menyebabkan 25 cold start.

Skenario yang disederhanakan ini menunjukkan potensi peningkatan efisiensi yang disebabkan oleh konkurensi. Pada kenyataannya, perilaku penskalaan untuk mengoptimalkan efisiensi dan mengurangi cold start dengan konkurensi lebih kompleks daripada itu. Konkurensi di Cloud Functions for Firebase generasi ke-2 didukung oleh Cloud Run, dan mengikuti aturan penskalaan instance container Cloud Run.

Saat bereksperimen dengan setelan konkurensi yang lebih tinggi di Cloud Functions for Firebase (generasi ke-2), perhatikan hal-hal berikut:

  • Setelan konkurensi yang lebih tinggi mungkin memerlukan CPU dan RAM yang lebih tinggi untuk mendapatkan performa optimal hingga mencapai batas praktis. Fungsi yang melakukan pemrosesan gambar atau video yang berat, misalnya, mungkin tidak memiliki resource untuk menangani 1.000 permintaan serentak, bahkan saat setelan CPU dan RAM-nya dimaksimalkan.
  • Karena Cloud Functions for Firebase (generasi ke-2) didukung oleh Cloud Run, Anda juga dapat membaca panduan Google Cloud untuk mengoptimalkan konkurensi.
  • Pastikan untuk menguji multi konkurensi secara menyeluruh di lingkungan pengujian sebelum beralih ke multi konkurensi dalam produksi.

Mempertahankan jumlah minimum instance tetap aktif

Anda dapat menetapkan jumlah minimum instance untuk fungsi dalam kode sumber. Misalnya, fungsi ini menetapkan minimum 5 instance yang harus tetap aktif:

Node.js

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

exports.getAutocompleteResponse = onCall(
  {
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  },
  (event) => {
    // Autocomplete user’s search term
  }
);

Python (pratinjau)

@https_fn.on_call(min_instances=5)
def get_autocomplete_response(event: https_fn.CallableRequest) -> https_fn.Response:

Berikut beberapa hal yang perlu dipertimbangkan saat menetapkan nilai instance minimum:

  • Jika penskalaan aplikasi oleh Cloud Functions for Firebase melampaui setelan, Anda akan mengalami cold start untuk setiap instance yang melampaui batas tersebut.
  • Cold start memiliki dampak yang paling signifikan pada aplikasi dengan lonjakan traffic yang tajam. Jika aplikasi Anda memiliki lonjakan traffic yang tajam dan nilai yang Anda tetapkan cukup tinggi sehingga cold start berkurang pada setiap peningkatan traffic, akan terjadi penurunan latensi yang signifikan. Untuk aplikasi dengan traffic yang konstan, cold start kemungkinan tidak akan memengaruhi performa secara signifikan.
  • Menetapkan instance minimum dapat dilakukan untuk lingkungan production, tetapi biasanya sebaiknya dihindari di lingkungan pengujian. Untuk melakukan penskalaan hingga nol dalam project pengujian, tetapi tetap mengurangi cold start di project lingkungan production, Anda dapat menetapkan nilai instance minimum dalam konfigurasi berparameter:

    Node.js

    const functions = require('firebase-functions');
    const { defineInt, defineString } = require('firebase-functions/params');
    
    // Define some parameters
    const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
    const welcomeMessage = defineString('WELCOME_MESSAGE');
    
    // To use configured parameters inside the config for a function, provide them 
    // directly. To use them at runtime, call .value() on them.
    export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
      (req, res) => {
        res.send(`${welcomeMessage.value()}! I am a function.`);
      }
    );
    

    Python (pratinjau)

    MIN_INSTANCES = params.IntParam("HELLO_WORLD_MININSTANCES")
    WELCOME_MESSAGE = params.StringParam("WELCOME_MESSAGE")
    
    @https_fn.on_request(min_instances=MIN_INSTANCES.value())
    def get_autocomplete_response(event: https_fn.Request) -> https_fn.Response:
        return https_fn.Response(f"{WELCOME_MESSAGE.value()} I'm a function.")
    

Membatasi jumlah maksimum instance untuk sebuah fungsi

Anda dapat menetapkan nilai untuk instance maksimum dalam kode sumber fungsi. Misalnya, fungsi ini menetapkan batas 100 instance agar tidak membebani suatu database lama fiktif:

Node.js

const { onMessagePublished } = require("firebase-functions/v2/pubsub");

exports.mirrorevents = onMessagePublished(
  { topic: "topic-name", maxInstances: 100 },
  (event) => {
    // Connect to legacy database
  }
);

Python (pratinjau)

@pubsub_fn.on_message_published(topic="topic-name", max_instances=100)
def mirrorevents(event: pubsub_fn.CloudEvent):
#  Connect to legacy database

Jika fungsi HTTP ditingkatkan skalanya hingga batas instance maksimum, permintaan baru akan dimasukkan ke dalam antrean selama 30 detik, lalu ditolak dengan kode respons 429 Too Many Requests jika tidak ada instance yang tersedia hingga saat itu.

Untuk mempelajari lebih lanjut praktik terbaik dalam menggunakan setelan instance maksimum, baca praktik terbaik dalam menetapkan instance maksimum ini.

Menetapkan waktu tunggu dan alokasi memori

Dalam beberapa kasus, fungsi Anda dapat memiliki persyaratan khusus untuk nilai waktu tunggu yang lama atau alokasi memori yang besar. Anda dapat menetapkan nilai-nilai ini di Google Cloud Console atau di kode sumber fungsi (khusus Firebase).

Untuk menetapkan alokasi memori dan waktu tunggu dalam kode sumber fungsi, gunakan opsi global untuk memori dan waktu tunggu dalam detik guna menyesuaikan virtual machine yang menjalankan fungsi Anda. Misalnya, fungsi Cloud Storage ini menggunakan memori 1 GiB dan akan berakhir setelah 300 detik:

Node.js

exports.convertLargeFile = onObjectFinalized({
  timeoutSeconds: 300,
  memory: "1GiB",
}, (event) => {
  // Do some complicated things that take a lot of memory and time
});

Python (pratinjau)

@storage_fn.on_object_finalized(timeout_sec=300, memory=options.MemoryOption.GB_1)
def convert_large_file(event: storage_fn.CloudEvent):
# Do some complicated things that take a lot of memory and time.

Nilai maksimum untuk detik waktu tunggu adalah 540, atau 9 menit.

Cara menetapkan alokasi memori dan waktu tunggu di Google Cloud Console:

  1. Di Google Cloud Console, pilih Cloud Functions for Firebase dari menu sebelah kiri.
  2. Pilih fungsi dengan mengklik namanya di daftar fungsi.
  3. Klik ikon Edit di menu atas.
  4. Pilih alokasi memori dari menu drop-down berlabel Memory allocated.
  5. Klik More untuk menampilkan opsi lanjutan, dan masukkan jumlah detik di kotak teks Timeout.
  6. Klik Save untuk mengubah fungsi.

Mengganti default CPU

Hingga 2 GB memori yang dialokasikan, setiap fungsi di Cloud Functions for Firebase (generasi ke-2) ditetapkan secara default ke satu CPU, lalu ditingkatkan menjadi 2 CPU untuk 4 dan 8 GB. Perlu diperhatikan bahwa hal ini sangat berbeda dengan perilaku default generasi ke-1, sehingga dapat mengakibatkan biaya yang sedikit lebih tinggi untuk fungsi dengan memori rendah seperti yang dinyatakan dalam tabel berikut:

RAM dialokasikan CPU default versi 1 (fraksional) CPU default versi 2 Kenaikan harga per md
128 MB 1/12 1 10.5x
256 MB 1/6 1 5.3x
512 MB 1/3 1 2.7x
1 GB 7/12 1 1.6x
2 GB 1 1 1x
4 GB 2 2 1x
8 GB 2 2 1x
16 GB t/a 4 t/a

Jika Anda lebih menyukai perilaku generasi ke-1 untuk fungsi generasi ke-2, tetapkan default generasi ke-1 sebagai opsi global:

Node.js

// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcf_gen1' });

Python (pratinjau)

# Use 1st gen behavior
set_global_options(cpu="gcf_gen1")

Untuk fungsi yang menggunakan CPU secara intensif, generasi ke-2 memberikan fleksibilitas untuk mengonfigurasi CPU tambahan. Anda dapat meningkatkan CPU berdasarkan setiap fungsi seperti yang ditunjukkan:

Node.js

// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
  // computer vision goes here
});

Python (pratinjau)

# Boost CPU in a function:
@storage_fn.on_object_finalized(cpu=2)
def analyze_image(event: storage_fn.CloudEvent):
# computer vision goes here