Мы довольно часто используем облачные функции Google (в настоящее время развернуто около 40 функций). Все они находятся в одном репозитории, который является монорепозиторием для нашего бэкэнда nodejs. Они развертываются с помощью Github Actions при слиянии новых функций / исправлений. Наша проблема в том, что все функции развернуты, мы имели дело с параллелизмом для развертывания более одной функции за раз (несколько развертываний выполнялись параллельно), но мы наткнулись на стену. Мы достигли квоты записи (которая составляет 80 запросов за 100 секунд), и мы не уверены, почему. Кажется, что развертывание одной функции отправляет около 40 запросов на запись, что является разумным, и при развертывании функций более медленным способом (максимум 2 за раз) это неприемлемо, так как развертывание займет 40+ минут.
При поиске информации о квоте я обнаружил, что развертывание одной функции должно выполнять 1 запрос на запись (имеет смысл), но для нас он выполняется несколько раз, и я не смог найти способ отладить это.
Пример использованной команды для развертывания:
gcloud functions deploy functionName --runtime nodejs10 --memory=2048MB --timeout=540s --set-env-vars FN_NAME=functionName --trigger-http --allow-unauthenticated --project our-project --set-env-vars APP_ENV=production
Наша структура функций выглядит так (имена были заменены):
functions/src
├── fns
│ │
│ ├── atlas
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ ├── newsletter
│ │ │ ├── some-function.fn.ts
│ │ │ └── some-function.fn.ts
│ │ ├── suggestion
│ │ │ ├── some-function.fn.ts
│ │ │ └── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ └── some-function.fn.ts
│ │
│ ├── leads
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ └── some-function.fn.ts
│ │
│ ├── utils
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ ├── some-function.fn.ts
│ │ └── some-function.fn.ts
│ └── development.fn.ts
├── utils
│ ├── some-file-used-by-multiple-functions.ts
│ └── some-file-used-by-multiple-functions.ts
└── index.ts
development.fn.ts содержит код, который запускается только на локальном компьютере и игнорируется во время развертывания. По сути, он запускает все функции.
Каждый .fn.ts экспортирует одну переменную, названную в честь функции, которая является просто функцией, обрабатывающей запрос запроса. Он заключен в наш "bootstrap", который обрабатывает подключение к базе данных, клиенту PubSub и т. Д.
index.ts - это входной файл для Google Cloud с таким содержанием:
import { fns, getFnDefinition } from './bootstrap/get-fns';
// should export util
const ENV_FUNCTION_NAME = process.env.FN_NAME;
const shouldExportFn = (fnName: string) => {
if (!ENV_FUNCTION_NAME) {
return true;
}
return ENV_FUNCTION_NAME === fnName;
};
// export cycle
for (const fn of fns) {
if (shouldExportFn(fn.name)) {
const fnDefinition = getFnDefinition(fn);
exports[fn.name] = fnDefinition.handler;
}
}
export default exports;
Где fns
- это массив { name, absolutePath }
для наших функций. Он читается из файловой системы (так что импорт отсутствует), и getFnDefinition
требует файл и на основе результата (объект экспорта) решает, запускается ли функция HTTP-запросом или сообщением PubSub.
Также я видел --entry-point=ENTRY_POINT
вариант, но я не уверен, что это решит нашу проблему. Помогло бы, если бы каждая функция имела свою точку входа вместо index.js
?