Przewodnik dewelopera dotyczący usługi Azure Functions Node.js
Ten przewodnik stanowi wprowadzenie do tworzenia usługi Azure Functions przy użyciu języka JavaScript lub TypeScript. W tym artykule założono, że znasz już przewodnik dewelopera usługi Azure Functions.
Ważne
Zawartość tego artykułu zmienia się w zależności od wybranego modelu programowania Node.js w selektorze w górnej części tej strony. Wybrana wersja powinna być zgodna z wersją pakietu npm używanego @azure/functions
w aplikacji. Jeśli nie masz tego pakietu wymienionego w pliku package.json
, wartość domyślna to v3. Dowiedz się więcej o różnicach między wersjami 3 i v4 w przewodniku migracji.
Jako deweloper Node.js możesz również zainteresować się jednym z następujących artykułów:
Wprowadzenie | Pojęcia | Nauka krok po kroku |
---|---|---|
Kwestie wymagające rozważenia
- Model programowania Node.js nie powinien być mylony ze środowiskiem uruchomieniowym usługi Azure Functions:
- Model programowania: definiuje sposób tworzenia kodu i jest specyficzny dla języków JavaScript i TypeScript.
- Środowisko uruchomieniowe: definiuje podstawowe zachowanie usługi Azure Functions i jest współużytkowane we wszystkich językach.
- Wersja modelu programowania jest ściśle powiązana z wersją
@azure/functions
pakietu npm. Jest ona wersjonowana niezależnie od środowiska uruchomieniowego. Zarówno środowisko uruchomieniowe, jak i model programowania używają numeru 4 jako najnowszej wersji głównej, ale to zbieg okoliczności. - Nie można mieszać modeli programowania w wersji 3 i 4 w tej samej aplikacji funkcji. Po zarejestrowaniu jednej funkcji w wersji 4 w aplikacji wszystkie funkcje w wersji 3 zarejestrowane w plikach function.json są ignorowane.
Obsługiwane wersje
W poniższej tabeli przedstawiono każdą wersję modelu programowania Node.js wraz z obsługiwanymi wersjami środowiska uruchomieniowego usługi Azure Functions i Node.js.
Wersja modelu programowania | Poziom pomocy technicznej | Wersja środowiska uruchomieniowego usługi Functions | wersja Node.js | opis |
---|---|---|---|---|
4.x | Ogólna dostępność | 4.25+ | 20.x, 18.x | Obsługuje elastyczną strukturę plików i podejście skoncentrowane na kodzie do wyzwalaczy i powiązań. |
3.x | Ogólna dostępność | 4.x | 20.x, 18.x, 16.x, 14.x | Wymaga określonej struktury plików z wyzwalaczami i powiązaniami zadeklarowanymi w pliku "function.json" |
2.x | nie dotyczy | 3.x | 14.x, 12.x, 10.x | 13 grudnia 2022 r. osiągnięto koniec wsparcia. Aby uzyskać więcej informacji, zobacz Wersje usługi Functions. |
1.x | nie dotyczy | 2.x | 10.x, 8.x | 13 grudnia 2022 r. osiągnięto koniec wsparcia. Aby uzyskać więcej informacji, zobacz Wersje usługi Functions. |
Struktura folderów
Wymagana struktura folderów dla projektu JavaScript wygląda następująco:
<project_root>/
| - .vscode/
| - node_modules/
| - myFirstFunction/
| | - index.js
| | - function.json
| - mySecondFunction/
| | - index.js
| | - function.json
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
Główny folder projektu, <project_root>, może zawierać następujące pliki:
- .vscode/: (Opcjonalnie) Zawiera przechowywaną konfigurację programu Visual Studio Code. Aby dowiedzieć się więcej, zobacz Ustawienia programu Visual Studio Code.
- myFirstFunction/function.json: zawiera konfigurację wyzwalacza, danych wejściowych i wyjściowych funkcji. Nazwa katalogu określa nazwę funkcji.
- myFirstFunction/index.js: przechowuje kod funkcji. Aby zmienić tę domyślną ścieżkę pliku, zobacz using scriptFile (Używanie pliku scriptFile).
- .funcignore: (Opcjonalnie) Deklaruje pliki, które nie powinny być publikowane na platformie Azure. Zazwyczaj ten plik zawiera plik vscode/ , aby zignorować ustawienie edytora, przetestować/ zignorować przypadki testowe i local.settings.json , aby zapobiec publikowaniu ustawień aplikacji lokalnych.
- host.json: zawiera opcje konfiguracji, które mają wpływ na wszystkie funkcje w wystąpieniu aplikacji funkcji. Ten plik jest publikowany na platformie Azure. Nie wszystkie opcje są obsługiwane w przypadku uruchamiania lokalnego. Aby dowiedzieć się więcej, zobacz host.json.
- local.settings.json: służy do przechowywania ustawień aplikacji i parametry połączenia, gdy są uruchomione lokalnie. Ten plik nie jest publikowany na platformie Azure. Aby dowiedzieć się więcej, zobacz local.settings.file.
- package.json: zawiera opcje konfiguracji, takie jak lista zależności pakietów, główny punkt wejścia i skrypty.
Zalecana struktura folderów dla projektu JavaScript wygląda następująco:
<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
Główny folder projektu, <project_root>, może zawierać następujące pliki:
- .vscode/: (Opcjonalnie) Zawiera przechowywaną konfigurację programu Visual Studio Code. Aby dowiedzieć się więcej, zobacz Ustawienia programu Visual Studio Code.
- src/functions/: domyślna lokalizacja wszystkich funkcji i powiązanych wyzwalaczy i powiązań.
- test/: (Opcjonalnie) Zawiera przypadki testowe aplikacji funkcji.
- .funcignore: (Opcjonalnie) Deklaruje pliki, które nie powinny być publikowane na platformie Azure. Zazwyczaj ten plik zawiera plik vscode/ , aby zignorować ustawienie edytora, przetestować/ zignorować przypadki testowe i local.settings.json , aby zapobiec publikowaniu ustawień aplikacji lokalnych.
- host.json: zawiera opcje konfiguracji, które mają wpływ na wszystkie funkcje w wystąpieniu aplikacji funkcji. Ten plik jest publikowany na platformie Azure. Nie wszystkie opcje są obsługiwane w przypadku uruchamiania lokalnego. Aby dowiedzieć się więcej, zobacz host.json.
- local.settings.json: służy do przechowywania ustawień aplikacji i parametry połączenia, gdy są uruchomione lokalnie. Ten plik nie jest publikowany na platformie Azure. Aby dowiedzieć się więcej, zobacz local.settings.file.
- package.json: zawiera opcje konfiguracji, takie jak lista zależności pakietów, główny punkt wejścia i skrypty.
Rejestrowanie funkcji
Model w wersji 3 rejestruje funkcję na podstawie istnienia dwóch plików. Najpierw potrzebny function.json
jest plik znajdujący się w folderze o jeden poziom w dół od katalogu głównego aplikacji. Po drugie, potrzebny jest plik JavaScript, który eksportuje funkcję. Domyślnie model szuka index.js
pliku w tym samym folderze co plik function.json
. Jeśli używasz języka TypeScript, musisz użyć scriptFile
właściwości w pliku , function.json
aby wskazać skompilowany plik JavaScript. Aby dostosować lokalizację pliku lub nazwę eksportu funkcji, zobacz konfigurowanie punktu wejścia funkcji.
Eksportowana funkcja powinna być zawsze zadeklarowana jako element async function
w modelu w wersji 3. Można wyeksportować funkcję synchroniczną, ale następnie należy wywołać context.done()
metodę , aby zasygnalizować, że funkcja została ukończona, co jest przestarzałe i nie jest zalecane.
Funkcja jest przekazywana wywołanie context
jako pierwszy argument i dane wejściowe jako pozostałe argumenty.
Poniższy przykład to prosta funkcja, która rejestruje, że została wyzwolona i odpowiada za pomocą polecenia Hello, world!
:
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"authLevel": "anonymous",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, request) {
context.log('Http function was triggered.');
context.res = { body: 'Hello, world!' };
};
Model programowania ładuje funkcje na main
podstawie pola w obiekcie package.json
. Pole można ustawić main
na jeden plik lub wiele plików przy użyciu wzorca glob. W poniższej main
tabeli przedstawiono przykładowe wartości pola:
Przykład | opis |
---|---|
src/index.js |
Rejestrowanie funkcji z jednego pliku głównego. |
src/functions/*.js |
Zarejestruj każdą funkcję z własnego pliku. |
src/{index.js,functions/*.js} |
Kombinacja, w której rejestrujesz każdą funkcję z własnego pliku, ale nadal masz plik główny ogólnego kodu na poziomie aplikacji. |
Aby zarejestrować funkcję, należy zaimportować app
obiekt z modułu @azure/functions
npm i wywołać metodę specyficzną dla typu wyzwalacza. Pierwszym argumentem podczas rejestrowania funkcji jest nazwa funkcji. Drugim argumentem jest obiekt określający konfigurację options
wyzwalacza, programu obsługi i innych danych wejściowych lub wyjściowych. W niektórych przypadkach, gdy konfiguracja wyzwalacza nie jest konieczna, można przekazać program obsługi bezpośrednio jako drugi argument zamiast options
obiektu.
Zarejestrowanie funkcji można wykonać z dowolnego pliku w projekcie, o ile plik jest ładowany (bezpośrednio lub pośrednio) na main
podstawie pola w package.json
pliku. Funkcja powinna być zarejestrowana w zakresie globalnym, ponieważ nie można rejestrować funkcji po rozpoczęciu wykonywania.
Poniższy przykład to prosta funkcja, która rejestruje, że została wyzwolona i odpowiada za pomocą polecenia Hello, world!
:
const { app } = require('@azure/functions');
app.http('helloWorld1', {
methods: ['POST', 'GET'],
handler: async (request, context) => {
context.log('Http function was triggered.');
return { body: 'Hello, world!' };
}
});
Dane wejściowe i wyjściowe
Funkcja jest wymagana, aby mieć dokładnie jedno podstawowe dane wejściowe nazywane wyzwalaczem. Może również mieć pomocnicze dane wejściowe i/lub wyjściowe. Dane wejściowe i wyjściowe są konfigurowane w plikach function.json
, a także nazywane powiązaniami.
Dane wejściowe
Dane wejściowe są powiązaniami z direction
ustawieniem in
. Główną różnicą między wyzwalaczem a pomocniczym wejściem jest to, że type
wyzwalacz kończy się na Trigger
, na przykład typ a typem blobTrigger
blob
. Większość funkcji używa tylko wyzwalacza, a nie wiele pomocniczych typów danych wejściowych jest obsługiwanych.
Dostęp do danych wejściowych można uzyskać na kilka sposobów:
[Zalecane] Jako argumenty przekazywane do funkcji: użyj argumentów w tej samej kolejności, w której są zdefiniowane w pliku
function.json
. Właściwość zdefiniowananame
w plikufunction.json
nie musi być zgodna z nazwą argumentu, chociaż jest zalecana dla dobra organizacji.module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
Jako właściwości
context.bindings
: użyj klucza pasującego do właściwości zdefiniowanejname
w plikufunction.json
.module.exports = async function (context) { context.log("This is myTrigger: " + context.bindings.myTrigger); context.log("This is myInput: " + context.bindings.myInput); context.log("This is myOtherInput: " + context.bindings.myOtherInput); };
Dane wyjściowe
Dane wyjściowe są powiązaniami z direction
ustawieniem i out
można je ustawić na kilka sposobów:
[Zalecane w przypadku pojedynczych danych wyjściowych] Zwróć wartość bezpośrednio: jeśli używasz funkcji asynchronicznych, możesz zwrócić tę wartość bezpośrednio. Należy zmienić
name
właściwość powiązania wyjściowego na$return
wfunction.json
następujący przykład:{ "name": "$return", "type": "http", "direction": "out" }
module.exports = async function (context, request) { return { body: "Hello, world!" }; }
[Zalecane dla wielu danych wyjściowych] Zwróć obiekt zawierający wszystkie dane wyjściowe: jeśli używasz funkcji asynchronicznych, możesz zwrócić obiekt z właściwością zgodną z nazwą każdego powiązania w obiekcie
function.json
. W poniższym przykładzie użyto powiązań wyjściowych o nazwach "httpResponse" i "queueOutput":{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; return { httpResponse: { body: message }, queueOutput: message }; };
Ustaw wartości na :
context.bindings
jeśli nie używasz funkcji asynchronicznych lub nie chcesz używać poprzednich opcji, możesz ustawić wartości bezpośrednio wcontext.bindings
obiekcie , gdzie klucz jest zgodny z nazwą powiązania. W poniższym przykładzie użyto powiązań wyjściowych o nazwach "httpResponse" i "queueOutput":{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; context.bindings.httpResponse = { body: message }; context.bindings.queueOutput = message; };
Typ danych powiązań
Możesz użyć właściwości w powiązaniu dataType
wejściowym, aby zmienić typ danych wejściowych, jednak ma pewne ograniczenia:
- W Node.js są obsługiwane tylko i
string
binary
są obsługiwane (stream
nie jest) - W przypadku danych wejściowych
dataType
HTTP właściwość jest ignorowana. Zamiast tego użyj właściwości wrequest
obiekcie, aby uzyskać treść w żądanym formacie. Aby uzyskać więcej informacji, zobacz Żądanie HTTP.
W poniższym przykładzie wyzwalacza kolejki magazynu domyślny typ myQueueItem
to string
, ale jeśli ustawiono wartość dataType
binary
, typ zmieni się na Node.js Buffer
.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "helloworldqueue",
"connection": "storage_APPSETTING",
"dataType": "binary"
}
const { Buffer } = require('node:buffer');
module.exports = async function (context, myQueueItem) {
if (typeof myQueueItem === 'string') {
context.log('myQueueItem is a string');
} else if (Buffer.isBuffer(myQueueItem)) {
context.log('myQueueItem is a buffer');
}
};
Funkcja jest wymagana, aby mieć dokładnie jedno podstawowe dane wejściowe nazywane wyzwalaczem. Może również mieć pomocnicze dane wejściowe, podstawowe dane wyjściowe nazywane zwracane dane wyjściowe i/lub pomocnicze. Dane wejściowe i wyjściowe są również określane jako powiązania poza kontekstem modelu programowania Node.js. Przed wersją 4 modelu te powiązania zostały skonfigurowane w function.json
plikach.
Wprowadzanie wyzwalacza
Wyzwalacz jest jedynym wymaganym wejściem lub wyjściem. W przypadku większości typów wyzwalaczy należy zarejestrować funkcję przy użyciu metody w app
obiekcie o nazwie po typie wyzwalacza. Możesz określić konfigurację specyficzną dla wyzwalacza bezpośrednio na argumencie options
. Na przykład wyzwalacz HTTP umożliwia określenie trasy. Podczas wykonywania wartość odpowiadająca temu wyzwalaczowi jest przekazywana jako pierwszy argument do programu obsługi.
const { app } = require('@azure/functions');
app.http('helloWorld1', {
route: 'hello/world',
handler: async (request, context) => {
...
}
});
Zwracanie danych wyjściowych
Zwracane dane wyjściowe są opcjonalne i w niektórych przypadkach skonfigurowane domyślnie. Na przykład wyzwalacz HTTP zarejestrowany app.http
przy użyciu jest skonfigurowany do automatycznego zwracania danych wyjściowych odpowiedzi HTTP. W przypadku większości typów danych wyjściowych należy określić konfigurację zwracaną dla options
argumentu z pomocą output
obiektu wyeksportowanego z modułu @azure/functions
. Podczas wykonywania ustawisz te dane wyjściowe, zwracając je z programu obsługi.
W poniższym przykładzie użyto wyzwalacza czasomierza i danych wyjściowych kolejki magazynu:
const { app, output } = require('@azure/functions');
app.timer('timerTrigger1', {
schedule: '0 */5 * * * *',
return: output.storageQueue({
connection: 'storage_APPSETTING',
...
}),
handler: (myTimer, context) => {
return { hello: 'world' }
}
});
Dodatkowe dane wejściowe i wyjściowe
Oprócz wyzwalacza i zwracania można określić dodatkowe dane wejściowe lub wyjściowe argumentu options
podczas rejestrowania funkcji. Obiekty input
i output
wyeksportowane z modułu @azure/functions
zapewniają metody specyficzne dla typu, aby ułatwić konstruowanie konfiguracji. Podczas wykonywania otrzymujesz lub ustawiasz wartości z parametrem context.extraInputs.get
lub context.extraOutputs.set
, przekazując oryginalny obiekt konfiguracji jako pierwszy argument.
Poniższy przykład to funkcja wyzwalana przez kolejkę magazynu z dodatkowymi danymi wejściowymi obiektu blob magazynu skopiowanymi do dodatkowych danych wyjściowych obiektu blob magazynu. Komunikat kolejki powinien być nazwą pliku i zastąpi {queueTrigger}
go nazwą obiektu blob, który ma zostać skopiowany, za pomocą wyrażenia powiązania.
const { app, input, output } = require('@azure/functions');
const blobInput = input.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}',
});
const blobOutput = output.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}-copy',
});
app.storageQueue('copyBlob1', {
queueName: 'copyblobqueue',
connection: 'storage_APPSETTING',
extraInputs: [blobInput],
extraOutputs: [blobOutput],
handler: (queueItem, context) => {
const blobInputValue = context.extraInputs.get(blobInput);
context.extraOutputs.set(blobOutput, blobInputValue);
}
});
Ogólne dane wejściowe i wyjściowe
Obiekty app
, , input
trigger
i output
wyeksportowane przez @azure/functions
moduł udostępniają metody specyficzne dla typu dla większości typów. W przypadku wszystkich typów, które nie są obsługiwane, udostępniono metodę umożliwiającą generic
ręczne określenie konfiguracji. Metodę generic
można również użyć, jeśli chcesz zmienić ustawienia domyślne udostępniane przez metodę specyficzną dla typu.
Poniższy przykład to prosta funkcja wyzwalana przez protokół HTTP przy użyciu metod ogólnych zamiast metod specyficznych dla typu.
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!` };
}
});
Kontekst wywołania
Każde wywołanie funkcji jest przekazywane obiekt wywołania, używany do odczytywania context
danych wejściowych, ustawiania danych wyjściowych, zapisywania w dziennikach i odczytywania różnych metadanych. W modelu w wersji 3 obiekt kontekstu jest zawsze pierwszym argumentem przekazywanym do programu obsługi.
Obiekt context
ma następujące właściwości:
Właściwości | opis |
---|---|
invocationId |
Identyfikator wywołania bieżącej funkcji. |
executionContext |
Zobacz kontekst wykonywania. |
bindings |
Zobacz powiązania. |
bindingData |
Metadane dotyczące danych wejściowych wyzwalacza dla tego wywołania, a nie w tym samej wartości. Na przykład wyzwalacz centrum zdarzeń ma enqueuedTimeUtc właściwość . |
traceContext |
Kontekst śledzenia rozproszonego. Aby uzyskać więcej informacji, zobacz Trace Context . |
bindingDefinitions |
Konfiguracja danych wejściowych i wyjściowych zgodnie z definicją w pliku function.json . |
req |
Zobacz Żądanie HTTP. |
res |
Zobacz Odpowiedź HTTP. |
context.executionContext
Obiekt context.executionContext
ma następujące właściwości:
Właściwości | opis |
---|---|
invocationId |
Identyfikator wywołania bieżącej funkcji. |
functionName |
Nazwa wywoływanej funkcji. Nazwa folderu zawierającego function.json plik określa nazwę funkcji. |
functionDirectory |
Folder zawierający function.json plik. |
retryContext |
Zobacz kontekst ponawiania prób. |
context.executionContext.retryContext
Obiekt context.executionContext.retryContext
ma następujące właściwości:
Właściwości | opis |
---|---|
retryCount |
Liczba reprezentująca bieżącą próbę ponawiania próby. |
maxRetryCount |
Maksymalna liczba ponownych prób wykonania. Wartość oznacza, aby ponowić -1 próbę na czas nieokreślony. |
exception |
Wyjątek, który spowodował ponowienie próby. |
context.bindings
Obiekt context.bindings
jest używany do odczytywania danych wejściowych lub ustawiania danych wyjściowych. Poniższy przykład to wyzwalacz kolejki magazynu, który służy context.bindings
do kopiowania danych wejściowych obiektu blob magazynu do danych wyjściowych obiektu blob magazynu. Zawartość komunikatu kolejki zastępuje {queueTrigger}
nazwę pliku, która ma zostać skopiowana, za pomocą wyrażenia powiązania.
{
"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
Metoda context.done
jest przestarzała. Zanim funkcje asynchroniczne były obsługiwane, należy zasygnalizował, że funkcja jest wykonywana przez wywołanie metody context.done()
:
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
Teraz zaleca się usunięcie wywołania context.done()
funkcji i oznaczenie jej jako asynchronicznych, tak aby zwracała obietnicę (nawet jeśli nic nie await
zrobisz). Gdy tylko funkcja zakończy działanie (innymi słowy, zwrócona obietnica zostanie rozwiązana), model w wersji 3 wie, że funkcja jest wykonywana.
module.exports = async function (context, request) {
context.log("you don't need context.done or an awaited call")
};
Każde wywołanie funkcji jest przekazywane jako obiekt wywołania context
z informacjami o wywołaniu i metodach używanych do rejestrowania. W modelu context
w wersji 4 obiekt jest zazwyczaj drugim argumentem przekazywanym do programu obsługi.
Klasa InvocationContext
ma następujące właściwości:
Właściwości | opis |
---|---|
invocationId |
Identyfikator wywołania bieżącej funkcji. |
functionName |
Nazwa funkcji. |
extraInputs |
Służy do pobierania wartości dodatkowych danych wejściowych. Aby uzyskać więcej informacji, zobacz dodatkowe dane wejściowe i wyjściowe. |
extraOutputs |
Służy do ustawiania wartości dodatkowych danych wyjściowych. Aby uzyskać więcej informacji, zobacz dodatkowe dane wejściowe i wyjściowe. |
retryContext |
Zobacz kontekst ponawiania prób. |
traceContext |
Kontekst śledzenia rozproszonego. Aby uzyskać więcej informacji, zobacz Trace Context . |
triggerMetadata |
Metadane dotyczące danych wejściowych wyzwalacza dla tego wywołania, a nie w tym samej wartości. Na przykład wyzwalacz centrum zdarzeń ma enqueuedTimeUtc właściwość . |
options |
Opcje używane podczas rejestrowania funkcji po ich zweryfikowaniu i z jawnie określonymi wartościami domyślnymi. |
Kontekst ponawiania prób
Obiekt retryContext
ma następujące właściwości:
Właściwości | opis |
---|---|
retryCount |
Liczba reprezentująca bieżącą próbę ponawiania próby. |
maxRetryCount |
Maksymalna liczba ponownych prób wykonania. Wartość oznacza, aby ponowić -1 próbę na czas nieokreślony. |
exception |
Wyjątek, który spowodował ponowienie próby. |
Aby uzyskać więcej informacji, zobacz retry-policies
.
Rejestrowanie
W usłudze Azure Functions zaleca się używanie context.log()
ich do zapisywania dzienników. Usługa Azure Functions integruje się z usługą aplikacja systemu Azure Insights, aby lepiej przechwytywać dzienniki aplikacji funkcji. Usługa Application Insights, część usługi Azure Monitor, udostępnia funkcje zbierania, renderowania wizualnego i analizy dzienników aplikacji oraz danych wyjściowych śledzenia. Aby dowiedzieć się więcej, zobacz Monitorowanie usługi Azure Functions.
Uwaga
Jeśli używasz alternatywnej metody Node.jsconsole.log
, te dzienniki są śledzone na poziomie aplikacji i nie będą skojarzone z żadną konkretną funkcją. Zdecydowanie zaleca się użycie context
funkcji rejestrowania zamiast console
tego, aby wszystkie dzienniki zostały skojarzone z określoną funkcją.
Poniższy przykład zapisuje dziennik na domyślnym poziomie "informacji", w tym identyfikator wywołania:
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
Poziomy rejestrowania
Oprócz metody domyślnej context.log
dostępne są następujące metody, które umożliwiają zapisywanie dzienników na określonych poziomach:
Metoda | opis |
---|---|
context.log.error() |
Zapisuje zdarzenie na poziomie błędu w dziennikach. |
context.log.warn() |
Zapisuje zdarzenie na poziomie ostrzeżenia w dziennikach. |
context.log.info() |
Zapisuje zdarzenie na poziomie informacji w dziennikach. |
context.log.verbose() |
Zapisuje zdarzenie na poziomie śledzenia w dziennikach. |
Metoda | opis |
---|---|
context.trace() |
Zapisuje zdarzenie na poziomie śledzenia w dziennikach. |
context.debug() |
Zapisuje zdarzenie na poziomie debugowania w dziennikach. |
context.info() |
Zapisuje zdarzenie na poziomie informacji w dziennikach. |
context.warn() |
Zapisuje zdarzenie na poziomie ostrzeżenia w dziennikach. |
context.error() |
Zapisuje zdarzenie na poziomie błędu w dziennikach. |
Konfigurowanie poziomu dziennika
Usługa Azure Functions umożliwia zdefiniowanie poziomu progu, który ma być używany podczas śledzenia i wyświetlania dzienników. Aby ustawić próg, użyj logging.logLevel
właściwości w host.json
pliku . Ta właściwość umożliwia zdefiniowanie domyślnego poziomu zastosowanego do wszystkich funkcji lub progu dla każdej funkcji. Aby dowiedzieć się więcej, zobacz Jak skonfigurować monitorowanie dla usługi Azure Functions.
Śledzenie danych niestandardowych
Domyślnie usługa Azure Functions zapisuje dane wyjściowe jako ślady w usłudze Application Insights. Aby uzyskać większą kontrolę, możesz zamiast tego użyć zestawu SDK usługi Application Insights Node.js do wysyłania danych niestandardowych do wystąpienia usługi Application Insights.
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});
};
Parametr tagOverrides
ustawia operation_Id
parametr na identyfikator wywołania funkcji. To ustawienie umożliwia skorelowanie wszystkich automatycznie generowanych i niestandardowych dzienników dla wywołania danej funkcji.
Wyzwalacze HTTP
Wyzwalacze HTTP i webhook używają obiektów żądań i odpowiedzi do reprezentowania komunikatów HTTP.
Wyzwalacze HTTP i webhook używają obiektów HttpRequest
i HttpResponse
do reprezentowania komunikatów HTTP. Klasy reprezentują podzbiór standardu pobierania undici
przy użyciu pakietu Node.js.
Żądanie HTTP
Dostęp do żądania można uzyskać na kilka sposobów:
Jako drugi argument funkcji:
module.exports = async function (context, request) { context.log(`Http function processed request for url "${request.url}"`);
context.req
Z właściwości:module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.req.url}"`);
Z nazwanych powiązań wejściowych: ta opcja działa tak samo jak dowolne powiązanie niezwiązane z protokołem HTTP. Nazwa powiązania w
function.json
pliku musi być zgodna z kluczem wcontext.bindings
pliku lub "request1" w poniższym przykładzie:{ "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}"`);
Obiekt HttpRequest
ma następujące właściwości:
Właściwość | Type | Opis |
---|---|---|
method |
string |
Metoda żądania HTTP używana do wywoływania tej funkcji. |
url |
string |
Adres URL żądania. |
headers |
Record<string, string> |
Nagłówki żądań HTTP. W tym obiekcie jest rozróżniana wielkość liter. Zaleca się zamiast tego użycie request.getHeader('header-name') , co jest niewrażliwe na wielkość liter. |
query |
Record<string, string> |
Klucze parametrów ciągu zapytania i wartości z adresu URL. |
params |
Record<string, string> |
Kierowanie kluczy parametrów i wartości. |
user |
HttpRequestUser | null |
Obiekt reprezentujący zalogowanego użytkownika za pośrednictwem uwierzytelniania usługi Functions, uwierzytelniania SWA lub wartości null, gdy taki użytkownik nie jest zalogowany. |
body |
Buffer | string | any |
Jeśli typ nośnika to "application/octet-stream" lub "multipart/*", body jest buforem. Jeśli wartość jest ciągiem analizowany w formacie JSON, body jest analizowany obiekt. body W przeciwnym razie jest ciągiem. |
rawBody |
string |
Treść jako ciąg. Pomimo nazwy ta właściwość nie zwraca buforu. |
bufferBody |
Buffer |
Treść jako bufor. |
Dostęp do żądania można uzyskać jako pierwszy argument procedury obsługi dla funkcji wyzwalanej przez protokół HTTP.
async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
Obiekt HttpRequest
ma następujące właściwości:
Właściwość | Type | Opis |
---|---|---|
method |
string |
Metoda żądania HTTP używana do wywoływania tej funkcji. |
url |
string |
Adres URL żądania. |
headers |
Headers |
Nagłówki żądań HTTP. |
query |
URLSearchParams |
Klucze parametrów ciągu zapytania i wartości z adresu URL. |
params |
Record<string, string> |
Kierowanie kluczy parametrów i wartości. |
user |
HttpRequestUser | null |
Obiekt reprezentujący zalogowanego użytkownika za pośrednictwem uwierzytelniania usługi Functions, uwierzytelniania SWA lub wartości null, gdy taki użytkownik nie jest zalogowany. |
body |
ReadableStream | null |
Treść jako strumień czytelny. |
bodyUsed |
boolean |
Wartość logiczna wskazująca, czy treść jest już odczytana. |
Aby uzyskać dostęp do treści żądania lub odpowiedzi, można użyć następujących metod:
Metoda | Zwracany typ |
---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
Uwaga
Funkcje ciała można uruchamiać tylko raz; kolejne wywołania zostaną rozwiązane z pustymi ciągami/tablicąBuffers.
Odpowiedź HTTP
Odpowiedź można ustawić na kilka sposobów:
context.res
Ustaw właściwość:module.exports = async function (context, request) { context.res = { body: `Hello, world!` };
Zwróć odpowiedź: Jeśli funkcja jest asynchronizna i ustawisz nazwę powiązania na
$return
wfunction.json
pliku , możesz zwrócić odpowiedź bezpośrednio zamiast ustawiać ją na .context
{ "type": "http", "direction": "out", "name": "$return" }
module.exports = async function (context, request) { return { body: `Hello, world!` };
Ustaw nazwane powiązanie danych wyjściowych: ta opcja działa tak samo jak dowolne powiązanie inne niż HTTP. Nazwa powiązania w
function.json
pliku musi być zgodna z kluczem wcontext.bindings
pliku lub "response1" w poniższym przykładzie:{ "type": "http", "direction": "out", "name": "response1" }
module.exports = async function (context, request) { context.bindings.response1 = { body: `Hello, world!` };
Wywołaj metodę
context.res.send()
: ta opcja jest przestarzała. Niejawnie wywołujecontext.done()
metodę i nie można jej używać w funkcji asynchronicznych.module.exports = function (context, request) { context.res.send(`Hello, world!`);
Jeśli podczas ustawiania odpowiedzi zostanie utworzony nowy obiekt, ten obiekt musi być zgodny z interfejsem HttpResponseSimple
, który ma następujące właściwości:
Właściwość | Type | Opis |
---|---|---|
headers |
Record<string, string> (opcjonalny) |
Nagłówki odpowiedzi HTTP. |
cookies |
Cookie[] (opcjonalny) |
Pliki cookie odpowiedzi HTTP. |
body |
any (opcjonalny) |
Treść odpowiedzi HTTP. |
statusCode |
number (opcjonalny) |
Kod stanu odpowiedzi HTTP. Jeśli nie zostanie ustawiona, wartość domyślna to 200 . |
status |
number (opcjonalny) |
To samo co statusCode . Ta właściwość jest ignorowana, jeśli statusCode jest ustawiona. |
Można również zmodyfikować context.res
obiekt bez zastępowania go. Obiekt domyślny context.res
używa interfejsu HttpResponseFull
, który obsługuje następujące metody oprócz HttpResponseSimple
właściwości:
Metoda | opis |
---|---|
status() |
Ustawia stan. |
setHeader() |
Ustawia pole nagłówka. UWAGA: res.set() i res.header() są również obsługiwane i robią to samo. |
getHeader() |
Pobierz pole nagłówka. UWAGA: res.get() jest również obsługiwana i robi to samo. |
removeHeader() |
Usuwa nagłówek. |
type() |
Ustawia nagłówek "content-type". |
send() |
Ta metoda jest przestarzała. Ustawia treść i wywołania context.done() , aby wskazać, że funkcja synchronizacji została zakończona. UWAGA: res.end() jest również obsługiwana i robi to samo. |
sendStatus() |
Ta metoda jest przestarzała. Ustawia kod stanu i wywołania context.done() , aby wskazać, że funkcja synchronizacji została zakończona. |
json() |
Ta metoda jest przestarzała. Ustawia wartość "content-type" na "application/json", ustawia treść i wywołuje context.done() polecenie, aby wskazać, że funkcja synchronizacji została zakończona. |
Odpowiedź można ustawić na kilka sposobów:
Jako prosty interfejs z typem
HttpResponseInit
: Ta opcja jest najbardziej zwięzłym sposobem zwracania odpowiedzi.return { body: `Hello, world!` };
Interfejs
HttpResponseInit
ma następujące właściwości:Właściwość Type Opis body
BodyInit
(opcjonalny)Treść odpowiedzi HTTP jako jedna z ArrayBuffer
,AsyncIterable<Uint8Array>
,Blob
NodeJS.ArrayBufferView
Iterable<Uint8Array>
URLSearchParams
FormData
, ,null
lub .string
jsonBody
any
(opcjonalny)Treść odpowiedzi HTTP z możliwością serializacji JSON. W przypadku ustawienia HttpResponseInit.body
właściwość jest ignorowana na rzecz tej właściwości.status
number
(opcjonalny)Kod stanu odpowiedzi HTTP. Jeśli nie zostanie ustawiona, wartość domyślna to 200
.headers
HeadersInit
(opcjonalny)Nagłówki odpowiedzi HTTP. cookies
Cookie[]
(opcjonalny)Pliki cookie odpowiedzi HTTP. Jako klasa z typem
HttpResponse
: Ta opcja zapewnia metody pomocnicze do odczytywania i modyfikowania różnych części odpowiedzi, takich jak nagłówki.const response = new HttpResponse({ body: `Hello, world!` }); response.headers.set('content-type', 'application/json'); return response;
Klasa
HttpResponse
akceptuje opcjonalnyHttpResponseInit
argument konstruktora i ma następujące właściwości:Właściwość Type Opis status
number
Kod stanu odpowiedzi HTTP. headers
Headers
Nagłówki odpowiedzi HTTP. cookies
Cookie[]
Pliki cookie odpowiedzi HTTP. body
ReadableStream | null
Treść jako strumień czytelny. bodyUsed
boolean
Wartość logiczna wskazująca, czy treść została już odczytana.
Strumienie HTTP
Strumienie HTTP to funkcja, która ułatwia przetwarzanie dużych danych, przesyłanie strumieniowe odpowiedzi openAI, dostarczanie zawartości dynamicznej i obsługę innych podstawowych scenariuszy HTTP. Umożliwia przesyłanie strumieniowe żądań do i odpowiedzi z punktów końcowych HTTP w aplikacji funkcji Node.js. Używaj strumieni HTTP w scenariuszach, w których aplikacja wymaga wymiany w czasie rzeczywistym i interakcji między klientem a serwerem za pośrednictwem protokołu HTTP. Możesz również użyć strumieni HTTP, aby uzyskać najlepszą wydajność i niezawodność aplikacji podczas korzystania z protokołu HTTP.
Ważne
Strumienie HTTP nie są obsługiwane w modelu w wersji 3. Uaktualnij model do wersji 4, aby użyć funkcji przesyłania strumieniowego HTTP.
Istniejące HttpRequest
typy i HttpResponse
w modelu programowania w wersji 4 obsługują już różne sposoby obsługi treści komunikatów, w tym jako strumień.
Wymagania wstępne
- Pakiet
@azure/functions
npm w wersji 4.3.0 lub nowszej. - Środowisko uruchomieniowe usługi Azure Functions w wersji 4.28 lub nowszej.
- Narzędzia Azure Functions Core Tools w wersji 4.0.5530 lub nowszej, która zawiera poprawną wersję środowiska uruchomieniowego.
Włączanie strumieni
Wykonaj następujące kroki, aby włączyć strumienie HTTP w aplikacji funkcji na platformie Azure i w projektach lokalnych:
Jeśli planujesz przesyłanie strumieniowe dużych ilości danych, zmodyfikuj
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
ustawienie na platformie Azure. Domyślny maksymalny dozwolony rozmiar treści to104857600
, który ogranicza żądania do rozmiaru ok. 100 MB.W przypadku programowania lokalnego dodaj
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
również plik local.settings.json.Dodaj następujący kod do aplikacji w dowolnym pliku dołączonym przez pole główne.
const { app } = require('@azure/functions'); app.setup({ enableHttpStream: true });
Przykłady strumieni
W tym przykładzie pokazano funkcję wyzwalaną przez protokół HTTP, która odbiera dane za pośrednictwem żądania HTTP POST, a funkcja przesyła strumieniowo te dane do określonego pliku wyjściowego:
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!' };
},
});
W tym przykładzie pokazano funkcję wyzwalaną przez protokół HTTP, która przesyła strumieniowo zawartość pliku jako odpowiedź na przychodzące żądania 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 };
},
});
Aby uruchomić przykładową aplikację gotową do uruchomienia przy użyciu strumieni, zapoznaj się z tym przykładem w witrynie GitHub.
Zagadnienia dotyczące strumienia
- Użyj
request.body
polecenia , aby uzyskać maksymalną korzyść z używania strumieni. Nadal możesz nadal używać metod takich jakrequest.text()
, które zawsze zwracają treść jako ciąg.
Punkty zaczepienia
Punkty zaczepienia nie są obsługiwane w modelu w wersji 3. Uaktualnij model do wersji 4, aby użyć punktów zaczepienia.
Użyj punktu zaczepienia, aby wykonać kod w różnych punktach cyklu życia usługi Azure Functions. Haki są wykonywane w kolejności ich rejestracji i można je zarejestrować z dowolnego pliku w aplikacji. Obecnie istnieją dwa zakresy punktów zaczepienia, poziom "aplikacja" i poziom "wywołania".
Wcięcie wywołania
Wywołania zaczepienia są wykonywane raz na wywołanie funkcji, albo przed w haku preInvocation
lub po w haku postInvocation
. Domyślnie punkt zaczepienia jest wykonywany dla wszystkich typów wyzwalaczy, ale można również filtrować według typu. W poniższym przykładzie pokazano, jak zarejestrować punkt zaczepienia wywołania i filtrować według typu wyzwalacza:
const { app } = require('@azure/functions');
app.hook.preInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`preInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
app.hook.postInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`postInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
Pierwszym argumentem programu obsługi punktów zaczepienia jest obiekt kontekstu specyficzny dla tego typu haka.
Obiekt PreInvocationContext
ma następujące właściwości:
Właściwości | opis |
---|---|
inputs |
Argumenty przekazane do wywołania. |
functionHandler |
Procedura obsługi funkcji dla wywołania. Zmiany tej wartości wpływają na samą funkcję. |
invocationContext |
Obiekt kontekstu wywołania przekazany do funkcji. |
hookData |
Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia. |
Obiekt PostInvocationContext
ma następujące właściwości:
Właściwości | opis |
---|---|
inputs |
Argumenty przekazane do wywołania. |
result |
Wynik funkcji. Zmiany tej wartości wpływają na ogólny wynik funkcji. |
error |
Błąd zgłaszany przez funkcję lub wartość null/niezdefiniowany, jeśli nie ma błędu. Zmiany tej wartości wpływają na ogólny wynik funkcji. |
invocationContext |
Obiekt kontekstu wywołania przekazany do funkcji. |
hookData |
Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia. |
Podpięcie aplikacji
Elementy zaczepienia aplikacji są wykonywane raz na wystąpienie aplikacji podczas uruchamiania w appStart
haczyku lub podczas kończenia działania w haku appTerminate
. Kończenie działania aplikacji ma ograniczony czas do wykonania i nie jest wykonywane we wszystkich scenariuszach.
Środowisko uruchomieniowe usługi Azure Functions obecnie nie obsługuje rejestrowania kontekstu poza wywołaniem. Użyj pakietu npm usługi Application Insights, aby rejestrować dane podczas punktów zaczepienia na poziomie aplikacji.
W poniższym przykładzie rejestruje się punkt zaczepienia aplikacji:
const { app } = require('@azure/functions');
app.hook.appStart((context) => {
// add your logic here
});
app.hook.appTerminate((context) => {
// add your logic here
});
Pierwszym argumentem programu obsługi punktów zaczepienia jest obiekt kontekstu specyficzny dla tego typu haka.
Obiekt AppStartContext
ma następujące właściwości:
Właściwości | opis |
---|---|
hookData |
Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia. |
Obiekt AppTerminateContext
ma następujące właściwości:
Właściwości | opis |
---|---|
hookData |
Zalecane miejsce do przechowywania i udostępniania danych między punktami zaczepienia w tym samym zakresie. Należy użyć unikatowej nazwy właściwości, aby nie powodować konfliktu z danymi innych punktów zaczepienia. |
Skalowanie i współbieżność
Domyślnie usługa Azure Functions automatycznie monitoruje obciążenie aplikacji i tworzy więcej wystąpień hosta dla Node.js zgodnie z potrzebami. Usługa Azure Functions używa wbudowanych (nie konfigurowalnych przez użytkownika) progów dla różnych typów wyzwalaczy, aby zdecydować, kiedy dodać wystąpienia, takie jak wiek komunikatów i rozmiar kolejki dla klasy QueueTrigger. Aby uzyskać więcej informacji, zobacz Jak działają plany Zużycie i Premium.
To zachowanie skalowania jest wystarczające dla wielu aplikacji Node.js. W przypadku aplikacji powiązanych z procesorem CPU można dodatkowo zwiększyć wydajność przy użyciu wielu procesów roboczych języka. Można zwiększyć liczbę procesów roboczych na hosta z wartości domyślnej 1 do maksymalnie 10, używając ustawienia aplikacji FUNCTIONS_WORKER_PROCESS_COUNT . Następnie usługa Azure Functions próbuje równomiernie dystrybuować równoczesne wywołania funkcji między tymi procesami roboczymi. To zachowanie sprawia, że mniej prawdopodobne jest, że funkcja intensywnie korzystająca z procesora CPU blokuje działanie innych funkcji. Ustawienie dotyczy każdego hosta tworzonego przez usługę Azure Functions podczas skalowania aplikacji w celu spełnienia wymagań.
Ostrzeżenie
FUNCTIONS_WORKER_PROCESS_COUNT
Użyj ustawienia z ostrożnością. Wiele procesów uruchomionych w tym samym wystąpieniu może prowadzić do nieprzewidywalnego zachowania i zwiększyć czas ładowania funkcji. Jeśli używasz tego ustawienia, zdecydowanie zaleca się przesunięcie tych wad przez uruchomienie z pliku pakietu.
Wersja środowiska Node
Możesz zobaczyć bieżącą wersję używaną przez środowisko uruchomieniowe, logując się process.version
z dowolnej funkcji. Zobacz supported versions
listę wersji Node.js obsługiwanych przez poszczególne modele programowania.
Ustawianie wersji środowiska Node
Sposób uaktualniania wersji Node.js zależy od systemu operacyjnego, na którym działa aplikacja funkcji.
W przypadku uruchamiania w systemie Windows Node.js wersja jest ustawiana przez WEBSITE_NODE_DEFAULT_VERSION
ustawienie aplikacji. To ustawienie można zaktualizować przy użyciu interfejsu wiersza polecenia platformy Azure lub w witrynie Azure Portal.
Aby uzyskać więcej informacji na temat wersji Node.js, zobacz Obsługiwane wersje.
Przed uaktualnieniem Node.js wersji upewnij się, że aplikacja funkcji jest uruchomiona w najnowszej wersji środowiska uruchomieniowego usługi Azure Functions. Jeśli musisz uaktualnić wersję środowiska uruchomieniowego, zobacz Migrowanie aplikacji z usługi Azure Functions w wersji 3.x do wersji 4.x.
Uruchom polecenie interfejsu wiersza polecenia az functionapp config appsettings set
platformy Azure, aby zaktualizować wersję Node.js dla aplikacji funkcji uruchomionej w systemie Windows:
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~20 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
Spowoduje to ustawienie WEBSITE_NODE_DEFAULT_VERSION
aplikacji dla obsługiwanej wersji LTS programu ~20
.
Po wprowadzeniu zmian aplikacja funkcji zostanie ponownie uruchomiona. Aby dowiedzieć się więcej o obsłudze usługi Functions dla Node.js, zobacz Zasady obsługi środowiska uruchomieniowego języka.
Zmienne środowiskowe
Zmienne środowiskowe mogą być przydatne w przypadku wpisów tajnych operacyjnych (parametry połączenia, kluczy, punktów końcowych itp.) lub ustawień środowiskowych, takich jak zmienne profilowania. Zmienne środowiskowe można dodawać zarówno w środowiskach lokalnych, jak i w chmurze, i uzyskiwać do nich dostęp za pomocą process.env
kodu funkcji.
Poniższy przykład rejestruje zmienną środowiskową 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"]}`);
}
W lokalnym środowisku projektowym
Po uruchomieniu lokalnie projekt funkcji zawiera local.settings.json
plik, w którym są przechowywane zmienne środowiskowe w Values
obiekcie.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CUSTOM_ENV_VAR_1": "hello",
"CUSTOM_ENV_VAR_2": "world"
}
}
W środowisku chmury platformy Azure
Po uruchomieniu na platformie Azure aplikacja funkcji umożliwia ustawianie i używanie ustawień aplikacji, takich jak parametry połączenia usługi, i uwidacznia te ustawienia jako zmienne środowiskowe podczas wykonywania.
Istnieje kilka sposobów dodawania, aktualizowania i usuwania ustawień aplikacji funkcji:
- W witrynie Azure Portal
- Za pomocą interfejsu wiersza polecenia platformy Azure.
- Za pomocą programu Azure PowerShell.
Zmiany ustawień aplikacji funkcji wymagają ponownego uruchomienia aplikacji funkcji.
Zmienne środowiskowe procesu roboczego
Istnieje kilka zmiennych środowiskowych funkcji specyficznych dla Node.js:
languageWorkers__node__arguments
To ustawienie umożliwia określenie niestandardowych argumentów podczas uruchamiania procesu Node.js. Jest ona najczęściej używana lokalnie do uruchamiania procesu roboczego w trybie debugowania, ale może być również używana na platformie Azure, jeśli potrzebujesz argumentów niestandardowych.
Ostrzeżenie
Jeśli to możliwe, unikaj korzystania z languageWorkers__node__arguments
platformy Azure, ponieważ może to mieć negatywny wpływ na zimne czasy rozpoczęcia. Zamiast używać wstępnie rozgrzanych procesów roboczych, środowisko uruchomieniowe musi od podstaw uruchomić nowy proces roboczy z niestandardowymi argumentami.
logging__logLevel__Worker
To ustawienie dostosowuje domyślny poziom dziennika dla dzienników procesów roboczych specyficznych dla Node.js. Domyślnie wyświetlane są tylko dzienniki ostrzegawcze lub dzienniki błędów, ale można je ustawić na information
lub debug
ułatwić diagnozowanie problemów z Node.js procesem roboczym. Aby uzyskać więcej informacji, zobacz Konfigurowanie poziomów dziennika.
Moduły ECMAScript (wersja zapoznawcza)
Uwaga
Ponieważ moduły ECMAScript są obecnie funkcją w wersji zapoznawczej w Node.js 14 lub nowszym w usłudze Azure Functions.
Moduły ECMAScript (moduły ES) to nowy oficjalny standardowy system modułów dla Node.js. Do tej pory przykłady kodu w tym artykule używają składni CommonJS. W przypadku uruchamiania usługi Azure Functions w wersji Node.js 14 lub nowszej można zapisać funkcje przy użyciu składni modułów ES.
Aby użyć modułów ES w funkcji, zmień jego nazwę pliku, aby użyć .mjs
rozszerzenia. Poniższy przykład pliku index.mjs to funkcja wyzwalana przez protokół HTTP, która używa składni modułów ES do importowania uuid
biblioteki i zwracania wartości.
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
});
Konfigurowanie punktu wejścia funkcji
Właściwości function.json
scriptFile
i entryPoint
mogą służyć do konfigurowania lokalizacji i nazwy wyeksportowanej funkcji. Właściwość jest wymagana scriptFile
, gdy używasz języka TypeScript i powinna wskazywać skompilowany kod JavaScript.
Korzystanie z akcji scriptFile
Domyślnie funkcja JavaScript jest wykonywana z index.js
pliku , który współudzieli ten sam katalog nadrzędny co odpowiadający mu function.json
element .
scriptFile
Może służyć do pobierania struktury folderów, która wygląda jak w poniższym przykładzie:
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
Element function.json
for myFirstFunction
powinien zawierać właściwość wskazującą scriptFile
plik z wyeksportowaną funkcją do uruchomienia.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
Korzystanie z akcji entryPoint
W modelu w wersji 3 należy wyeksportować funkcję przy użyciu polecenia module.exports
w celu znalezienia i uruchomienia. Domyślnie funkcja wykonywana po wyzwoleniu jest jedynym eksportem z tego pliku, eksportem o nazwie lub eksportem o nazwie run
index
. W poniższym przykładzie ustawiono entryPoint
function.json
wartość niestandardową "logHello":
{
"entryPoint": "logHello",
"bindings": [
...
]
}
async function logHello(context) {
context.log('Hello, world!');
}
module.exports = { logHello };
Debugowanie lokalne
Zaleca się używanie programu VS Code do debugowania lokalnego, co powoduje automatyczne uruchomienie procesu Node.js w trybie debugowania i dołączenie go do procesu. Aby uzyskać więcej informacji, zobacz uruchamianie funkcji lokalnie.
Jeśli używasz innego narzędzia do debugowania lub chcesz ręcznie uruchomić proces Node.js w trybie debugowania, dodaj "languageWorkers__node__arguments": "--inspect"
element Values
w local.settings.json. Argument --inspect
informuje Node.js domyślnie nasłuchiwać klienta debugowania na porcie 9229. Aby uzyskać więcej informacji, zobacz przewodnik debugowania Node.js.
Zalecenia
W tej sekcji opisano kilka wzorców wpływających na Node.js aplikacji, które zalecamy.
Wybieranie planów usługi App Service z jednym procesorem wirtualnym
Podczas tworzenia aplikacji funkcji korzystającej z planu usługi App Service zalecamy wybranie planu pojedynczego procesora wirtualnego zamiast planu z wieloma procesorami wirtualnymi. Obecnie funkcje Node.js działają wydajniej na maszynach wirtualnych z jedną procesorem wirtualnym, a użycie większych maszyn wirtualnych nie generuje oczekiwanych ulepszeń wydajności. W razie potrzeby możesz ręcznie skalować w poziomie, dodając więcej wystąpień maszyn wirtualnych z pojedynczą procesorem wirtualnym lub możesz włączyć skalowanie automatyczne. Aby uzyskać więcej informacji, zobacz Ręczne lub automatyczne skalowanie liczby wystąpień.
Uruchamianie z pliku pakietu
Podczas opracowywania usługi Azure Functions w modelu hostingu bezserwerowego zimne starty są rzeczywistością. Zimny start odnosi się do pierwszego uruchomienia aplikacji funkcji po okresie braku aktywności, co trwa dłużej. W przypadku Node.js aplikacji z dużymi drzewami zależności w szczególności zimny start może być znaczący. Aby przyspieszyć proces zimnego uruchamiania, uruchom funkcje jako plik pakietu, jeśli to możliwe. Wiele metod wdrażania używa tego modelu domyślnie, ale jeśli występują duże zimne uruchomienia, sprawdź, czy działasz w ten sposób.
Używanie pojedynczego klienta statycznego
Jeśli używasz klienta specyficznego dla usługi w aplikacji usługi Azure Functions, nie twórz nowego klienta z każdym wywołaniem funkcji, ponieważ można osiągnąć limity połączeń. Zamiast tego utwórz jednego, statycznego klienta w zakresie globalnym. Aby uzyskać więcej informacji, zobacz Zarządzanie połączeniami w usłudze Azure Functions.
Używanie i async
await
Podczas pisania usługi Azure Functions w Node.js należy napisać kod przy użyciu async
słów kluczowych i await
. Pisanie kodu przy użyciu funkcji async
i await
zamiast wywołań zwrotnych lub .then
i .catch
z narzędziem Promises pomaga uniknąć dwóch typowych problemów:
- Zgłaszanie nieuchwyconych wyjątków, które powodują awarię procesu Node.js, potencjalnie wpływające na wykonywanie innych funkcji.
- Nieoczekiwane zachowanie, takie jak brakujące dzienniki z
context.log
programu , spowodowane przez wywołania asynchroniczne, które nie są prawidłowo oczekiwane.
W poniższym przykładzie metoda fs.readFile
asynchroniczna jest wywoływana z funkcją wywołania zwrotnego pierwszego błędu jako jej drugi parametr. Ten kod powoduje, że oba wymienione wcześniej problemy. Wyjątek, który nie jest jawnie przechwycony w prawidłowym zakresie, może ulec awarii całego procesu (problem nr 1). Zwracanie bez zapewnienia zakończenia wywołania zwrotnego oznacza, że odpowiedź HTTP czasami będzie mieć pustą treść (problem nr 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 };
},
});
W poniższym przykładzie metoda fs.readFile
asynchroniczna jest wywoływana z funkcją wywołania zwrotnego pierwszego błędu jako jej drugi parametr. Ten kod powoduje, że oba wymienione wcześniej problemy. Wyjątek, który nie jest jawnie przechwycony w prawidłowym zakresie, może ulec awarii całego procesu (problem nr 1). Wywołanie przestarzałej context.done()
metody poza zakresem wywołania zwrotnego może sygnalizować zakończenie działania funkcji przed odczytaniem pliku (problem nr 2). W tym przykładzie wywołanie context.done()
zbyt wcześnie powoduje brakujących wpisów dziennika rozpoczynających się od 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
Użyj słów kluczowych iawait
, aby uniknąć obu tych problemów. Większość interfejsów API w ekosystemie Node.js została przekonwertowana na obsługę obietnic w jakiejś formie. Na przykład, począwszy od wersji 14, Node.js udostępnia fs/promises
interfejs API do zastąpienia interfejsu fs
API wywołania zwrotnego.
W poniższym przykładzie wszelkie nieobsługiwane wyjątki zgłoszone podczas wykonywania funkcji kończą się niepowodzeniem tylko pojedynczego wywołania, które zgłosiło wyjątek. Słowo await
kluczowe oznacza, że kroki wykonywane readFile
tylko po jego zakończeniu.
// 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;
}
},
});
W systemach async
i await
nie trzeba również wywoływać wywołania zwrotnego 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}`);
}
Rozwiązywanie problemów
Zobacz przewodnik rozwiązywania problemów z Node.js.
Następne kroki
Aby uzyskać więcej informacji, zobacz następujące zasoby: