O manipulador da função do Lambda é o método no código da função que processa eventos. Quando sua função é invocada, o Lambda executa o método do manipulador. A função é executada até que o manipulador retorne uma resposta, seja encerrado ou atinja o tempo limite.
Esta página descreve como trabalhar com manipuladores de função do Lambda em Node.js, incluindo opções para a configuração de projeto, as convenções de nomenclatura e as práticas recomendadas. Além disso, esta página apresenta um exemplo de uma função do Lambda em Node.js que aceita informações sobre um pedido, produz um recibo em formato de texto e armazena esse arquivo em um bucket do Amazon Simple Storage Service (Amazon S3). Para obter mais informações sobre como implantar a função após gravá-la, consulte Implantar funções do Lambda em Node.js com arquivos .zip ou Implantar funções do Lambda em Node.js com imagens de contêiner.
Configuração do projeto de manipulador em Node.js
Há várias maneiras de inicializar um projeto Lambda em Node.js. Por exemplo, é possível criar um projeto Node.js padrão usando o npm
, criar uma aplicação do AWS SAM, ou criar uma aplicação do AWS CDK.
Para criar um projeto usando o npm
:
npm init
Este comando inicializa seu projeto e gera um arquivo package.json
que gerencia os metadados e as dependências do projeto.
O código da função função reside em um arquivo JavaScript .js
ou .mjs
. No exemplo a seguir, chamamos esse arquivo de index.mjs
porque ele usa um manipulador de módulo ES. O Lambda oferece suporte a manipuladores de módulo ES e CommonJS. Para ter mais informações, consulte Designar um manipulador de funções como módulo ES.
Um projeto típico de função do Lambda em Node.js segue esta estrutura geral:
/project-root ├── index.mjs — Contains main handler ├── package.json — Project metadata and dependencies ├── package-lock.json — Dependency lock file └── node_modules/ — Installed dependencies
Exemplo de código da função do Lambda em Node.js
O exemplo de código apresentado a seguir para uma função do Lambda em Node.js aceita informações sobre um pedido, produz um recibo em formato de texto e armazena esse arquivo em um bucket do Amazon S3.
nota
Este exemplo usa um manipulador de módulo ES. O Lambda oferece suporte a manipuladores de módulo ES e CommonJS. Para ter mais informações, consulte Designar um manipulador de funções como módulo ES.
exemplo Função do Lambda index.mjs
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
// Initialize the S3 client outside the handler for reuse
const s3Client = new S3Client();
/**
* Lambda handler for processing orders and storing receipts in S3.
* @param {Object} event - Input event containing order details
* @param {string} event.order_id - The unique identifier for the order
* @param {number} event.amount - The order amount
* @param {string} event.item - The item purchased
* @returns {Promise<string>} Success message
*/
export const handler = async(event) => {
try {
// Access environment variables
const bucketName = process.env.RECEIPT_BUCKET;
if (!bucketName) {
throw new Error('RECEIPT_BUCKET environment variable is not set');
}
// Create the receipt content and key destination
const receiptContent = `OrderID: ${event.order_id}\nAmount: $${event.amount.toFixed(2)}\nItem: ${event.item}`;
const key = `receipts/${event.order_id}.txt`;
// Upload the receipt to S3
await uploadReceiptToS3(bucketName, key, receiptContent);
console.log(`Successfully processed order ${event.order_id} and stored receipt in S3 bucket ${bucketName}`);
return 'Success';
} catch (error) {
console.error(`Failed to process order: ${error.message}`);
throw error;
}
};
/**
* Helper function to upload receipt to S3
* @param {string} bucketName - The S3 bucket name
* @param {string} key - The S3 object key
* @param {string} receiptContent - The content to upload
* @returns {Promise<void>}
*/
async function uploadReceiptToS3(bucketName, key, receiptContent) {
try {
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
Body: receiptContent
});
await s3Client.send(command);
} catch (error) {
throw new Error(`Failed to upload receipt to S3: ${error.message}`);
}
}
Este arquivo index.mjs
contém as seguintes seções de código:
-
Bloco
import
: utilize este bloco para incluir as bibliotecas necessárias para a função do Lambda, como clientes do AWS SDK. -
Declaração de
const s3Client
: inicializa um cliente do Amazon S3 fora da função do manipulador. Isso faz com que o Lambda execute esse código durante a fase de inicialização, e o cliente é preservado para reutilização em várias invocações. -
Bloco de comentários JSDoc: defina os tipos de entrada e saída para seu manipulador usando anotações JSDoc
. -
export const handler
: esta é a função de manipulação principal invocada pelo Lambda. Ao implantar sua função, especifiqueindex.handler
para a propriedade Handler. O valor da propriedadeHandler
é o nome do arquivo e o nome do método do manipulador exportado, separados por um ponto. -
Função
uploadReceiptToS3
: uma função auxiliar referenciada pela função do manipulador principal.
Para que esta função funcione corretamente, seu perfil de execução deve permitir a ação s3:PutObject
. Além disso, certifique-se de definir a variável de ambiente RECEIPT_BUCKET
. Após uma invocação com êxito, o bucket do Amazon S3 deve conter um arquivo de recibo.
Convenções de nomenclatura para manipuladores
Quando você configura uma função, o valor da configuração do Handler é o nome do arquivo e o nome do módulo do handler exportado, separados por um ponto. O padrão para as funções criadas no console e para os exemplos deste guia é index.handler
. Isso indica o método de handler
que é exportado do arquivo index.js
ou index.mjs
.
Se você criar uma função no console usando um nome de arquivo ou nome de manipulador de funções diferente, deverá editar o nome do manipulador padrão.
Para alterar o nome do manipulador de funções (console)
-
Abra a página Funções
do console do Lambda e escolha sua função. -
Escolha a guia Código.
-
Role para baixo até o painel Configurações de runtime e escolha Editar.
-
Em Manipulador, insira o novo nome para seu manipulador de funções.
-
Escolha Salvar.
Definição e acesso ao objeto do evento de entrada
O formato de entrada JSON é o mais comum e padrão para funções do Lambda. Neste exemplo, a função espera uma entrada semelhante à seguinte:
{
"order_id": "12345",
"amount": 199.99,
"item": "Wireless Headphones"
}
Ao trabalhar com funções do Lambda em Node.js, é possível definir o formato do evento de entrada esperado usando anotações JSDoc. Neste exemplo, definimos a estrutura de entrada no comentário JSDoc do manipulador:
/**
* Lambda handler for processing orders and storing receipts in S3.
* @param {Object} event - Input event containing order details
* @param {string} event.order_id - The unique identifier for the order
* @param {number} event.amount - The order amount
* @param {string} event.item - The item purchased
* @returns {Promise<string>} Success message
*/
Depois de definir esses tipos em seu comentário JSDoc, você poderá acessar os campos do objeto de evento diretamente no código. Por exemplo, event.order_id
recupera o valor de order_id
da entrada original.
Padrões de manipulador válidos para funções Node.js
Recomendamos usar async/await para declarar o manipulador da função em vez de usar retornos de chamada. O uso de async/await é uma forma concisa e legível de escrever código assíncrono em Node.js, sem a necessidade de usar retornos de chamada aninhados ou promessas de encadeamento. Com async/await, é possível escrever um código que seja lido como código síncrono e, ao mesmo tempo, seja assíncrono e sem bloqueio.
Usar async/await (recomendado)
A palavra-chave async
marca uma função como assíncrona, e a palavra-chave await
pausa a execução da função até que uma Promise
seja resolvida. O manipulador aceita os seguintes argumentos:
-
event
: contém os dados de entrada passados para sua função. -
context
: contém informações sobre a invocação, a função e o ambiente de execução. Para ter mais informações, consulte Usar o objeto de contexto do Lambda para recuperar informações das funções em Node.js.
As assinaturas válidas para o padrão async/await são:
export const handler = async
(event)
=> { };export const handler = async
(event, context)
=> { };
nota
Use um ambiente de desenvolvimento integrado (IDE) ou editor de texto local para escrever o código de função TypeScript. Não é possível criar código TypeScript no console do Lambda.
Usar retornos de chamada
Os manipuladores de retorno de chamada podem usar os argumentos event, context e callback. As assinaturas válidas são:
export const handler =
(event, callback)
=> { };export const handler =
(event, context, callback)
=> { };
A função de retorno de chamada espera um Error
e uma resposta, que deve ser serializável em JSON. A função continuará em execução até que o loop de evento
exemplo – Solicitação HTTP com callback
O exemplo de função a seguir verifica um URL e retorna o código de status para o invocador.
import https from "https";
let url = "https://aws.amazon.com/";
export const handler = (event, context, callback) => {
https.get(url, (res) => {
callback(null, res.statusCode);
}).on("error", (e) => {
callback(Error(e));
});
};
Usar o SDK para JavaScript v3 em seu manipulador
Frequentemente, você usará as funções do Lambda para interagir com ou fazer atualizações em outros recursos da AWS. A maneira mais simples de interagir com esses recursos é usar o AWS SDK for JavaScript. Todos os runtimes Node.js do Lambda compatíveis incluem o SDK para JavaScript versão 3. No entanto, recomendamos fortemente que você inclua os clientes do AWS SDK necessários em seu pacote de implantação. Isso maximiza a compatibilidade com versões anteriores durante futuras atualizações do runtime do Lambda. Confie apenas no SDK fornecido com o runtime quando não puder incluir pacotes adicionais (por exemplo, ao usar o editor de código do console do Lambda ou código embutido em um modelo do AWS CloudFormation).
Para adicionar as dependências do SDK à sua função, use o comando npm install
para os clientes específicos do SDK que você precisa. No código de exemplo, usamos o cliente do Amazon S3. Adicione essa dependência executando o seguinte comando no diretório que contém seu arquivos package.json
:
npm install @aws-sdk/client-s3
No código da função, importe o cliente e os comandos necessários, conforme demonstrado na função de exemplo:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
Em seguida, inicialize um cliente do Amazon S3:
const s3Client = new S3Client();
Neste exemplo, inicializamos nosso cliente do Amazon S3 fora da função do manipulador principal para evitar a necessidade que inicializá-lo a cada vez que nossa função é invocada. Após inicializar o cliente do SDK, você poderá usá-lo para fazer chamadas de API para esse serviço da AWS. O código de exemplo chama a API PutObject do Amazon S3 da seguinte forma:
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
Body: receiptContent
});
Acesso a variáveis de ambiente
No código do manipulador, você pode fazer referência a quaisquer variáveis de ambiente usando o método process.env
. Neste exemplo, referenciamos a variável de ambiente RECEIPT_BUCKET
definida usando as seguintes linhas de código:
// Access environment variables
const bucketName = process.env.RECEIPT_BUCKET;
if (!bucketName) {
throw new Error('RECEIPT_BUCKET environment variable is not set');
}
Usar o estado global
O Lambda executa seu código estático durante a fase de inicialização antes de invocar a função pela primeira vez. Os recursos criados durante a inicialização permanecem na memória entre as invocações, para que você possa evitar ter que criá-los toda vez que invocar sua função.
No código de exemplo, o código de inicialização do cliente do S3 está fora do manipulador. O runtime inicializa o cliente antes que a função manipule seu primeiro evento e o cliente permanece disponível para reutilização em todas as invocações.
Práticas recomendadas de código para as funções do Lambda em Node.js
Siga estas diretrizes ao criar funções do Lambda:
-
Separe o manipulador do Lambda da lógica central. Isso permite que você crie uma função mais fácil para teste de unidade.
-
Controle as dependências no pacote de implantação da função. O ambiente de execução do AWS Lambda contém várias bibliotecas. Para os runtimes em Node.js e Python, os AWS SDKs estão incluídos. Para habilitar o conjunto de recursos e atualizações de segurança mais recente, o Lambda atualizará periodicamente essas bibliotecas. Essas atualizações podem introduzir alterações sutis ao comportamento de sua função do Lambda. Para ter controle total das dependências usadas por sua função, empacote todas as dependências em seu pacote de implantação.
-
Minimize a complexidade de suas dependências. Prefira frameworks mais simples que sejam carregados rapidamente no startup do ambiente de execução.
-
Minimize o tamanho do pacote de implantação às necessidades do runtime. Isso reduzirá a quantidade de tempo necessária para que seu pacote de implantação seja obtido por download e desempacotado antes da invocação.
-
Aproveite a reutilização do ambiente de execução para melhorar a performance da função. Inicialize clientes SDK e conexões de banco de dados fora do manipulador de funções e armazene em cache os ativos estáticos localmente no diretório
/tmp
. As invocações subsequentes processadas pela mesma instância da função podem reutilizar esses recursos. Isso economiza custos reduzindo o runtime da função.Para evitar possíveis vazamentos de dados entre invocações, não use o ambiente de execução para armazenar dados do usuário, eventos ou outras informações com implicações de segurança. Se sua função depende de um estado mutável que não pode ser armazenado na memória dentro do manipulador, considere criar uma função separada ou versões separadas de uma função para cada usuário.
-
Use uma diretiva de keep-alive para manter conexões persistentes. O Lambda limpa conexões ociosas ao longo do tempo. A tentativa de reutilizar uma conexão ociosa ao invocar uma função resultará em um erro de conexão. Para manter sua conexão persistente, use a diretiva keep-alive associada ao runtime. Para obter um exemplo, consulte Reutilizar conexões com keep-alive em Node.js.
-
Use variáveis de ambiente para passar parâmetros operacionais para sua função. Por exemplo, se estiver gravando em um bucket do Amazon S3, em vez fixar no código o nome do bucket em que você está gravando, configure o nome do bucket como uma variável de ambiente.
-
Evite usar invocações recursivas em sua função do Lambda, em que a função invoca a si mesma ou inicia um processo que pode invocar a função novamente. Isso pode levar a um volume não intencional de invocações da função e a custos elevados. Se você observar um volume não intencional de invocações, defina a simultaneidade reservada da função como
0
imediatamente para limitar todas as invocações da função enquanto atualiza o código. -
Não use APIs não documentadas e não públicas no código da função Lambda. Para os tempos de execução gerenciados pelo AWS Lambda, o Lambda aplica periodicamente atualizações funcionais e de segurança às APIs internas do Lambda. Essas atualizações internas da API podem ser incompatíveis com versões anteriores, gerando consequências não intencionais, como falhas de invocação, caso sua função tenha dependência nessas APIs não públicas. Consulte a referência da API para obter uma lista de APIs disponíveis publicamente.
-
Escreva um código idempotente. Escrever um código idempotente para suas funções garante que eventos duplicados sejam tratados da mesma maneira. Seu código deve validar eventos adequadamente e lidar corretamente com eventos duplicados. Para obter mais informações, consulte Como torno minha função do Lambda idempotente?
.