Tài liệu này mô tả cách bạn có thể yêu cầu các hàm nền không đồng bộ (không phải HTTPS) thử lại khi gặp lỗi.
Lý do hàm dựa trên sự kiện không hoàn tất
Trong một số trường hợp hiếm gặp, một hàm có thể thoát sớm do lỗi nội bộ và theo mặc định, hàm có thể được hoặc không được tự động thử lại.
Thông thường hơn, một hàm dựa trên sự kiện có thể không hoàn tất thành công do các lỗi được trả về trong chính mã hàm. Dưới đây là một số lý do khiến điều này có thể xảy ra:
- Hàm chứa lỗi và thời gian chạy trả về một ngoại lệ.
- Hàm không thể truy cập vào một điểm cuối dịch vụ hoặc hết thời gian chờ khi cố gắng truy cập.
- Hàm cố ý trả về một ngoại lệ (ví dụ: khi một tham số không vượt qua được quá trình xác thực).
- Một hàm Node.js trả về một lời hứa bị từ chối hoặc truyền một giá trị không phải là
nullcho một lệnh gọi lại.
Trong bất kỳ trường hợp nào ở trên, hàm sẽ ngừng thực thi và trả về lỗi. Các trình kích hoạt sự kiện tạo ra thông báo có chính sách thử lại mà bạn có thể tuỳ chỉnh để đáp ứng nhu cầu của hàm.
Ngữ nghĩa của việc thử lại
Cloud Functions cung cấp quá trình thực thi ít nhất một lần của một hàm dựa trên sự kiện cho mỗi sự kiện do nguồn sự kiện phát ra. Theo mặc định, nếu một lệnh gọi hàm kết thúc bằng lỗi, thì hàm sẽ không được gọi lại và sự kiện sẽ bị loại bỏ. Khi bạn bật tính năng thử lại trên một hàm dựa trên sự kiện, Cloud Functions sẽ thử lại một lệnh gọi hàm không thành công cho đến khi hoàn tất thành công hoặc hết thời hạn thử lại.
Khi không bật tính năng thử lại cho một hàm (đây là chế độ mặc định), hàm sẽ luôn báo cáo rằng đã thực thi thành công và mã phản hồi 200 OK có thể xuất hiện trong nhật ký của hàm. Điều này xảy ra ngay cả khi hàm gặp lỗi. Để
làm rõ thời điểm hàm gặp lỗi, hãy nhớ
báo cáo lỗi
một cách thích hợp.
Định cấu hình tính năng thử lại từ mã hàm
Với Cloud Functions for Firebase, bạn có thể bật tính năng thử lại trong mã cho một
hàm. Để thực hiện việc này cho một sự kiện nền như việc tạo một tài liệu Firestore mới, hãy đặt tuỳ chọn failurePolicy (thế hệ thứ 1) hoặc retrychính sách (thế hệ thứ 2) thành true:
thế hệ thứ 1
exports.docCreated = functions
.runWith({
// retry on failure
failurePolicy: true,
})
.firestore.document("my-collection/{docId}")
.onCreate((change, context) => {
/* ... */
});
thế hệ thứ 2
const { onDocumentCreated } = require("firebase-functions/firestore");
exports.docCreated = onDocumentCreated(
{
// retry on failure
retry: true,
},
"my-collection/{docId}",
(event) => {
/* ... */
},
);
Việc đặt true như minh hoạ sẽ định cấu hình một hàm để thử lại khi gặp lỗi.
Thời hạn thử lại
Đối với các hàm thế hệ thứ 2, thời hạn thử lại này sẽ hết sau 24 giờ. Đối với các hàm thế hệ thứ 1, thời hạn này sẽ hết sau 7 ngày. Cloud Functions thử lại các hàm dựa trên sự kiện mới tạo bằng chiến lược thời gian đợi tăng theo cấp số nhân, với thời gian đợi tăng từ 10 đến 600 giây. Chính sách này được áp dụng cho các hàm mới vào lần đầu tiên bạn triển khai. Chính sách này không được áp dụng hồi tố cho các hàm hiện có được triển khai lần đầu tiên trước khi các thay đổi được mô tả trong ghi chú phát hành này có hiệu lực, ngay cả khi bạn triển khai lại các hàm.Các phương pháp hay nhất
Phần này mô tả các phương pháp hay nhất để sử dụng tính năng thử lại.
Sử dụng tính năng thử lại để xử lý các lỗi tạm thời
Vì hàm của bạn được thử lại liên tục cho đến khi thực thi thành công, nên bạn phải loại bỏ các lỗi vĩnh viễn như lỗi khỏi mã thông qua quá trình kiểm thử trước khi bật tính năng thử lại. Bạn nên sử dụng tính năng thử lại để xử lý các lỗi không liên tục hoặc tạm thời có khả năng cao sẽ được giải quyết khi thử lại, chẳng hạn như điểm cuối dịch vụ không ổn định hoặc hết thời gian chờ.
Đặt điều kiện kết thúc để tránh vòng lặp thử lại vô hạn
Bạn nên bảo vệ hàm của mình khỏi việc lặp lại liên tục khi sử dụng tính năng thử lại. Bạn có thể thực hiện việc này bằng cách đưa vào một điều kiện kết thúc được xác định rõ ràng, trước khi hàm bắt đầu xử lý. Xin lưu ý rằng kỹ thuật này chỉ hoạt động nếu hàm của bạn bắt đầu thành công và có thể đánh giá điều kiện kết thúc.
Một phương pháp đơn giản nhưng hiệu quả là loại bỏ các sự kiện có dấu thời gian cũ hơn một thời gian nhất định. Điều này giúp tránh thực thi quá mức khi lỗi là lỗi liên tục hoặc tồn tại lâu hơn dự kiến.
Ví dụ: đoạn mã này loại bỏ tất cả các sự kiện cũ hơn 10 giây:
const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
callback();
return;
}
Sử dụng catch với Lời hứa
Nếu hàm của bạn đã bật tính năng thử lại, thì mọi lỗi chưa được xử lý sẽ kích hoạt quá trình thử lại. Hãy đảm bảo rằng mã của bạn ghi lại mọi lỗi không được dẫn đến việc thử lại.
Dưới đây là ví dụ về những việc bạn nên làm:
return doFooAsync().catch((err) => {
if (isFatal(err)) {
console.error(`Fatal error ${err}`);
}
return Promise.reject(err);
});
Giúp các hàm dựa trên sự kiện có thể thử lại trở thành hàm luỹ đẳng
Các hàm dựa trên sự kiện có thể thử lại phải là hàm luỹ đẳng. Dưới đây là một số nguyên tắc chung để tạo một hàm luỹ đẳng:
- Nhiều API bên ngoài (chẳng hạn như Stripe) cho phép bạn cung cấp một khoá luỹ đẳng làm tham số. Nếu đang sử dụng một API như vậy, bạn nên sử dụng mã sự kiện làm khoá luỹ đẳng.
- Tính năng luỹ đẳng hoạt động tốt với tính năng gửi ít nhất một lần, vì tính năng này giúp bạn có thể thử lại một cách an toàn. Vì vậy, một phương pháp hay nhất chung để viết mã đáng tin cậy là kết hợp tính năng luỹ đẳng với tính năng thử lại.
- Đảm bảo rằng mã của bạn là luỹ đẳng bên trong. Ví dụ:
- Đảm bảo rằng các đột biến có thể xảy ra nhiều lần mà không thay đổi kết quả.
- Truy vấn trạng thái cơ sở dữ liệu trong một giao dịch trước khi đột biến trạng thái.
- Đảm bảo rằng tất cả các tác dụng phụ đều là luỹ đẳng.
- Áp đặt một quy trình kiểm tra giao dịch bên ngoài hàm, độc lập với mã. Ví dụ: duy trì trạng thái ở một nơi nào đó ghi lại rằng một mã sự kiện nhất định đã được xử lý.
- Xử lý các lệnh gọi hàm trùng lặp ngoài băng tần. Ví dụ: có một quy trình dọn dẹp riêng biệt để dọn dẹp sau các lệnh gọi hàm trùng lặp.
Định cấu hình chính sách thử lại
Tuỳ thuộc vào nhu cầu của hàm, bạn có thể muốn định cấu hình trực tiếp chính sách thử lại. Điều này sẽ cho phép bạn thiết lập bất kỳ tổ hợp nào sau đây:
- Rút ngắn thời hạn thử lại từ 7 ngày xuống chỉ còn 10 phút.
- Thay đổi thời gian đợi tối thiểu và tối đa cho chiến lược thử lại thời gian đợi tăng theo cấp số nhân.
- Thay đổi chiến lược thử lại để thử lại ngay lập tức.
- Định cấu hình một chủ đề thư chết.
- Đặt số lần thử gửi tối đa và tối thiểu.
Cách định cấu hình chính sách thử lại:
- Viết một hàm HTTP.
- Sử dụng API Pub/Sub để tạo một gói thuê bao Pub/Sub, chỉ định URL của hàm làm mục tiêu.
Hãy xem tài liệu về cách xử lý lỗi để biết thêm thông tin về cách định cấu hình trực tiếp.Pub/SubPub/Sub