

# Runtime de Java para instâncias gerenciadas do Lambda
<a name="lambda-managed-instances-java-runtime"></a>

Para runtimes de Java, as instâncias gerenciadas do Lambda usam threads do sistema operacional para simultaneidade. O Lambda carrega seu objeto manipulador uma vez por ambiente de execução durante a inicialização e, em seguida, cria vários threads. Esses threads são executados paralelamente e exigem um tratamento seguro do estado e dos recursos compartilhados. Cada thread compartilha o mesmo objeto manipulador e quaisquer campos estáticos.

## Configuração de simultaneidade
<a name="lambda-managed-instances-java-concurrency-config"></a>

O número máximo de solicitações simultâneas que o Lambda envia para cada ambiente de execução é controlado pela definição `PerExecutionEnvironmentMaxConcurrency` da configuração da função. Essa é uma definição opcional e o valor padrão varia de acordo com o runtime. Para runtimes de Java, o padrão é 32 solicitações simultâneas por vCPU, ou é possível configurar seu próprio valor. Esse valor também determina o número de threads usados pelo runtime de Java. O Lambda ajusta automaticamente o número de solicitações simultâneas até o máximo configurado com base na capacidade de cada ambiente de execução de absorver essas solicitações.

## Funções de construção para multissimultaneidade
<a name="lambda-managed-instances-java-building"></a>

É necessário aplicar as mesmas práticas de segurança de thread ao usar instâncias gerenciadas do Lambda como você faria em qualquer outro ambiente de vários threads. Como o objeto manipulador é compartilhado entre todas as threads de operador de runtime, qualquer estado mutável deve ser seguro para threads. Isso inclui coleções, conexões de banco de dados e quaisquer objetos estáticos que sejam modificados durante o processamento da solicitação.

Os clientes de SDK da AWS são seguros para threads e não exigem tratamento especial.

**Exemplo: grupos de conexão de banco de dados**

O código a seguir usa um objeto de conexão de banco de dados estático que é compartilhado entre threads. Dependendo da biblioteca de conexão usada, isso pode não ser seguro para threads.

```
public class DBQueryHandler implements RequestHandler<Object, String> {
    // Single connection shared across all threads - NOT SAFE
    private static Connection connection;

    public DBQueryHandler() {
        this.connection = DriverManager.getConnection(jdbcUrl, username, password);
    }

    @Override
    public String handleRequest(Object input, Context context) {
        PreparedStatement stmt = connection.prepareStatement(query);
        ResultSet rs = stmt.executeQuery();
        // Multiple threads using same connection causes issues
        return result.toString();
    }
}
```

Uma abordagem segura para threads é usar um grupo de conexões. No exemplo a seguir, o manipulador de funções recupera uma conexão do grupo. A conexão só é usada no contexto de uma única solicitação.

```
public class DBQueryHandler implements RequestHandler<Object, String> {

    private static HikariDataSource dataSource;

    public DBQueryHandler() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/your_database");
        dataSource = new HikariDataSource(config); // Create pool once per Lambda container
    }

    @Override
    public String handleRequest(Object input, Context context) {
        String query = "SELECT column_name FROM your_table LIMIT 10";
        StringBuilder result = new StringBuilder("Data:\n");

        // try-with-resources automatically calls close() on the connection,
        // which returns it to the HikariCP pool (does NOT close the physical DB connection)
        try (Connection connection = dataSource.getConnection();
             PreparedStatement stmt = connection.prepareStatement(query);
             ResultSet rs = stmt.executeQuery()) {

            while (rs.next()) {
                result.append(rs.getString("column_name")).append("\n");
            }

        } catch (Exception e) {
            context.getLogger().log("Error: " + e.getMessage());
            return "Error";
        }

        return result.toString();
    }
}
```

**Exemplo: coleções**

As coleções de Java padrão não são seguras para threads:

```
public class Handler implements RequestHandler<Object, String> {
    private static List<String> items = new ArrayList<>();
    private static Map<String, Object> cache = new HashMap<>();

    @Override
    public String handleRequest(Object input, Context context) {
        items.add("list item");  // Not thread-safe
        cache.put("key", input); // Not thread-safe
        return "Success";
    }
}
```

Em vez disso, use coleções seguras para threads:

```
public class Handler implements RequestHandler<Object, String> {
    private static final List<String> items = 
        Collections.synchronizedList(new ArrayList<>());
    private static final ConcurrentHashMap<String, Object> cache = 
        new ConcurrentHashMap<>();

    @Override
    public String handleRequest(Object input, Context context) {
        items.add("list item");  // Thread-safe
        cache.put("key", input); // Thread-safe
        return "Success";
    }
}
```

## Diretório /tmp compartilhado
<a name="lambda-managed-instances-java-shared-tmp"></a>

O diretório `/tmp` é compartilhado entre todas as solicitações simultâneas no ambiente de execução. Gravações simultâneas no mesmo arquivo podem causar corrupção de dados, por exemplo, se outro processo sobrescrever o arquivo. Para resolver isso, implemente o bloqueio de arquivos para arquivos compartilhados ou use nomes de arquivo exclusivos por thread ou por solicitação para evitar conflitos. Lembre-se de limpar arquivos desnecessários para evitar o esgotamento do espaço disponível.

## Registro em log
<a name="lambda-managed-instances-java-logging"></a>

A intercalação de logs (entradas de logs de solicitações diferentes sendo intercaladas em logs) é normal em sistemas multissimultâneos.

As funções que usam instâncias gerenciadas do Lambda sempre usam o formato de log de JSON estruturado introduzido com [controles de registro em log avançados](monitoring-logs.md#monitoring-cloudwatchlogs-advanced). Esse formato inclui o `requestId`, permitindo que as entradas de log sejam correlacionadas a uma única solicitação. Quando você usa o objeto `LambdaLogger` de `context.getLogger()`, o `requestId` é incluído automaticamente em cada entrada de log. Consulte para obter mais informações [Usar controles avançados de registro em log do Lambda com Java](java-logging.md#java-logging-advanced).

## Contexto da solicitação
<a name="lambda-managed-instances-java-request-context"></a>

O objeto `context` está vinculado ao thread da solicitação. O uso de `context.getAwsRequestId()` proporciona acesso com segurança de thread para acessar o ID da solicitação atual.

Use `context.getXrayTraceId()` para acessar o ID de rastreamento do X-Ray. Isso fornece acesso com segurança de thread ao ID de rastreamento da solicitação atual. O Lambda não oferece suporte à variável de ambiente `_X_AMZN_TRACE_ID` com instâncias gerenciadas do Lambda. O ID de rastreamento do X-Ray é propagado automaticamente ao usar o AWS SDK.

Use `com.amazonaws.services.lambda.runtime.Context.getRemainingTimeInMillis()` para detectar tempos limite. Consulte [Tratamento de erros e recuperação](lambda-managed-instances-execution-environment.md#lambda-managed-instances-error-handling) para obter mais informações.

Se você usar threads virtuais em seu programa ou criar threads durante a inicialização, precisará passar qualquer contexto de solicitação necessário para esses threads.

## Inicialização e desligamento
<a name="lambda-managed-instances-java-init-shutdown"></a>

A inicialização da função ocorre uma vez por ambiente de execução. Os objetos criados durante a inicialização são compartilhados entre os threads.

Para as funções do Lambda com extensões, o ambiente de execução emite um sinal SIGTERM durante o desligamento. Esse sinal é usado pelas extensões para acionar tarefas de limpeza, como descarregar buffers. É possível se inscrever em eventos SIGTERM para acionar tarefas de limpeza de funções, como fechar conexões de banco de dados. Para saber mais sobre o ciclo de vida do ambiente de execução, consulte [Noções básicas sobre o ciclo de vida do ambiente de execução do Lambda](lambda-runtime-environment.md).

## Versões de dependências
<a name="lambda-managed-instances-java-dependencies"></a>

As instâncias gerenciadas do Lambda exigem as versões mínimas de pacotes a seguir:
+ AWS SDK para Java 2.0: versão 2.34.0 ou posterior
+ AWS X-Ray SDK para Java: versão 2.20.0 ou posterior
+ AWS Distro para OpenTelemetry - Instrumentação para Java: versão 2.20.0 ou posterior
+ Powertools para AWS Lambda (Java): versão 2.8.0 ou posterior

## Powertools para AWS Lambda (Java)
<a name="lambda-managed-instances-java-powertools"></a>

O Powertools para AWS Lambda (Java) é compatível com as instâncias gerenciadas do Lambda e fornece utilitários para registro em log, rastreamento, métricas e muito mais. Para obter mais informações, consulte [Powertools para AWS Lambda (Java)](https://github.com/aws-powertools/powertools-lambda-java).

## Próximas etapas
<a name="lambda-managed-instances-java-next-steps"></a>
+ Analise o [runtime de Node.js para instâncias gerenciadas do Lambda](lambda-managed-instances-nodejs-runtime.md)
+ Analise o [runtime de Python para instâncias gerenciadas do Lambda](lambda-managed-instances-python-runtime.md)
+ Analise o [runtime de .NET para instâncias gerenciadas do Lambda](lambda-managed-instances-dotnet-runtime.md)
+ Saiba mais sobre a [escalabilidade de instâncias gerenciadas do Lambda](lambda-managed-instances-scaling.md)