Ambiente de execução do Lambda - AWS Lambda

Ambiente de execução do Lambda

O Lambda invoca a função em um ambiente de execução, que fornece um ambiente do runtime seguro e isolado. O ambiente de execução gerencia os recursos necessários para executar a função. O ambiente de execução também fornece suporte ao ciclo de vida para o runtime da função e qualquer extensão externa associada à função.

O runtime da função se comunica com o Lambda usando a API de runtime. As extensões se comunicam com o Lambda usando a API Extensions. As extensões também podem receber mensagens de log e outras telemetrias da função ao usar a API de telemetria.

Diagrama de arquitetura do ambiente de execução.

Quando você cria uma função do Lambda, você especifica informações de configuração, como a quantidade de memória disponível e o tempo máximo de execução permitido para sua função. O Lambda usa essas informações para configurar o ambiente de execução.

O runtime da função e cada extensão externa são processos executados dentro do ambiente de execução. Permissões, recursos, credenciais e variáveis de ambiente são compartilhados entre a função e as extensões.

Ciclo de vida do ambiente de execução do Lambda

A fase Init é seguida por uma ou mais invocações de função. Quando não há solicitações de invocação, o Lambda inicia a fase Shutdown.

Cada fase começa com um evento que o Lambda envia para o runtime e para todas as extensões registradas. O runtime e cada extensão indicam a conclusão enviando uma solicitação de API Next. O Lambda congela o ambiente de execução quando o runtime e cada extensão tiverem sido concluídos e não houver eventos pendentes.

Fase de inicialização

Na fase Init, o Lambda executa três tarefas:

  • Iniciar todas as extensões (Extension init)

  • Realizar bootstrap no runtime (Runtime init)

  • Executar o código estático da função (Function init)

  • Execute qualquer hook de runtime beforeCheckpoint (somente para Lambda SnapStart)

A fase Init termina quando o runtime e todas as extensões sinalizam que estão prontas enviando uma solicitação de API Next. A fase Init é limitada a 10 segundos. Se todas as três tarefas não forem concluídas em até dez segundos, o Lambda repetirá a fase Init no momento da primeira invocação de função com o tempo-limite de função configurado.

Quando o Lambda SnapStart está ativado, a fase Init ocorre ao você publicar uma versão da função. O Lambda salva um snapshot do estado da memória e do disco do ambiente de execução inicializado, mantém o snapshot criptografado e o armazena em cache para acesso de baixa latência. Se você tiver um hook de runtime beforeCheckpoint, então, o código será executado ao final da fase Init.

nota

O tempo limite de dez segundos não se aplica às funções que estão usando concorrência provisionada ou SnapStart. Para funções de concorrência provisionada e SnapStart, seu código de inicialização pode ser executado por até 15 minutos. O limite de tempo é de 130 segundos ou o tempo limite da função configurada (máximo de 900 segundos), o que for maior.

Quando você usa simultaneidade provisionada, o Lambda inicializa o ambiente de execução quando você define as configurações do PC para uma função. O Lambda também garante que os ambientes de execução inicializados estejam sempre disponíveis antes das invocações. Você pode observar lacunas entre a invocação e as fases de inicialização da sua função. Dependendo do runtime e da configuração de memória da sua função, é possível observar uma latência variável na primeira invocação em um ambiente de execução inicializado.

Para funções que usam simultaneidade sob demanda, o Lambda pode ocasionalmente inicializar ambientes de execução antes das solicitações de invocação. Quando isso acontece, você também pode observar uma lacuna de tempo entre as fases de inicialização e invocação da função. Recomendamos que você não dependa desse comportamento.

Falhas durante a fase de inicialização

Se uma função falhar ou atingir o tempo limite durante a fase Init, o Lambda emite informações de erro no log INIT_REPORT.

exemplo — log INIT_REPORT para tempo limite
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: timeout
exemplo — log INIT_REPORT para falha de extensão
INIT_REPORT Init Duration: 1236.04 ms Phase: init Status: error Error Type: Extension.Crash

Se a fase Init for bem-sucedida, o Lambda não emitirá o log INIT_REPORT, a menos que o SnapStart seja ativado. As funções do SnapStart sempre emitem INIT_REPORT. Para ter mais informações, consulte Monitoramento para Lambda SnapStart.

Fase de restauração (somente para Lambda SnapStart)

Quando você invoca uma função do SnapStart pela primeira vez e à medida que aumenta a escala verticalmente da função, o Lambda retoma novos ambientes de execução a partir do snapshot retido, em vez de inicializar a função do zero. Se você tiver um hook de runtime afterRestore(), o código será executado ao final da fase Restore. Você terá cobranças pela duração dos hooks de runtime afterRestore(). O runtime (JVM) deve ser carregado e os hooks de runtime afterRestore() devem ser concluídos dentro do limite de tempo limite (dez segundos). Caso contrário, você obterá uma SnapStartTimeoutException. Quando a fase Restore é concluída, o Lambda invoca o manipulador de função (a Fase de invocação).

Falhas durante a fase de restauração

Se a fase Restore falhar, o Lambda emite informações de erro no log RESTORE_REPORT.

exemplo — log RESTORE_REPORT para tempo limite
RESTORE_REPORT Restore Duration: 1236.04 ms Status: timeout
exemplo — log RESTORE_REPORT para falha no hook de runtime
RESTORE_REPORT Restore Duration: 1236.04 ms Status: error Error Type: Runtime.ExitError

Para obter mais informações sobre o log RESTORE_REPORT, consulte Monitoramento para Lambda SnapStart.

Fase de invocação

Quando uma função do Lambda é invocada em resposta a uma solicitação de API Next, o Lambda envia um evento Invoke para o runtime e para cada extensão.

A configuração de tempo limite da função limita a duração de toda a fase Invoke. Por exemplo, se você definir o tempo limite da função como 360 segundos, a função e todas as extensões precisam ser concluídas em até 360 segundos. Observe que não há fase de pós-invocação independente. A duração é a soma de todo o tempo de invocação (runtime + extensões) e não é calculada até que a função e todas as extensões tenham terminado a execução.

A fase de invocação termina após o runtime e todas as extensões sinalizam que elas foram concluídas enviando uma solicitação de API Next.

Falhas durante a fase de invocação

Se a função do Lambda falhar ou expirar durante oInvokefase, o Lambda redefine o ambiente de execução. O diagrama a seguir ilustra o comportamento do ambiente de execução do Lambda quando há falha de invocação:

No diagrama anterior:

  • A primeira fase é a fase INIT, que é executada sem erros.

  • A segunda fase é a fase INVOKE, que é executada sem erros.

  • Em algum momento, suponha que a função tenha uma falha de invocação durante a execução (como erro de tempo limite ou de runtime da função). A terceira fase, chamada INVOKE WITH ERROR, ilustra esse caso. Quando isso ocorre, o serviço do Lambda executa uma redefinição. A redefinição se comporta como um evento Shutdown. Primeiro, o Lambda encerra o runtime; depois, envia um evento Shutdown para cada extensão externa registrada. O evento inclui o motivo do desligamento. Se esse ambiente for usado para uma nova invocação, o Lambda reinicializará a extensão e o runtime com a próxima invocação.

    nota

    Redefinir o Lambda não limpa o conteúdo do diretório /tmp antes da próxima fase de inicialização. Esse comportamento é consistente com a fase de desligamento regular.

  • A quarta fase representa a fase INVOKE imediatamente após uma falha de invocação. Aqui, o Lambda reinicializa o ambiente executando a fase INIT. Isso se chama inicialização suprimida. Quando ocorrem inicializações suprimidas, o Lambda não relata explicitamente uma fase adicional de INIT no CloudWatch Logs. Em vez disso, você perceberá que a duração na linha REPORT inclui uma duração adicional de INIT mais a duração de INVOKE. Por exemplo, digamos que você veja os seguintes logs no CloudWatch:

    2022-12-20T01:00:00.000-08:00 START RequestId: XXX Version: $LATEST 2022-12-20T01:00:02.500-08:00 END RequestId: XXX 2022-12-20T01:00:02.500-08:00 REPORT RequestId: XXX Duration: 3022.91 ms Billed Duration: 3000 ms Memory Size: 512 MB Max Memory Used: 157 MB

    Neste exemplo, a diferença entre os carimbos de data e hora REPORT e START é de 2,5 segundos. Isso não corresponde à duração relatada de 3022,91 milissegundos, pois não leva em conta o INIT adicional (inicialização suprimida) que o Lambda executou. Neste exemplo, podemos inferir que a fase INVOKE exata durou 2,5 segundos.

    Para obter mais insights sobre esse comportamento, você pode usar API de Telemetria do Lambda. A API Telemetry emite eventos INIT_START, INIT_RUNTIME_DONE e INIT_REPORT com phase=invoke sempre que ocorrem inicializações suprimidas entre as fases de invocação.

  • A quinta fase representa a fase SHUTDOWN, que é executada sem erros.

Fase de desligamento

Quando o Lambda estiver prestes a encerrar o runtime, ele enviará um evento Shutdown a cada extensão externa registrada. As extensões podem usar esse tempo para tarefas de limpeza finais. O evento Shutdown é uma resposta a uma solicitação de API Next.

Duração: toda a fase Shutdown é limitada a 2 segundos. Se o runtime ou qualquer extensão não responder, o Lambda o encerrará por meio de um sinal (SIGKILL).

Após a conclusão da função e de todas as extensões, o Lambda mantém o ambiente de execução por algum tempo à espera de uma outra invocação de função. No entanto, o Lambda encerra os ambientes de execução a cada poucas horas para permitir atualizações e manutenção do runtime, mesmo para funções que são invocadas continuamente. Você não deve presumir que o ambiente de execução persistirá indefinidamente. Para ter mais informações, consulte Como implementar a ausência de estado em funções.

Quando a função é invocada novamente, o Lambda descongela o ambiente para reutilização. Reutilizar o ambiente de execução tem as seguintes implicações:

  • Os objetos declarados fora do método do manipulador da função permanecem inicializados, fornecendo otimização adicional quando a função é invocada novamente. Por exemplo, se sua função do Lambda estabelecer uma conexão com o banco de dados, em vez de restabelecer a conexão, a conexão original é usada em invocações subsequentes. Recomendamos que você adicione lógica em seu código para verificar se uma há conexão existente antes de criar outra.

  • Cada ambiente de execução fornece entre 512 MB e 10.240 MB, em incrementos de 1 MB, de espaço em disco no diretório /tmp. O conteúdo do diretório permanece quando o ambiente de execução é congelado, fornecendo cache transitório que pode ser usado para várias invocações. Você pode adicionar um código extra para verificar se o cache tem os dados que você armazenou. Para obter mais informações sobre limites de tamanho de implantação, consulte Cotas Lambda.

  • Processos em segundo plano ou retornos de chamada que foram iniciados pela função do Lambda e não foram concluídos quando a função terminou serão retomados se o Lambda reutilizar o ambiente de execução. Garanta que todos os processos em segundo plano ou retornos de chamadas no seu código sejam concluídos antes que o código seja encerrado.

Como implementar a ausência de estado em funções

Ao escrever seu código de função do Lambda, trate o ambiente de execução como sem estado, supondo que ele exista apenas para uma única invocação. O Lambda encerra os ambientes de execução a cada poucas horas para permitir atualizações e manutenção do runtime, mesmo para funções que são invocadas continuamente. Inicialize qualquer estado necessário (por exemplo, buscar um carrinho de compras em uma tabela do Amazon DynamoDB) quando sua função começar. Antes de sair, confirme as alterações permanentes de dados em armazenamentos duráveis, como Amazon Simple Storage Service (Amazon S3), DynamoDB ou Amazon Simple Queue Service (Amazon SQS). Evite depender de estruturas de dados existentes, arquivos temporários ou estados que abranjam invocações, como contadores ou agregados. Isso garante que sua função manipule cada invocação de forma independente.