Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом справочнике рассматривается, как разрабатывать Функции Azure с помощью JavaScript и TypeScript с помощью пакета @azure/functions npm. Для общего обзора концепций Функции Azure, которые используются во всех языках, см. ссылку на разработчика Функции Azure.
| Ресурс | Link |
|---|---|
| Создайте свою первую JavaScript-функцию | Visual Studio Code/CLI |
| Создайте свою первую функцию TypeScript | Visual Studio Code/CLI |
| Сценарии и образцы | JavaScript/Машинописный текст |
| Справочник по API |
@azure/functions API |
Примечание.
В этой статье представлен контент для конкретной версии модели программирования на основе селектора в верхней части страницы. Выбранная вами версия должна соответствовать версии @azure/functions вашего NPM-пакета. Нельзя смешивать функции v3 и v4 в одном приложении. Если в вашем package.json нет пакета, по умолчанию используется v3.
Модель программирования
Функции Azure для Node.js поддерживает две версии моделей программирования. Новые проекты должны использовать v4.
| Функция | v4 (рекомендуется) | v3 |
|---|---|---|
| Status | Общедоступная версия | GA (техническое обслуживание) |
@azure/functions пакет |
4.x | 3.x |
| Регистрация функции | Ориентированный на код (app.http(), app.timer()) |
На основе файлов (function.json) |
| Структура файлов | Гибкий | Исправлено (одна папка на каждую функцию) |
| Версия среды выполнения функций | 4.25+ | 4.x |
| версии Node.js | 24.x, 22.x | 24.x, 22.x |
В модели программирования Node.js v4 вы регистрируете функции, импортируя app объект из @azure/functions и вызывая специфические для триггера методы. Функции определяются напрямую в вашем коде с гибкой структурой файлов. Каждая функция имеет один триггер , который запускает своё выполнение, а также может иметь связки — декларативные соединения с другими сервисами для чтения входных данных или записи выходных. Для получения дополнительной информации смотрите раздел Триггеры и привязки.
В модели v4 вы:
- Регистрируйте функции с помощью методов, специфичных для триггеров, таких как
app.http(),app.timer()иapp.storageQueue(). - Получите доступ к входу триггера как к первому аргументу обработчику (например,
HttpRequest). - Верните первичный выход напрямую от функции обработчика.
- Используйте
context.extraInputs.get()для чтения из дополнительных входных привязок, таких как Хранилище BLOB-объектов. - Используйте
context.extraOutputs.set()для записи в дополнительные выходные привязки, например очереди. - Каждая функция имеет ровно один триггер, но может иметь несколько дополнительных входов и выходов.
- Вы можете кэшировать данные в глобальных переменных для повторного использования между вызовами, но не полагайтесь на сохранение этого состояния. Среда выполнения может в любой момент перезапустить ваш рабочий процесс.
В модели программирования Node.js v3 каждая функция определяется с помощью function.json конфигурационного файла и соответствующего кода JavaScript или TypeScript. Вы организуете функции в отдельных папках с определёнными структурами файлов. Каждая функция имеет один триггер , который запускает своё выполнение, а также может иметь связки — декларативные соединения с другими сервисами для чтения входных данных или записи выходных. Для получения дополнительной информации смотрите раздел Триггеры и привязки.
В модели v3 вы:
- Определите триггеры и привязки в
function.jsonфайле. Используйтеdirection: "in"для входов иdirection: "out"выходов. - Получите доступ к входному параметру триггера в качестве второго аргумента обработчика или получите его из
context.bindings. - Задайте выходные данные, присвоив значения
context.bindings(например,context.bindings.outputQueue). Для HTTP используйтеcontext.res. - Проектам TypeScript требуется свойство
scriptFileвfunction.json, которое указывает на скомпилированный JavaScript-файл. - Каждая функция имеет ровно один триггер, но может иметь несколько входных и выходных связей.
- Вы можете кэшировать данные в глобальных переменных для повторного использования между вызовами, но не полагайтесь на сохранение этого состояния. Среда выполнения может в любой момент перезапустить ваш рабочий процесс.
Примеры
Ниже приведена простая функция, которая отвечает на HTTP-запрос:
const { app } = require('@azure/functions');
app.http('httpTrigger', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
const name = request.query.get('name') || 'World';
context.log('HTTP trigger function processed a request.');
return { body: `Hello, ${name}!` };
}
});
Следующий пример, не относящийся к HTTP, использует триггер таймера:
const { app } = require('@azure/functions');
app.timer('cleanupTimer', {
schedule: '0 */5 * * * *',
handler: async (myTimer, context) => {
context.log('Timer trigger function ran at', new Date().toISOString());
}
});
В следующем примере показан HTTP-триггер с выходной привязкой к очереди:
const { app, output } = require('@azure/functions');
const queueOutput = output.storageQueue({
queueName: 'work-items',
connection: 'AzureWebJobsStorage'
});
app.http('submitWorkItem', {
methods: ['POST'],
extraOutputs: [queueOutput],
handler: async (request, context) => {
const body = await request.json();
context.extraOutputs.set(queueOutput, JSON.stringify(body));
return { status: 202, jsonBody: { accepted: true } };
}
});
Ниже приведена простая функция, которая отвечает на HTTP-запрос:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, req) {
const name = (req.query.name || (req.body && req.body.name)) || 'World';
context.log('HTTP trigger function processed a request.');
context.res = {
body: `Hello, ${name}!`
};
};
Следующий пример, не относящийся к HTTP, использует триггер таймера:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
}
]
}
module.exports = async function (context, myTimer) {
context.log('Timer trigger function ran at', new Date().toISOString());
};
В следующем примере показан HTTP-триггер с выходной привязкой к очереди:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["post"]
},
{
"type": "queue",
"direction": "out",
"name": "workItems",
"queueName": "work-items",
"connection": "AzureWebJobsStorage"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, req) {
const payload = req.body || {};
context.bindings.workItems = JSON.stringify(payload);
context.res = {
status: 202,
body: { accepted: true }
};
};
Создание функционального приложения
В этом разделе рассматриваются основные компоненты для создания и структурирования вашего функционального приложения Node, включая @azure/functions библиотеку, структуру проекта и управление пакетами.
@azure/functions Библиотека
Библиотека @azure/functions TypeScript/JavaScript предоставляет базовые типы и функции, которые используются для взаимодействия со средой выполнения Функции Azure. Чтобы просмотреть все доступные типы и методы, посетите @azure/functions API.
Ваш код функции может использовать @azure/functions для:
- Регистрируйте функции и определяйте триггеры (модель v4).
- Получить доступ к сильно типизированным входным данным триггера (например,
HttpRequest,Timer). - Создайте типизированные значения вывода (например
HttpResponseInit). - Взаимодействовать с данными контекста и связывания, предоставленными во время выполнения.
Если вы используете @azure/functions в приложении, добавьте его в зависимости проекта:
{
"dependencies": {
"@azure/functions": "^4.0.0"
}
}
Примечание.
Библиотека @azure/functions определяет поверхность программирования для Node.js Функции Azure, но это не универсальный SDK. Используйте его специально для разработки и запуска функций в среде выполнения Функции Azure.
Конфигурация TypeScript
Для максимально комфортной разработки на TypeScript убедитесь, что tsconfig.json содержит необходимую конфигурацию:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "dist",
"rootDir": ".",
"sourceMap": true,
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Структура папок
Для проекта на JavaScript требуется структура папок, показанная в следующем примере:
<project_root>/
| - .vscode/
| - node_modules/
| - myFirstFunction/
| | - index.js
| | - function.json
| - mySecondFunction/
| | - index.js
| | - function.json
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
Основная папка проекта, <project_root>, может содержать следующие файлы:
- .vscode/: (необязательно) содержит хранимую конфигурацию Visual Studio Code. Дополнительные сведения см. в разделе настройки Visual Studio Code.
- myFirstFunction/function.json: содержит конфигурацию триггера, входных данных и выходных данных функции. Имя каталога определяет имя функции.
- myFirstFunction/index.js: хранит код функции. Чтобы изменить путь к файлу по умолчанию, используйте scriptFile.
- .funcignore: (необязательно) объявляет файлы, которые не должны публиковаться в Azure. Обычно этот файл содержит .vscode/, чтобы игнорировать настройки редактора, test/, чтобы игнорировать тестовые случаи, и local.settings.json, чтобы локальные настройки приложения не публиковались.
- host.json: содержит параметры глобальной конфигурации, влияющие на все функции в экземпляре приложения-функции. Этот файл публикуется в Azure. При локальном запуске поддерживаются не все параметры. Дополнительные сведения см. в разделе host.json.
- local.settings.json: Используется для хранения параметров приложения и строк подключения при локальном запуске. Этот файл не публикуется в Azure. Дополнительные сведения см. в разделе local.settings.file.
- package.json: Содержит опции конфигурации, такие как список зависимостей пакета, основная точка входа и скрипты.
JavaScript-проект следует рекомендованной структуре папок в следующем примере:
<project_root>/
| - .vscode/
| - node_modules/
| - src/
| | - functions/
| | | - myFirstFunction.js
| | | - mySecondFunction.js
| - test/
| | - functions/
| | | - myFirstFunction.test.js
| | | - mySecondFunction.test.js
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
Основная папка проекта, <project_root>, может содержать следующие файлы:
- .vscode/: (необязательно) содержит хранимую конфигурацию Visual Studio Code. Дополнительные сведения см. в разделе настройки Visual Studio Code.
- src/functions/: расположение по умолчанию для всех функций и связанных с ними триггеров и привязок.
- test/: (необязательно) Содержит тестовые варианты приложения-функции.
- .funcignore: (необязательно) объявляет файлы, которые не должны публиковаться в Azure. Обычно этот файл содержит .vscode/, чтобы игнорировать настройки редактора, test/, чтобы игнорировать тестовые случаи, и local.settings.json, чтобы локальные настройки приложения не публиковались.
- host.json: содержит параметры глобальной конфигурации, влияющие на все функции в экземпляре приложения-функции. Этот файл публикуется в Azure. При локальном запуске поддерживаются не все параметры. Дополнительные сведения см. в разделе host.json.
- local.settings.json: Используется для хранения параметров приложения и строк подключения при локальном запуске. Этот файл не публикуется в Azure. Дополнительные сведения см. в разделе local.settings.file.
- package.json: Содержит опции конфигурации, такие как список зависимостей пакета, основная точка входа и скрипты.
Управление пакетами
Эффективное управление пакетами крайне важно в проектах Функции Azure на Node.js. В этом разделе рассматривается управление зависимостями, конфигурацию пакетов и лучшие практики поддержания зависимостей ваших функциональных приложений.
Управление зависимостями
Все Node.js Функции Azure проекты используют NPM для управления пакетами. Ваш package.json файл определяет конфигурацию проекта, зависимости и скрипты, необходимые для создания и запуска ваших функций.
Основная структура package.json:
{
"name": "my-functions-app",
"version": "1.0.0",
"description": "Azure Functions Node.js app",
"main": "src/index.js",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"prestart": "npm run build",
"start": "func start",
"test": "jest"
},
"dependencies": {
"@azure/functions": "^4.0.0"
},
"devDependencies": {
"@azure/functions-core-tools": "^4.0.4670",
"@types/node": "^18.0.0",
"typescript": "^4.0.0",
"jest": "^29.0.0"
}
}
Зависимости времени выполнения и разработки
Разделяйте зависимости соответствующим образом:
Зависимости во время выполнения (dependencies):
-
@azure/functions: Основная библиотека Функции Azure - Библиотеки бизнес-логики (lodash, axios и аналогичные пакеты)
- Драйверы баз данных (mongodb, mssql и аналогичные пакеты)
- пакеты Azure SDK (@azure/storage-blob, @azure/cosmos, и аналогичные пакеты)
Зависимости от развития (devDependencies):
- Компилятор TypeScript и определения типов
- Тестирование фреймворков (Jest, Mocha)
- Инструменты сборки и линтеры
- Функции Azure Core Tools (для локальной разработки)
Специфичные пакеты для TypeScript
Для проектов TypeScript включайте следующие основные зависимости разработки:
{
"devDependencies": {
"@types/node": "^18.0.0",
"typescript": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0"
}
}
Безопасность и обновления
Регулярно обновляйте свои зависимости для устранения уязвимостей безопасности:
# Check for outdated packages
npm outdated
# Update packages
npm update
# Audit for security issues
npm audit
npm audit fix
Запуск и отладка
Этот раздел охватывает локальную разработку, методы отладки и стратегии тестирования для Node.js Функции Azure.
Настройка локальной разработки
Prerequisites:
- Node.js версии 18.x или 20.x
- Функции Azure Core Tools v4.x
- Azure CLI (необязательно)
Действия по настройке:
Установите зависимости:
npm installПостройте проекты TypeScript:
npm run buildНачните локальное время выполнения:
npm start # or directly: func start
Конфигурация среды
Настройте вашу локальную среду разработки, используя local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"NODE_ENV": "development",
"CUSTOM_ENV_VARIABLE": "local-value"
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*",
"CORSCredentials": false
}
}
Отладка
Отладка Visual Studio Code:
Создайте .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Node Functions",
"type": "node",
"request": "attach",
"port": 9229,
"preLaunchTask": "func: host start"
}
]
}
Создайте .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "func",
"label": "func: host start",
"command": "host start",
"problemMatcher": "$func-node-watch",
"isBackground": true,
"options": {
"cwd": "${workspaceFolder}"
}
}
]
}
Отладка командной строки:
# Start with debugging enabled
func start --p <port>
# For TypeScript, ensure you build first
npm run build
func start --p 9229
Развертывание
В этом разделе рассматриваются стратегии развертывания, интеграция CI/CD и лучшие производственные практики для Node.js Функции Azure.
Методы развертывания
1. Развертывание Visual Studio Code:
- Установите расширение Функции Azure.
- Кликните правой кнопкой мыши по функциональному приложению в панели Azure.
- Выберите «Развернуть в функциональное приложение».
2. Функции Azure Core Tools:
# Deploy to Azure
func azure functionapp publish <FunctionAppName>
# Deploy with custom settings
func azure functionapp publish <FunctionAppName> --build local --publish-local-settings
3. Azure CLI deployment:
# Deploy from local folder
az functionapp deployment source config-zip \
--resource-group <ResourceGroupName> \
--name <FunctionAppName> \
--src <PathToZipFile>
Рабочая конфигурация
Application settings in Azure:
Настройте переменные среды для производства:
-
WEBSITE_NODE_DEFAULT_VERSION: установите значение~18или~20. -
FUNCTIONS_WORKER_RUNTIME: задано значениеnode. - Строки подключения и ключи API как защищённые настройки приложения.
-
NODE_ENV: задано значениеproduction.
Триггеры и привязки
Функции Azure используют триггеры для запуска выполнения функций и привязок для подключения кода к другим службам, таким как хранилище, очереди и базы данных. В модели программирования Node.js вы объявляете привязки по-разному в зависимости от версии модели.
Существуют два основных типа привязок:
- Триггеры (входные данные, запускающие функцию)
- Входные и выходные данные (дополнительные источники данных или назначения)
Дополнительные сведения о доступных триггерах и привязках см. в разделе "Триггеры и привязки" в Функциях Azure.
Пример: триггер таймера с входными данными объектов Blob
Эта функция срабатывает каждые 10 минут, считывает данные из объекта Blob, используя дополнительные входные данные, и записывает содержимое объекта Blob в журнал.
const { app, input } = require('@azure/functions');
let CACHED_BLOB_DATA = null;
const blobInput = input.storageBlob({
connection: 'BLOB_CONNECTION_SETTING',
path: 'mycontainer/myblob.txt'
});
app.timer('TimerTriggerWithBlob', {
schedule: '0 */10 * * * *',
extraInputs: [blobInput],
handler: async (myTimer, context) => {
if (CACHED_BLOB_DATA === null) {
// Read blob content and cache it
CACHED_BLOB_DATA = context.extraInputs.get(blobInput);
context.log(`Blob content cached: ${CACHED_BLOB_DATA?.substring(0, 100)}...`);
}
context.log(`Timer function executed at: ${new Date().toISOString()}`);
context.log(`Using cached data of length: ${CACHED_BLOB_DATA?.length || 0}`);
}
});
Эта функция запускается каждые 10 минут, считывает данные из BLOB-объекта с помощью конфигурации привязок и записывает содержимое BLOB-объекта в журнал.
{
"scriptFile": "index.js",
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */10 * * * *"
},
{
"name": "blobInput",
"type": "blob",
"direction": "in",
"path": "mycontainer/myblob.txt",
"connection": "AzureWebJobsStorage"
}
]
}
let CACHED_BLOB_DATA = null;
module.exports = async function (context, myTimer) {
if (CACHED_BLOB_DATA === null) {
// Read blob content and cache it
CACHED_BLOB_DATA = context.bindings.blobInput;
context.log(`Blob content cached: ${CACHED_BLOB_DATA?.substring(0, 100)}...`);
}
context.log(`Timer function executed at: ${new Date().toISOString()}`);
context.log(`Using cached data of length: ${CACHED_BLOB_DATA?.length || 0}`);
};
Пример: HTTP-триггер с выходной привязкой к очереди
Эта функция запускается при HTTP-запросе, записывает сообщение в очередь хранения и возвращает HTTP-ответ.
const { app, output } = require('@azure/functions');
const queueOutput = output.storageQueue({
connection: 'AzureWebJobsStorage',
queueName: 'myqueue'
});
app.http('httpTriggerWithQueue', {
methods: ['GET', 'POST'],
extraOutputs: [queueOutput],
handler: async (request, context) => {
const name = request.query.get('name') || 'World';
const message = {
id: context.invocationId,
name: name,
timestamp: new Date().toISOString()
};
// Write to queue output
context.extraOutputs.set(queueOutput, JSON.stringify(message));
context.log(`Message sent to queue: ${JSON.stringify(message)}`);
return {
body: `Hello, ${name}! Message queued successfully.`
};
}
});
Эта функция запускается при HTTP-запросе, записывает сообщение в очередь хранения и возвращает HTTP-ответ.
{
"scriptFile": "index.js",
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "$return"
},
{
"type": "queue",
"direction": "out",
"name": "outputQueue",
"queueName": "myqueue",
"connection": "AzureWebJobsStorage"
}
]
}
module.exports = async function (context, req) {
const name = (req.query.name || (req.body && req.body.name)) || 'World';
const message = {
id: context.invocationId,
name: name,
timestamp: new Date().toISOString()
};
// Write to queue output
context.bindings.outputQueue = JSON.stringify(message);
context.log(`Message sent to queue: ${JSON.stringify(message)}`);
return {
status: 200,
body: `Hello, ${name}! Message queued successfully.`
};
};
Объекты app, trigger, input и output, экспортируемые модулем @azure/functions, предоставляют типовые методы для большинства типов. Для всех типов, которые не поддерживаются, предоставляется метод, generic позволяющий вручную указать конфигурацию. Этот generic метод можно также использовать, если вы хотите изменить параметры по умолчанию, предоставляемые типовым методом.
В следующем примере показана простая функция, активироваемая HTTP, с помощью универсальных методов вместо методов, относящихся к типу.
const { app, output, trigger } = require("@azure/functions");
app.generic("helloWorld1", {
trigger: trigger.generic({
type: "httpTrigger",
methods: ["GET", "POST"],
}),
return: output.generic({
type: "http",
}),
handler: async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
return { body: `Hello, world!` };
},
});
::: зональный конец
Контекст вызова
Каждый вызов вашей функции получает объект вызова context . Используйте этот объект для чтения входных данных, настройки выходов, записи в журналы и доступа к различным метаданным. В модели v3 вы всегда передаёте объект контекста как первый аргумент обработчику.
Объект context включает следующие свойства:
| Свойство | Описание |
|---|---|
invocationId |
Идентификатор вызова текущей функции. |
executionContext |
См. контекст выполнения. |
bindings |
См. привязки. |
bindingData |
Метаданные о входном триггере для этого вызова, исключая само значение. Например, триггер концентратора событий имеет enqueuedTimeUtc свойство. |
traceContext |
Контекст распределенной трассировки. Дополнительные сведения см. в разделе Trace Context. |
bindingDefinitions |
Конфигурация входных и выходных данных, как определено в function.json. |
req |
См . HTTP-запрос. |
res |
См HTTP-ответ. |
контекст.executionContext
Объект context.executionContext имеет следующие свойства.
| Свойство | Описание |
|---|---|
invocationId |
Идентификатор вызова текущей функции. |
functionName |
Название функции, которую вы вызываете. Имя папки, function.json содержащей файл, определяет имя функции. |
functionDirectory |
Папка, содержащая function.json файл. |
retryContext |
См. контекст повторных попыток. |
context.executionContext.retryContext
Объект context.executionContext.retryContext имеет следующие свойства.
| Свойство | Описание |
|---|---|
retryCount |
Число, представляющее текущую попытку повтора. |
maxRetryCount |
Максимальное количество повторных попыток выполнения. Значение -1 указывает на неограниченное число повторных попыток. |
exception |
Исключение, вызвавшее повторную попытку. |
Объект context.bindings
Используйте context.bindings объект для чтения входных данных или настройки выходов. Следующий пример — это триггер очереди хранилища , который копирует context.bindingsвход блока хранения в выход блока хранилища. Содержимое сообщения очереди заменяет {queueTrigger}, которое используется как имя файла, подлежащее копированию, с помощью выражения привязки.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"connection": "storage_APPSETTING",
"queueName": "helloworldqueue"
},
{
"name": "myInput",
"type": "blob",
"direction": "in",
"connection": "storage_APPSETTING",
"path": "helloworld/{queueTrigger}"
},
{
"name": "myOutput",
"type": "blob",
"direction": "out",
"connection": "storage_APPSETTING",
"path": "helloworld/{queueTrigger}-copy"
}
module.exports = async function (context, myQueueItem) {
const blobValue = context.bindings.myInput;
context.bindings.myOutput = blobValue;
};
context.done
Метод context.done не рекомендуется. До того как Функции Azure начал поддерживать асинхронные функции, вы показывали, что ваша функция выполнена, вызывая context.done():
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
Удалите вызов context.done(). Отметьте свою функцию как асинхронную, чтобы она возвращала обещание (даже если вы ничего не await сделаете). Как только функция завершится (другими словами, возвращенное обещание разрешается), модель версии 3 знает, что ваша функция выполнена.
module.exports = async function (context, request) {
context.log("you don't need context.done or an awaited call");
};
Каждый вызов вашей функции получает объект вызова context . Этот объект содержит информацию о вашем вызове и методах логирования. В модели v4 вы обычно передаёте context объект как второй аргумент обработчику.
Класс InvocationContext содержит следующие свойства:
| Свойство | Описание |
|---|---|
invocationId |
Идентификатор вызова текущей функции. |
functionName |
Имя функции. |
extraInputs |
Используется для получения значений дополнительных входных данных. Дополнительные сведения см. в дополнительных входных данных и выходных данных. |
extraOutputs |
Используется для задания значений дополнительных выходных данных. Дополнительные сведения см. в дополнительных входных данных и выходных данных. |
retryContext |
См. контекст повторных попыток. |
traceContext |
Контекст распределенной трассировки. Дополнительные сведения см. в разделе Trace Context. |
triggerMetadata |
Метаданные о входных параметрах триггера для этого вызова, за исключением самого значения. Например, триггер концентратора событий имеет enqueuedTimeUtc свойство. |
options |
Параметры, используемые при регистрации функции, после их проверки и явного задания значений по умолчанию. |
Контекст повторной попытки
Объект retryContext имеет следующие свойства.
| Свойство | Описание |
|---|---|
retryCount |
Число, представляющее текущую попытку повтора. |
maxRetryCount |
Максимальное количество повторных попыток выполнения. Значение -1 указывает на неограниченное число повторных попыток. |
exception |
Исключение, вызвавшее повторную попытку. |
Дополнительные сведения см. в разделе retry-policies.
Ведение журнала
В Функции Azure используйте context.log() для записи логов. Функции Azure интегрируется с приложение Azure Insights, чтобы лучше записывать журналы приложений-функций. Application Insights, являясь частью Azure Monitor, предоставляет средства для сбора, визуализации и анализа как журналов приложений, так и выходных данных трассировки. Дополнительные сведения см. в статье monitoring Функции Azure.
Примечание.
Если использовать альтернативный метод Node.js console.log , логи на уровне приложений отслеживаются, но не связаны с какой-либо конкретной функцией. Используйте context для логирования вместо console того, чтобы все логи были связаны с определённой функцией.
В следующем примере записывается журнал на уровне сведений по умолчанию, включая идентификатор вызова:
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
Уровни журнала
В дополнение к стандартному context.log методу используйте следующие методы для записи логов на определённых уровнях:
| Метод | Описание |
|---|---|
context.log.error() |
Записывает событие уровня ошибки в журналы. |
context.log.warn() |
Записывает событие уровня предупреждения в журналы. |
context.log.info() |
Записывает событие уровня информации в журналы. |
context.log.verbose() |
Записывает событие уровня трассировки в журналы. |
| Метод | Описание |
|---|---|
context.trace() |
Записывает событие уровня трассировки в журналы. |
context.debug() |
Записывает событие уровня отладки в журналы. |
context.info() |
Записывает событие уровня информации в журналы. |
context.warn() |
Записывает событие уровня предупреждения в журналы. |
context.error() |
Записывает событие уровня ошибки в журналы. |
Настройка уровня журнала
Функции позволяют задать порог для отслеживания и просмотра журналов. Чтобы задать пороговое значение, используйте logging.logLevel свойство в host.json файле. Это свойство позволяет определить уровень по умолчанию для всех функций или порог для каждой отдельной функции. Дополнительные сведения см. в разделе Настройка мониторинга для Функций Azure.
Отслеживание настраиваемых данных
По умолчанию Функции Azure записывает выходные данные в виде трассировок в Application Insights. Для большего контроля используйте Application Insights Node.js SDK , чтобы отправлять пользовательские журналы, метрики и зависимости в ваш экземпляр Application Insights.
Примечание.
Методы в пакете SDK Node.js Application Insights могут изменяться с течением времени. В примерах, показанных здесь, могут быть незначительные отличия синтаксиса. Последние примеры использования API см. в документации по пакету SDK для Application Insights Node.js.
Для распределённого трассирования в модели программирования Node.js v4 используйте пакет @azure/functions-opentelemetry-instrumentation вместо Application Insights SDK. Этот пакет предоставляет автоматическое инструментирование на основе OpenTelemetry для Функции Azure. Дополнительные сведения см. в репозитории OpenTelemetry Функции Azure инструментирование для Node.js на GitHub.
const appInsights = require("applicationinsights");
appInsights.setup();
const client = appInsights.defaultClient;
module.exports = async function (context, request) {
// Use this with 'tagOverrides' to correlate custom logs to the parent function invocation.
var operationIdOverride = {
"ai.operation.id": context.traceContext.traceparent,
};
client.trackEvent({
name: "my custom event",
tagOverrides: operationIdOverride,
properties: { customProperty2: "custom property value" },
});
client.trackException({
exception: new Error("handled exceptions can be logged with this method"),
tagOverrides: operationIdOverride,
});
client.trackMetric({
name: "custom metric",
value: 3,
tagOverrides: operationIdOverride,
});
client.trackTrace({
message: "trace message",
tagOverrides: operationIdOverride,
});
client.trackDependency({
target: "http://dbname",
name: "select customers proc",
data: "SELECT * FROM Customers",
duration: 231,
resultCode: 0,
success: true,
dependencyTypeName: "ZSQL",
tagOverrides: operationIdOverride,
});
client.trackRequest({
name: "GET /customers",
url: "http://myserver/customers",
duration: 309,
resultCode: 200,
success: true,
tagOverrides: operationIdOverride,
});
};
Параметр tagOverrides присваивает параметру operation_Id значение идентификатора вызова функции. Эта настройка позволяет сопоставлять все автоматически сгенерированные и пользовательские логи для заданного вызова функции.
Триггеры HTTP
Триггеры HTTP и веб-хук используют объекты запроса и ответа для представления HTTP-сообщений.
Триггеры HTTP и веб-перехватчика используют объекты HttpRequest и HttpResponse для представления HTTP-сообщений. Классы представляют подмножество стандарта fetch, с использованием пакета Node.js .
HTTP-запрос
Получить доступ к запросу можно несколькими способами:
В качестве второго аргумента функции:
module.exports = async function (context, request) { context.log(`Http function processed request for url "${request.url}"`);
Из
context.reqсвойства:module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.req.url}"`);
Из именованных входных привязок: Эта опция работает так же, как и любое не-HTTP-привязание. Имя привязки в
function.jsonдолжно соответствовать ключу наcontext.bindings, или "request1" в следующем примере:{ "name": "request1", "type": "httpTrigger", "direction": "in", "authLevel": "anonymous", "methods": ["get", "post"] }module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.bindings.request1.url}"`);
Объект HttpRequest имеет следующие свойства.
| Свойство | Тип | Описание |
|---|---|---|
method |
string |
Метод HTTP-запроса, используемый для вызова этой функции. |
url |
string |
URL-адрес запроса. |
headers |
Record<string, string> |
Заголовки HTTP-запроса. Этот объект чувствителен к регистру. Используйте вместо этого request.getHeader('header-name'), так как он не учитывает регистр. |
query |
Record<string, string> |
Запрос ключей и значений строковых параметров из URL-адреса. |
params |
Record<string, string> |
Ключи и значения параметров маршрута. |
user |
HttpRequestUser \| null |
Объект, представляющий пользователя, вошедшего в систему, через аутентификацию через Функции, аутентификацию через SWA или null, если пользователь не вошел в систему. |
body |
Buffer \| string \| any |
Если тип носителя — application/octet-stream или multipart/*, body это буфер. Если значение является строкой с возможностью синтаксического анализа JSON, body является объектом синтаксического анализа. В противном случае, это строка body. |
rawBody |
string |
Тело в виде строки. Несмотря на название, это свойство не возвращает буфер. |
bufferBody |
Buffer |
Тело в качестве буфера. |
Вы можете обращаться к запросу как к первому аргументу обработчика для функции, активируемой HTTP-запросом.
async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
Объект HttpRequest имеет следующие свойства.
| Свойство | Тип | Описание |
|---|---|---|
method |
string |
Метод HTTP-запроса, используемый для вызова этой функции. |
url |
string |
URL-адрес запроса. |
headers |
Headers |
Заголовки HTTP-запроса. |
query |
URLSearchParams |
Запрос ключей и значений строковых параметров из URL-адреса. |
params |
Record<string, string> |
Ключи и значения параметров маршрута. |
user |
HttpRequestUser \| null |
Объект, представляющий пользователя, вошедшего в систему, через аутентификацию через Функции, аутентификацию через SWA или null, если пользователь не вошел в систему. |
body |
ReadableStream \| null |
Тело в виде читаемого потока. |
bodyUsed |
boolean |
Логическое значение, указывающее, считывается ли текст. |
Чтобы получить доступ к телу запроса или ответа, используйте следующие методы:
| Метод | Тип возвращаемых данных |
|---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
Примечание.
Функции тела можно выполнить только один раз. Последующие вызовы возвращают пустые строки или объекты ArrayBuffer.
HTTP-ответ
Вы можете настроить ответ несколькими способами. Например, вы можете использовать:
context.resЗадайте свойство:module.exports = async function (context, request) { context.res = { body: `Hello, world!` };
Верните ответ: если ваша функция асинхронная и вы задаете имя привязки как
$returnв вашемfunction.json, вы можете вернуть ответ напрямую, вместо того чтобы задавать его вcontext.{ "type": "http", "direction": "out", "name": "$return" }module.exports = async function (context, request) { return { body: `Hello, world!` };
Установите именованный выходной привязок: Эта опция работает так же, как и любое не-HTTP-привязание. Имя привязки в
function.jsonдолжно соответствовать ключу наcontext.bindings, или "response1" в следующем примере:{ "type": "http", "direction": "out", "name": "response1" }module.exports = async function (context, request) { context.bindings.response1 = { body: `Hello, world!` };
Вызов
context.res.send(): этот параметр не рекомендуется. Он неявно вызываетcontext.done(), и вы не можете использовать его в асинхронной функции.module.exports = function (context, request) { context.res.send(`Hello, world!`);
При создании нового объекта при настройке ответа этот объект должен соответствовать интерфейсу HttpResponseSimple , который имеет следующие свойства:
| Свойство | Тип | Описание |
|---|---|---|
headers |
Record<string, string> (необязательно) |
Заголовки HTTP-ответа. |
cookies |
Cookie[] (необязательно) |
Файлы cookie ответа HTTP. |
body |
any (необязательно) |
Текст ответа HTTP. |
statusCode |
number (необязательно) |
Код состояния HTTP-ответа. Если значение не задано, по умолчанию используется 200значение . |
status |
number (необязательно) |
То же самое, что statusCode. Это свойство игнорируется, если statusCode задано. |
Можно также изменить context.res объект, не перезаписав его. Объект по умолчанию context.res использует HttpResponseFull интерфейс, который поддерживает следующие методы в дополнение к свойствам HttpResponseSimple :
| Метод | Описание |
|---|---|
status() |
Устанавливает статус. |
setHeader() |
Задает поле заголовка.
ПРИМЕЧАНИЕ:res.set() И res.header() тоже поддерживаются и делают то же самое. |
getHeader() |
Получает поле для заголовка.
ПРИМЕЧАНИЕ:res.get() также поддерживается и делает то же самое. |
removeHeader() |
Удаляет заголовок. |
type() |
Задает заголовок content-type. |
send() |
Этот метод является устаревшим. Он задает тело и вызывает context.done(), чтобы указать на завершение функции синхронизации.
ПРИМЕЧАНИЕ:res.end() Это также поддерживается и выполняет ту же функцию. |
sendStatus() |
Этот метод является устаревшим. Он задает код состояния и вызовы context.done() для указания завершения функции синхронизации. |
json() |
Этот метод является устаревшим. Он устанавливает "content-type" на "application/json", устанавливает тело и вызывает context.done() для указания завершения функции синхронизации. |
Вы можете настроить ответ несколькими способами. Например, вы можете использовать:
Простой интерфейс с типом
HttpResponseInit: Эта опция — самый лаконичный способ возврата ответов.return { body: `Hello, world!` };
Интерфейс HttpResponseInit имеет следующие свойства:
| Свойство | Тип | Описание |
|---|---|---|
body |
BodyInit (необязательно) |
Текст ответа HTTP в виде одного из ArrayBuffer, AsyncIterable<Uint8Array>BlobFormDataIterable<Uint8Array>NodeJS.ArrayBufferViewURLSearchParamsnullили .string |
jsonBody |
any (необязательно) |
Текст ответа HTTP, сериализуемый в формате JSON. Если задано, HttpResponseInit.body свойство игнорируется в пользу этого свойства. |
status |
number (необязательно) |
Код состояния HTTP-ответа. Если значение не задано, по умолчанию используется 200значение . |
headers |
HeadersInit (необязательно) |
Заголовки HTTP-ответа. |
cookies |
Cookie[] (необязательно) |
Файлы cookie ответа HTTP. |
Как класс с типом
HttpResponse: этот параметр предоставляет вспомогательные методы для чтения и изменения различных частей ответа, таких как заголовки.const response = new HttpResponse({ body: `Hello, world!` }); response.headers.set("content-type", "application/json"); return response;
Класс HttpResponse принимает необязательный HttpResponseInit аргумент в качестве аргумента его конструктора и имеет следующие свойства:
| Свойство | Тип | Описание |
|---|---|---|
status |
number |
Код состояния HTTP-ответа. |
headers |
Headers |
Заголовки HTTP-ответа. |
cookies |
Cookie[] |
Файлы cookie ответа HTTP. |
body |
ReadableStream | null |
Тело в виде читаемого потока. |
bodyUsed |
boolean |
Логическое значение, указывающее, считывается ли текст. |
HTTP-потоки
HTTP-потоки — это функция, которая упрощает обработку больших данных, потоковую передачу ответов OpenAI, доставку динамического содержимого и поддержку других основных сценариев HTTP. Он позволяет передавать запросы и ответы от конечных точек HTTP в приложении-функции Node.js. Используйте http-потоки в сценариях, когда приложению требуется обмен данными в режиме реального времени и взаимодействие между клиентом и сервером по протоколу HTTP. Вы также можете использовать HTTP-потоки для получения оптимальной производительности и надежности приложений при использовании HTTP.
Внимание
Http-потоки не поддерживаются в модели версии 3.
Обновите модель версии 4 , чтобы использовать функцию потоковой передачи HTTP.
Существующие HttpRequest и HttpResponse типы в модели программирования версии 4 уже поддерживают различные способы обработки текста сообщения, включая поток.
Предварительные требования
-
@azure/functionsnpm-пакет версии 4.3.0 или более поздней. - среда выполнения Функции Azure версии 4.28 или более поздней.
- Функции Azure Core Tools версии 4.0.5530 или новее, которая содержит правильную версию среды выполнения.
Включение потоков
Выполните следующие действия, чтобы включить HTTP-потоки в приложении-функции в Azure и в локальных проектах:
Если планируется потоковая передача больших объемов данных, измените параметр
FUNCTIONS_REQUEST_BODY_SIZE_LIMITв Azure. Максимально допустимый размер тела запроса по умолчанию —104857600, что ограничивает размер запросов примерно до 100 МБ.Для
FUNCTIONS_REQUEST_BODY_SIZE_LIMITтакже добавьте в файл local.settings.json.Добавьте следующий код в ваше приложение в любой файл, включенный вашим главным полем.
const { app } = require("@azure/functions"); app.setup({ enableHttpStream: true });
Примеры потоков
Следующий пример показывает HTTP-триггерную функцию, которая получает данные через HTTP-запрос POST. Функция передаёт эти данные в заданный выходной файл:
const { app } = require('@azure/functions');
const { createWriteStream } = require('fs');
const { Writable } = require('stream');
app.http('httpTriggerStreamRequest', {
methods: ['POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
const writeStream = createWriteStream('<output file path>');
await request.body.pipeTo(Writable.toWeb(writeStream));
return { body: 'Done!' };
},
});
В следующем примере показана функция, спровоцированная через HTTP, которая транслирует содержимое файла в ответ на входящие запросы HTTP GET:
const { app } = require('@azure/functions');
const { createReadStream } = require('fs');
app.http('httpTriggerStreamResponse', {
methods: ['GET'],
authLevel: 'anonymous',
handler: async (request, context) => {
const body = createReadStream('<input file path>');
return { body };
},
});
Для готового к запуску примера приложения, использующего потоки, посмотрите этот пример на GitHub.
Соображения по потокам
- Используйте
request.body, чтобы получить максимальную пользу от использования потоков. Вы всё ещё можете использовать такие методы, какrequest.text(), которые всегда возвращают тело ответа в виде строки.
Хуки
Модель v3 не поддерживает крючки. Обновите до модели v4, чтобы использовать хуки.
Используйте хук для выполнения кода на различных этапах жизненного цикла Функции Azure. Порядок регистрации хуков определяет порядок их выполнения. Вы можете регистрировать хуки из любого файла в приложении. Существует два диапазона зацепок: уровень «приложения» и уровень «вызова».
Крючки вызова
Хуки вызова срабатывают один раз при каждом вызове вашей функции. Хук preInvocation выполняется до выполнения функции, а хук postInvocation — после выполнения функции. По умолчанию ваш крюк выполняется для всех типов триггеров, но вы также можете фильтровать по типу. В следующем примере показано, как зарегистрировать перехватчик вызовов и отфильтровать по типу триггера.
const { app } = require('@azure/functions');
// Pre-invocation hook with trigger filtering
app.hook.preInvocation('httpPreInvocation', async (context) => {
context.hookData.startTime = Date.now();
context.invocationContext.log(`Pre-invocation hook executed for ${context.invocationContext.functionName}`);
// Add custom headers or modify function handler if needed
if (context.functionHandler.name === 'httpTrigger') {
context.invocationContext.log('HTTP function detected, preparing request processing');
}
}, {
filter: ['httpTrigger']
});
// Post-invocation hook
app.hook.postInvocation('httpPostInvocation', async (context) => {
const duration = Date.now() - context.hookData.startTime;
context.invocationContext.log(`Function ${context.invocationContext.functionName} completed in ${duration}ms`);
// Log results or errors
if (context.error) {
context.invocationContext.log.error(`Function failed: ${context.error.message}`);
} else {
context.invocationContext.log(`Function succeeded with result: ${JSON.stringify(context.result)}`);
}
}, {
filter: ['httpTrigger']
});
Первым аргументом обработчика хука является объект контекста, характерный для данного типа хуков.
Объект PreInvocationContext имеет следующие свойства.
| Свойство | Описание |
|---|---|
inputs |
Аргументы, которые вы передаёте при вызове. |
functionHandler |
Обработчик функции для вызова. Изменения этого значения влияют на саму функцию. |
invocationContext |
Объект контекста вызова, переданный функции. |
hookData |
Рекомендуемое место для хранения и совместного использования данных между перехватчиками в одной области. Используйте уникальное имя свойства, чтобы оно не конфликтовало с данными других хуков. |
Объект PostInvocationContext имеет следующие свойства.
| Свойство | Описание |
|---|---|
inputs |
Аргументы, которые ты передаёшь на призыв. |
result |
Результат функции. Изменения этого значения влияют на общий результат функции. |
error |
Ошибка, выбрасываемая функцией, или null/undefined, если ошибка отсутствует. Изменения этого значения влияют на общий результат функции. |
invocationContext |
Объект контекста вызова, переданный функции. |
hookData |
Рекомендуемое место для хранения и совместного использования данных между перехватчиками в одной области. Используйте уникальное имя свойства, чтобы оно не конфликтовало с данными других хуков. |
Перехватчики приложений
Среда выполнения выполняет хуки приложения один раз для каждого экземпляра вашего приложения. Он выполняет хуки appStart при запуске и хуки appTerminate при завершении. Перехватчики завершения приложения (хуки) имеют ограниченное время выполнения и могут не выполняться во всех сценариях.
Среда выполнения Функции Azure в настоящее время не поддерживает логирование контекста вне вызова. Используйте пакет npm Application Insights для регистрации данных во время перехватчиков на уровне приложения.
В следующем примере регистрируются хуки приложений:
const { app } = require('@azure/functions');
const appInsights = require('applicationinsights');
// Initialize Application Insights for app-level logging
appInsights.setup().start();
const client = appInsights.defaultClient;
// App start hook
app.hook.appStart('appStartup', async (context) => {
context.hookData.appStartTime = Date.now();
context.hookData.initializationData = {};
// Initialize shared resources, database connections, etc.
client.trackEvent({
name: 'FunctionAppStarted',
properties: {
timestamp: new Date().toISOString(),
nodeVersion: process.version
}
});
// Set up global configurations
process.env.APP_INITIALIZED = 'true';
});
// App terminate hook
app.hook.appTerminate('appShutdown', async (context) => {
const uptime = Date.now() - context.hookData.appStartTime;
// Cleanup resources, close connections, etc.
client.trackEvent({
name: 'FunctionAppTerminated',
properties: {
uptime: uptime,
timestamp: new Date().toISOString()
}
});
// Flush Application Insights data
await new Promise((resolve) => client.flush({ callback: resolve }));
});
Первым аргументом обработчика хука является объект контекста, характерный для данного типа хуков.
Объект AppStartContext обладает следующим свойством:
| Свойство | Описание |
|---|---|
hookData |
Рекомендуемое место для хранения и совместного использования данных между перехватчиками в одной области. Используйте уникальное имя свойства, чтобы оно не конфликтовало с данными других хуков. |
Объект AppTerminateContext обладает следующим свойством:
| Свойство | Описание |
|---|---|
hookData |
Рекомендуемое место для хранения и совместного использования данных между перехватчиками в одной области. Используйте уникальное имя свойства, чтобы оно не конфликтовало с данными других хуков. |
Лучшие практики использования хуков
При использовании хуков в Функции Azure учитывайте следующие рекомендации:
Вопросы производительности
- Минимизируйте время выполнения хука, чтобы не влиять на производительность функций.
- По возможности используйте асинхронные операции для предотвращения блокировки.
- Учитывайте накладные расходы на хуки при обработке запросов с большим объёмом.
Обработка ошибок
- Всегда предусматривайте в хуках корректную обработку ошибок.
- Не позволяйте отказам крючка приводить к отказу функций, если это не абсолютно необходимо.
- Ошибки hook следует регистрировать в журнале надлежащим образом для отладки.
Общий доступ к данным
- Используйте
hookDataдля обмена информацией между хуками до и после вызова. - Используйте уникальные имена свойств, чтобы избежать конфликтов с другими крючками.
- Очищайте данные хука, когда они больше не нужны, чтобы предотвратить утечки памяти.
Фильтрация
- Используйте фильтрацию типа триггеров, чтобы хуки выполнялись только для соответствующих функций.
- Будьте конкретны в фильтрах для оптимизации производительности.
Масштабирование и параллелизм
По умолчанию Функции Azure автоматически отслеживает нагрузку в приложении и создает больше экземпляров узлов для Node.js по мере необходимости. Функции Azure использует встроенные (не настраиваемые пользователем) пороги для различных типов триггеров, чтобы решать, когда добавлять экземпляры, такие как возраст сообщений и размер очереди для QueueTrigger. Дополнительные сведения см. в статье, посвященной планам с оплатой по мере использования и планам "Премиум".
Такого поведения при масштабировании достаточно для многих приложений Node.js. Для приложений, зависящих от ЦП, производительность можно повысить путем увеличения числа рабочих процессов обработки языка. Число рабочих процессов на узел можно увеличить с 1 до максимума 10, используя параметр приложения FUNCTIONS_WORKER_PROCESS_COUNT. Функции Azure затем пытается равномерно распределять параллельные вызовы функций между этими рабочими. Такое поведение делает его менее вероятным, что функция с большим объемом ЦП блокирует выполнение других функций. Этот параметр применяется к каждому узлу, который Функции Azure создает при масштабировании приложения в соответствии с требованиями.
Предупреждение
FUNCTIONS_WORKER_PROCESS_COUNT Используйте параметр с осторожностью. Несколько процессов, выполняемых в одном экземпляре, могут привести к непредсказуемому поведению и увеличению времени загрузки функции. Если вы используете эту настройку, запуск из файла пакета может компенсировать эти недостатки.
Версия Node.js
Чтобы увидеть текущую версию, которую использует среда выполнения, можно выполнить логирование process.version из любой функции. Список supported versions версий Node.js, поддерживаемых каждой моделью программирования.
Настройка версии Node.js
Способ обновления версии Node.js зависит от ОС, на которой работает ваше приложение-функция.
Когда он запускается на Windows, настройте версию Node.js с помощью WEBSITE_NODE_DEFAULT_VERSION настройки приложения. Обновите этот параметр либо с помощью Azure CLI, либо в портале Azure.
Дополнительные сведения о версиях Node.js см. в статье "Поддерживаемые версии".
Перед обновлением версии Node.js убедитесь, что приложение-функция работает в последней версии среды выполнения Функции Azure. Если вам нужно обновить версию среды выполнения, ознакомьтесь с приложениями Migrate с Функции Azure версии 3.x до версии 4.x.
Выполните команду Azure CLI az functionapp config appsettings set, чтобы обновить версию Node.js приложения-функции, запущенную в Windows:
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~22 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
Эта команда устанавливает WEBSITE_NODE_DEFAULT_VERSION настройки приложения на поддерживаемую LTS-версию ~22.
После внесения изменений ваше приложение перезапускается. Дополнительные сведения о поддержке функций для Node.js см. в политике поддержки среды выполнения языка.
Переменные среды
Используйте переменные среды для управления операционными секретами, такими как строки соединений, ключи и конечные точки. Также используйте их для переменных окружения, например для переменных профиля. Добавляйте переменные среды как в локальной, так и в облачной среде и получайте доступ к process.env ним через ваш функциональный код.
В следующем примере регистрируется WEBSITE_SITE_NAME переменная среды:
module.exports = async function (context) {
context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
};
async function timerTrigger1(myTimer, context) {
context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
}
В локальной среде разработки
При локальном запуске проект функций содержит local.settings.json файл, в котором хранятся переменные среды в объекте Values .
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CUSTOM_ENV_VAR_1": "hello",
"CUSTOM_ENV_VAR_2": "world"
}
}
В облачной среде Azure
При запуске в Azure приложение-функция позволяет задавать и использовать параметры Application, например строки подключения службы, и предоставляет эти параметры в качестве переменных среды во время выполнения.
Существует несколько способов для добавления, обновления и удаления параметров приложения-функции.
Изменения в настройках функционального приложения требуют его перезапуска.
Переменные рабочей среды
Node.js имеет несколько специфичных для него переменных среды Functions:
languageWorkers__node__arguments
Используйте эту настановку для указания пользовательских аргументов при запуске процесса Node.js. Чаще всего вы используете его локально для запуска рабочего в режиме отладки, но также можно использовать его в Azure, если нужны пользовательские аргументы.
Предупреждение
Если возможно, избегайте использования languageWorkers__node__arguments в Azure, так как это может негативно повлиять на время холодного запуска. Вместо использования предварительно запущенных рабочих процессов среде выполнения приходится запускать новый рабочий процесс с нуля, используя ваши аргументы.
ЛогированиеlogLevelWorker
Используйте этот параметр, чтобы настроить уровень журналирования по умолчанию для журналов worker-процессов Node.js. По умолчанию отображаются только журналы предупреждений или ошибок, но вы можете настроить это на information или debug, чтобы помочь диагностировать проблемы с работником Node.js. Дополнительные сведения см. в разделе Настройка уровней журнала.
Модули ECMAScript (предварительная версия)
Примечание.
Модули ECMAScript в настоящее время являются предпросмотрной функцией в Node.js 14 и выше в Функции Azure.
Модули ECMAScript (модули ES) — это новая официальная стандартная система модулей для Node.js. Пока что в примерах кода в этой статье используется синтаксис CommonJS. При запуске Функции Azure в Node.js 14 или выше вы можете выбрать написание функций, используя синтаксис модулей ES.
Чтобы использовать в функции модули ES, переименуйте ее файл, заменив расширение на .mjs. Следующий пример файла index.mjs — это функция, активируемая через HTTP, которая использует синтаксис модулей ES для импорта библиотеки uuid и возвращает значение.
import { v4 as uuidv4 } from "uuid";
async function httpTrigger1(context, request) {
context.res.body = uuidv4();
}
export default httpTrigger;
import { v4 as uuidv4 } from "uuid";
async function httpTrigger1(request, context) {
return { body: uuidv4() };
}
app.http("httpTrigger1", {
methods: ["GET", "POST"],
handler: httpTrigger1,
});
Настройка точки входа функции
Используйте function.json свойства scriptFile и entryPoint чтобы задать местоположение и название экспортируемой функции. Когда вы используете TypeScript, вам нужно это scriptFile свойство, и оно должно указывать на скомпилированный JavaScript.
С использованием scriptFile
По умолчанию функция JavaScript выполняется из index.js. Этот файл использует тот же родительский каталог, что и соответствующий function.json файл.
Используйте scriptFile для организации структуры папок. Следующий пример показывает один из способов настройки ваших папок:
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
Файл function.json для myFirstFunction должен содержать scriptFile свойство, указывающее на файл с экспортированной функцией для запуска.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
С использованием entryPoint
В модели v3 необходимо экспортировать функцию с помощью module.exports, чтобы её можно было найти и запустить. По умолчанию функция, которая запускается при срабатывании, является единственным экспортом из этого файла. Это также может быть экспортное имя run или экспорт с названием index. В следующем примере устанавливается entryPoint в function.json на настраиваемое значение "logHello":
{
"entryPoint": "logHello",
"bindings": [
...
]
}
async function logHello(context) {
context.log("Hello, world!");
}
module.exports = { logHello };
Рекомендации
В этом разделе описаны несколько важных шаблонов для Node.js приложений, которым стоит следовать.
Выбирайте планы службы приложений с одним vCPU
Когда вы создаёте функциональное приложение, использующее тарифный план App Service, выберите план с одним vCPU, а не план с несколькими vCPU. Сегодня Functions эффективнее выполняет функции Node.js на виртуальных машинах с одним vCPU, а использование виртуальных машин большего размера не дает ожидаемого прироста производительности. При необходимости можно масштабироваться, добавляя больше экземпляров виртуальных машин с одним процессором, или включить автомасштабирование. Дополнительные сведения см. в статье Масштабирование числа экземпляров вручную или автоматически.
Запуск из файла пакета
При разработке Функции Azure в бессерверной модели размещения холодные запуски являются реальностью. Холодный запуск обозначает первый запуск функции приложения после периода простоя, что требует больше времени на включение. Для приложений Node.js с большими деревьями зависимостей холодный старт может иметь значительное влияние. Чтобы ускорить процесс холодного запуска, по возможности выполняйте функции в виде файла пакета. Во многих методах развертывания этот вариант используется по умолчанию, но если вы сталкиваетесь с длительным холодным стартом, убедитесь, что используете именно его.
Использование async и await
При написании функций Azure на Node.js пишите код с использованием ключевых слов async и await. Написание кода с использованием async и await вместо обратных вызовов или .then и .catch при использовании промисов помогает избежать двух распространённых проблем:
- Возникновение неперехваченных исключений, которые приводят к аварийному завершению процесса Node.js, что может повлиять и на выполнение других функций.
- Непредвиденное поведение, например отсутствие журналов из
context.log, вызванное асинхронными вызовами, которые не ожидаются должным образом.
В следующем примере асинхронный метод fs.readFile вызывается с функцией обратного вызова error-first в качестве второго параметра. Этот код вызывает обе проблемы, упомянутые ранее. Исключение, которое намеренно не обработано в нужной области, может обрушить весь процесс (проблема №1). Возврат без завершения обратного вызова приводит к тому, что HTTP-ответ иногда имеет пустое тело (проблема #2).
// DO NOT USE THIS CODE
const { app } = require('@azure/functions');
const fs = require('fs');
app.http('httpTriggerBadAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
let fileData;
fs.readFile('./helloWorld.txt', (err, data) => {
if (err) {
context.error(err);
// BUG #1: This will result in an uncaught exception that crashes the entire process
throw err;
}
fileData = data;
});
// BUG #2: fileData is not guaranteed to be set before the invocation ends
return { body: fileData };
},
});
В следующем примере асинхронный метод fs.readFile вызывается с функцией обратного вызова error-first в качестве второго параметра. Этот код вызывает обе вышеупомянутые проблемы. Исключение, которое явно не попадает в правильную область действия, может вызвать сбой всего процесса (проблема #1). Вызов устареваемого context.done() метода вне сферы действия обратного вызова может сигнализировать о завершении функции до того, как файл будет прочитан (проблема #2). В этом примере слишком ранний вызов context.done() приводит к отсутствию записей в журнале, начиная с Data from file:.
// NOT RECOMMENDED PATTERN
const fs = require("fs");
module.exports = function (context) {
fs.readFile("./hello.txt", (err, data) => {
if (err) {
context.log.error("ERROR", err);
// BUG #1: This will result in an uncaught exception that crashes the entire process
throw err;
}
context.log(`Data from file: ${data}`);
// context.done() should be called here
});
// BUG #2: Data is not guaranteed to be read before the Azure Function's invocation ends
context.done();
};
Используйте async ключевые слова и await , чтобы избежать обеих этих проблем. Большинство API в экосистеме Node.js теперь поддерживают обещания в той или иной форме. Например, начиная с версии 14, Node.js предоставляет fs/promises API для замены fs API обратного вызова.
В следующем примере любые необработанные исключения, вызываемые во время выполнения функции, приводят к сбою только отдельного вызова, вызвавшего исключение. Ключевое await слово означает, что шаги, следующие за readFile, выполняются только после его завершения.
// Recommended pattern
const { app } = require('@azure/functions');
const fs = require('fs/promises');
app.http('httpTriggerGoodAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
try {
const fileData = await fs.readFile('./helloWorld.txt');
return { body: fileData };
} catch (err) {
context.error(err);
// This rethrown exception will only fail the individual invocation, instead of crashing the whole process
throw err;
}
},
});
Когда вы используете async и await, вам не нужно вызывать context.done() обратный вызов.
// Recommended pattern
const fs = require("fs/promises");
module.exports = async function (context) {
let data;
try {
data = await fs.readFile("./hello.txt");
} catch (err) {
context.log.error("ERROR", err);
// This rethrown exception will be handled by the Functions Runtime and will only fail the individual invocation
throw err;
}
context.log(`Data from file: ${data}`);
};
Устранение неполадок
См. руководство по устранению неполадок Node.js.
Следующие шаги
Дополнительные сведения см. на следующих ресурсах:
- Лучшие практики для Функции Azure
- Справочник разработчика Функции Azure
- Функции Azure триггеры и привязки