Quản lý hàm


Bạn có thể triển khai, xoá và sửa đổi các hàm bằng lệnh CLI của Firebase hoặc bằng cách đặt các tuỳ chọn thời gian chạy trong mã nguồn của hàm.

Triển khai hàm

Để triển khai các hàm, hãy chạy lệnh Firebase CLI sau:

firebase deploy --only functions

Theo mặc định, Giao diện dòng lệnh (CLI) của Firebase sẽ triển khai tất cả hàm bên trong nguồn của bạn cùng một lúc. Nếu dự án của bạn chứa hơn 5 hàm, bạn nên sử dụng cờ --only có tên hàm cụ thể để chỉ triển khai các hàm bạn đã chỉnh sửa. Triển khai các hàm cụ thể theo cách này giúp đẩy nhanh quá trình triển khai và giúp bạn tránh rơi vào hạn mức triển khai. Ví dụ:

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

Khi triển khai số lượng lớn hàm, bạn có thể vượt quá hạn mức chuẩn và nhận được thông báo lỗi HTTP 429 hoặc 500. Để giải quyết vấn đề này, hãy triển khai các hàm theo nhóm có từ 10 hàm trở xuống.

Hãy xem tài liệu tham khảo về Giao diện dòng lệnh (CLI) của Firebase để biết danh sách đầy đủ các lệnh có sẵn.

Theo mặc định, Firebase CLI sẽ tìm mã nguồn trong thư mục functions/. Nếu muốn, bạn có thể sắp xếp các hàm trong cơ sở mã hoặc nhiều nhóm tệp.

Xoá hàm

Bạn có thể xoá các hàm đã triển khai trước đây theo những cách sau:

  • một cách rõ ràng trong Giao diện dòng lệnh (CLI) của Firebase với functions:delete
  • một cách rõ ràng trong bảng điều khiển Google Cloud.
  • một cách ngầm ẩn bằng cách xoá hàm đó khỏi nguồn trước khi triển khai.

Tất cả các thao tác xoá đều nhắc bạn xác nhận trước khi xoá hàm này khỏi phiên bản chính thức.

Tính năng xoá hàm rõ ràng trong Giao diện dòng lệnh (CLI) của Firebase hỗ trợ nhiều đối số cũng như nhóm hàm và cho phép bạn chỉ định một hàm chạy trong một khu vực cụ thể. Ngoài ra, bạn có thể ghi đè lời nhắc xác nhận.

# 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

Với thao tác xoá hàm ngầm ẩn, firebase deploy sẽ phân tích cú pháp nguồn của bạn và xoá khỏi phiên bản chính thức mọi hàm đã bị xoá khỏi tệp.

Sửa đổi tên, khu vực hoặc điều kiện kích hoạt của hàm

Nếu bạn đổi tên hoặc thay đổi vùng hoặc trình kích hoạt cho các hàm đang xử lý lưu lượng truy cập chính thức, hãy làm theo các bước trong phần này để tránh bị mất sự kiện trong quá trình sửa đổi. Trước khi bạn làm theo các bước này, đầu tiên hãy đảm bảo rằng hàm của bạn không thay đổi, vì cả phiên bản mới và phiên bản cũ của hàm sẽ chạy cùng lúc trong quá trình thay đổi.

Đổi tên hàm

Để đổi tên một hàm, hãy tạo một phiên bản mới đã đổi tên của hàm trong nguồn, sau đó chạy 2 lệnh triển khai riêng biệt. Lệnh đầu tiên triển khai hàm mới được đặt tên và lệnh thứ hai sẽ xoá phiên bản đã triển khai trước đó. Ví dụ: nếu bạn có một hàm Node.js tên là webhook mà bạn muốn thay đổi thành webhookNew, hãy sửa đổi mã như sau:

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

Sau đó, chạy các lệnh sau để triển khai hàm mới:

# 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

Thay đổi vùng hoặc các vùng của hàm

Nếu đang thay đổi khu vực được chỉ định cho một hàm đang xử lý lưu lượng truy cập thực tế, thì bạn có thể ngăn chặn tình trạng mất sự kiện bằng cách thực hiện các bước sau theo thứ tự:

  1. Đổi tên hàm và thay đổi vùng hoặc các vùng của hàm như mong muốn.
  2. Triển khai hàm được đổi tên, dẫn đến việc tạm thời chạy cùng một mã trong cả hai nhóm khu vực.
  3. Xoá hàm trước đó.

Ví dụ: nếu bạn có một hàm tên là webhook hiện đang nằm trong vùng hàm mặc định của us-central1 và bạn muốn di chuyển hàm đó sang asia-northeast1, trước tiên, bạn cần sửa đổi mã nguồn để đổi tên hàm và sửa đổi khu vực.

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

Sau đó, hãy triển khai bằng cách chạy:

firebase deploy --only functions:webhookAsia

Hiện có 2 hàm giống hệt nhau đang chạy: webhook đang chạy trong us-central1webhookAsia đang chạy trong asia-northeast1.

Sau đó, xoá webhook:

firebase functions:delete webhook

Hiện tại, chỉ có một hàm duy nhất là webhookAsia đang chạy trong asia-northeast1.

Thay đổi loại điều kiện kích hoạt của hàm

Khi phát triển Chức năng đám mây để triển khai Firebase theo thời gian, bạn có thể cần thay đổi loại điều kiện kích hoạt của hàm vì nhiều lý do. Ví dụ: bạn có thể muốn thay đổi từ một loại sự kiện Cơ sở dữ liệu theo thời gian thực của Firebase hoặc Cloud Firestore thành một loại khác.

Bạn không thể thay đổi loại sự kiện của hàm chỉ bằng cách thay đổi mã nguồn và chạy firebase deploy. Để tránh lỗi, hãy thay đổi loại điều kiện kích hoạt của hàm theo quy trình sau:

  1. Sửa đổi mã nguồn để bao gồm một hàm mới có loại điều kiện kích hoạt mong muốn.
  2. Triển khai hàm này, giúp tạm thời chạy cả hàm cũ và hàm mới.
  3. Xoá hoàn toàn hàm cũ khỏi phiên bản chính thức bằng cách sử dụng Giao diện dòng lệnh (CLI) của Firebase.

Ví dụ: nếu bạn có một hàm Node.js tên là objectChanged. Hàm này có loại sự kiện onChange cũ và bạn muốn thay đổi thành onFinalize, trước tiên, hãy đổi tên hàm và chỉnh sửa để có loại sự kiện 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);
});

Sau đó, chạy các lệnh sau để tạo hàm mới trước khi xoá hàm cũ:

# 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

Đặt tuỳ chọn thời gian chạy

Chức năng đám mây cho Firebase cho phép bạn chọn các tuỳ chọn thời gian chạy, chẳng hạn như phiên bản thời gian chạy Node.js và thời gian chờ của mỗi hàm, phân bổ bộ nhớ và các thực thể hàm tối thiểu/tối đa.

Tốt nhất là bạn nên đặt các tuỳ chọn này (ngoại trừ phiên bản Node.js) trên một đối tượng cấu hình bên trong mã hàm. Đối tượng RuntimeOptions này là nguồn đáng tin cậy cho các tuỳ chọn thời gian chạy của hàm và sẽ ghi đè các tuỳ chọn được thiết lập qua bất kỳ phương thức nào khác (chẳng hạn như qua bảng điều khiển Google Cloud hoặc gcloud CLI).

Nếu quy trình phát triển của bạn liên quan đến việc thiết lập các tuỳ chọn thời gian chạy theo cách thủ công qua Google Cloud Console hoặc gcloud CLI và bạn không muốn các giá trị này bị ghi đè trong mỗi lần triển khai, hãy đặt tuỳ chọn preserveExternalChanges thành true. Khi bạn đặt tuỳ chọn này thành true, Firebase sẽ hợp nhất các tuỳ chọn thời gian chạy được đặt trong mã của bạn với các chế độ cài đặt của phiên bản hàm đang được triển khai với mức độ ưu tiên sau:

  1. Tuỳ chọn được đặt trong mã hàm: ghi đè các thay đổi bên ngoài.
  2. Tuỳ chọn được đặt thành RESET_VALUE trong mã hàm: ghi đè các thay đổi bên ngoài bằng giá trị mặc định.
  3. Tuỳ chọn không được đặt trong mã hàm, nhưng được đặt trong hàm hiện đã triển khai: sử dụng lựa chọn được chỉ định trong hàm đã triển khai.

Bạn không nên sử dụng tuỳ chọn preserveExternalChanges: true cho hầu hết các trường hợp vì mã của bạn sẽ không còn là nguồn đáng tin cậy đầy đủ cho các tuỳ chọn thời gian chạy cho các hàm của bạn. Nếu bạn sử dụng tính năng này, hãy kiểm tra bảng điều khiển Google Cloud hoặc sử dụng Giao diện dòng lệnh (CLI) của gcloud để xem cấu hình đầy đủ của một hàm.

Thiết lập phiên bản Node.js

SDK Firebase cho chức năng đám mây cho phép chọn thời gian chạy Node.js. Bạn có thể chọn chạy tất cả hàm trong một dự án độc quyền trên môi trường thời gian chạy tương ứng với một trong các phiên bản Node.js được hỗ trợ sau:

  • Node.js 20 (bản xem trước)
  • Node.js 18
  • Node.js 16
  • Node.js 14

Cách thiết lập phiên bản Node.js:

Bạn có thể đặt phiên bản trong trường engines của tệp package.json được tạo trong thư mục functions/ trong quá trình khởi chạy. Ví dụ: để chỉ sử dụng phiên bản 18, hãy chỉnh sửa dòng này trong package.json:

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

Nếu đang sử dụng trình quản lý gói của Yarn hoặc có các yêu cầu cụ thể khác đối với trường engines, thì bạn có thể đặt thời gian chạy cho Firebase SDK cho Cloud Functions trong firebase.json:

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

CLI sử dụng giá trị được đặt trong firebase.json ưu tiên cho bất kỳ giá trị hoặc dải ô nào mà bạn đặt riêng trong package.json.

Nâng cấp thời gian chạy Node.js

Cách nâng cấp thời gian chạy Node.js:

  1. Đảm bảo rằng dự án của bạn đang sử dụng Gói giá linh hoạt.
  2. Đảm bảo bạn đang sử dụng Firebase CLI phiên bản 11.18.0 trở lên.
  3. Thay đổi giá trị engines ở tệp package.json đã được tạo trong thư mục functions/ của bạn trong quá trình khởi chạy. Ví dụ: nếu bạn đang nâng cấp từ phiên bản 16 lên phiên bản 18, mục sẽ có dạng như sau: "engines": {"node": "18"}
  4. Nếu muốn, bạn có thể kiểm thử các thay đổi của mình bằng cách sử dụng Bộ công cụ mô phỏng cục bộ Firebase.
  5. Triển khai lại tất cả hàm.

Kiểm soát hành vi điều chỉnh theo tỷ lệ

Theo mặc định, Cloud Functions cho Firebase điều chỉnh tỷ lệ số lượng thực thể đang chạy dựa trên số lượng yêu cầu đến, có thể sẽ giảm xuống mức 0 thực thể trong thời gian lưu lượng truy cập giảm. Tuy nhiên, nếu ứng dụng yêu cầu giảm độ trễ và bạn muốn giới hạn số lần khởi động nguội, thì bạn có thể thay đổi hành vi mặc định này bằng cách chỉ định số lượng thực thể vùng chứa tối thiểu cần được giữ ấm và sẵn sàng phân phát các yêu cầu.

Tương tự, bạn có thể đặt số lượng tối đa để giới hạn tỷ lệ thực thể nhằm phản hồi các yêu cầu đến. Hãy sử dụng chế độ cài đặt này để kiểm soát chi phí hoặc giới hạn số lượng kết nối đến một dịch vụ sao lưu, chẳng hạn như tới cơ sở dữ liệu.

Giảm số lần khởi động nguội

Để đặt số lượng thực thể tối thiểu cho một hàm trong mã nguồn, hãy sử dụng phương thức runWith. Phương thức này chấp nhận một đối tượng JSON tuân theo giao diện RuntimeOptions. Giao diện này sẽ xác định giá trị cho minInstances. Ví dụ: hàm này đặt tối thiểu 5 thực thể để giữ ấm:

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

Sau đây là một số điều cần lưu ý khi đặt giá trị cho minInstances:

  • Nếu Cloud Functions cho Firebase điều chỉnh tỷ lệ ứng dụng của bạn cao hơn chế độ cài đặt minInstances, thì bạn sẽ thấy một khởi động nguội cho mỗi phiên bản trên ngưỡng đó.
  • Khởi động nguội ảnh hưởng nghiêm trọng nhất đến những ứng dụng có lưu lượng truy cập tăng đột biến. Nếu ứng dụng của bạn có lưu lượng truy cập tăng đột biến và bạn đặt giá trị minInstances đủ cao để giảm tình trạng khởi động nguội mỗi lần tăng lưu lượng truy cập, thì bạn sẽ thấy độ trễ giảm đáng kể. Đối với các ứng dụng có lưu lượng truy cập không đổi, việc khởi động nguội có thể không ảnh hưởng nghiêm trọng đến hiệu suất.
  • Việc đặt số thực thể tối thiểu có thể hợp lý đối với môi trường thực tế, nhưng thường nên tránh trong môi trường kiểm thử. Để điều chỉnh tỷ lệ về 0 trong dự án kiểm thử nhưng vẫn giảm thiểu số lượt khởi động nguội trong dự án phát hành chính thức, bạn có thể đặt minInstances dựa trên biến môi trường 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
        });
    

Giới hạn số lượng thực thể tối đa cho một hàm

Để đặt các thực thể tối đa trong mã nguồn của hàm, hãy sử dụng phương thức runWith. Phương thức này chấp nhận một đối tượng JSON tuân theo giao diện RuntimeOptions. Giao diện này sẽ xác định các giá trị cho maxInstances. Ví dụ: hàm này đặt giới hạn 100 thực thể để không làm ngập cơ sở dữ liệu cũ giả định:

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

Nếu một hàm HTTP được mở rộng lên đến giới hạn maxInstances, các yêu cầu mới sẽ được đưa vào hàng đợi trong 30 giây và sau đó bị từ chối bằng mã phản hồi 429 Too Many Requests nếu không có thực thể nào đến thời điểm đó.

Để tìm hiểu thêm về các phương pháp hay nhất khi sử dụng chế độ cài đặt thực thể tối đa, hãy xem các phương pháp hay nhất khi sử dụng maxInstances.

Đặt thời gian chờ và phân bổ bộ nhớ

Trong một số trường hợp, hàm của bạn có thể có các yêu cầu đặc biệt đối với giá trị thời gian chờ dài hoặc mức phân bổ bộ nhớ lớn. Bạn có thể đặt các giá trị này trong Google Cloud Console hoặc trong mã nguồn hàm (chỉ dành cho Firebase).

Để đặt mức phân bổ bộ nhớ và thời gian chờ trong mã nguồn của hàm, hãy sử dụng tham số runWith được giới thiệu trong SDK Firebase cho Hàm đám mây 2.0.0. Tuỳ chọn thời gian chạy này chấp nhận một đối tượng JSON tuân theo giao diện RuntimeOptions. Giao diện này xác định các giá trị cho timeoutSecondsmemory. Ví dụ: chức năng lưu trữ này sử dụng 1 GB bộ nhớ và hết thời gian chờ sau 300 giây:

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

Giá trị tối đa của timeoutSeconds540 hay 9 phút. Dung lượng bộ nhớ được cấp cho một hàm tương ứng với CPU được phân bổ cho hàm đó, như đã nêu chi tiết trong danh sách các giá trị hợp lệ cho memory sau đây:

  • 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

Cách thiết lập chế độ phân bổ bộ nhớ và thời gian chờ trong bảng điều khiển Google Cloud:

  1. Trong bảng điều khiển Google Cloud, hãy chọn Cloud Functions (Chức năng đám mây) trên trình đơn bên trái.
  2. Chọn một hàm bằng cách nhấp vào tên của hàm đó trong danh sách hàm.
  3. Nhấp vào biểu tượng Chỉnh sửa trong trình đơn trên cùng.
  4. Chọn một mức phân bổ bộ nhớ trên trình đơn thả xuống có nhãn Bộ nhớ đã phân bổ.
  5. Nhấp vào Khác để hiển thị các tùy chọn nâng cao và nhập số giây vào hộp văn bản Thời gian chờ.
  6. Nhấp vào Lưu để cập nhật hàm.