Документы Firebase для пространства имен functions.https показывают, что функция принимает объект express.Request и объект express.Response. Нигде не упоминается, что вы можете передать объект экспресс-сервера functions.https.onRequest. Тем не менее, я обнаружил, что люди делают это без четкого указания от комментаторов, что этого делать не следует (кроме одного человека в ветке {101} репо № 101)

Видеть:

Мои вопросы тогда:

  1. Как Облачные функции для Firebase или GCP Облачные функции управляют временем жизни объектов, инициализированных вне определения функции?
  2. Как сказанное выше влияет на время жизни функции? Он работает до истечения времени ожидания или работает аналогично AWS Lambda?

Разъяснение для 1 и 2: В Lambda любые ресурсы вне экспортируемой функции используются во всех последующих вызовах того же экземпляра Lambda, пока этот экземпляр функции «теплый». Это означает, что на время отклика функции не оказывает негативного влияния какой-либо сложный код инициализации, который вы можете иметь заранее, как это делается один раз для «теплого» экземпляра. В этом примере не требуется инициализировать сервер ExpressJS при каждом вызове, только один раз, пока функция «тёплая». Мне интересно, облачные функции делают то же самое?

Также в Lambda наличие сервера ExpressJS не увеличивает время выполнения функции (когда она возвращается, это сделано), мне также любопытно, как здесь реализованы облачные функции. Он просто делает то же самое, что и лямбда, или (потому что он может обрабатывать существующие объекты по-разному) он делает что-то еще?

  1. В functions.https.onRequest документации не указано, что вы можете передать в него объект сервера ExpressJS, так как это работает? Есть ли тогда две конечные точки? Может кто-нибудь объяснить, что здесь происходит?

Уточнение для 3: Я видел, как люди делают следующее:

// './functions/index.js'

var functions = require("firebase-functions");
const express = require("express");

// setup ExpressJS Server
const expressRouter = new express.Router();
expressRouter.get("*", (req, res) => {
  res.send(`Hello from Express in Cloud Functions for Firebase`);
});

// Cloud Function
exports.express = functions.https.onRequest(expressRouter);

И вы хотите знать, как это работает, учитывая, что API Cloud Functions указывает только принятие functions.https.onRequest(request, response) параметров, смоделированных после API ExpressJS.

Эти параметры основаны на объектах экспресс-запросов и ответов - firebase.google.com/docs/functions/http-events

Так как все вопросы относятся к одному фрагменту кода и этому одному варианту использования, я подумал, что лучше будет ответить вместе.

Заранее спасибо :)

25
jthegedus 24 Апр 2017 в 06:42

2 ответа

Лучший ответ

Все это работает, потому что под прикрытием приложение Express на самом деле является просто функцией, которая принимает HTTP-запрос и ответ Node.js и воздействует на них с помощью некоторого автоматического подслащивания, такого как маршрутизация. Таким образом, вы можете без проблем передать маршрутизатор Express или приложение в обработчик Cloud Function, поскольку объекты Express req и res совместимы со стандартными версиями Node.js. По сути, это приложение «двойной экспресс», где одно приложение вызывает другое.

Что касается жизненного цикла функции и общего состояния: функции запускаются в эфемерных вычислительных экземплярах, которые могут выжить, чтобы обработать несколько запросов, но не могут. Вы не можете настроить или гарантировать, будет ли функция вызываться в одном и том же вычислительном экземпляре от одного вызова к другому.

Вы можете создавать ресурсы (такие как приложение Express) вне вызова функции, и это будет выполнено, когда вычислительные ресурсы будут ускорены для этой функции. Это выживет так же долго, как и экземпляр; однако ЦП / сеть сокращаются до нуля между вызовами, поэтому вы не можете выполнять «работу» вне жизненного цикла вызова функции. Как только обещание будет выполнено (или вы ответите на HTTP-запрос), ваши вычислительные ресурсы будут ограничены с помощью регулирования, а может прерваться в любой момент.

29
Michael Bleigh 24 Апр 2017 в 19:24

Вы не должны ожидать, что у вас будет какой-либо ресурс за пределами жизненного цикла функции. Вы должны ожидать, что контейнер будет полностью очищен после того, как окончательное обещание функции будет выполнено или HTTP-ответ будет полностью отправлен. Нет общего состояния между вызовами любой функции. Это единственный способ масштабирования облачных функций. Если вам нужно общее состояние, сохраните его в базе данных и читайте его при каждом вызове, при необходимости защищая его с помощью транзакции.

Я не уверен, что вы спрашиваете в третьем вопросе. Это кажется не связанным с первыми двумя вопросами - может быть, это должен быть его собственный вопрос? Насколько я знаю, для вашего бэкэнда есть только одна конечная точка.

4
Doug Stevenson 24 Апр 2017 в 12:56
43579442