

# Lambda マネージドインスタンスのランタイム
<a name="lambda-managed-instances-runtimes"></a>

Lambda マネージドインスタンスを使用する場合、Lambda はリクエストを異なる方法で処理します。Lambda マネージドインスタンスは、各実行環境でリクエストを順次処理する代わりに、各実行環境内で複数のリクエストを同時に処理します。この実行モデルの変更により、Lambda マネージドインスタンスを使用する関数は、スレッドセーフ、状態管理、コンテキストの分離、および Lambda (デフォルト) の単一同時実行モデルでは発生しない懸念を考慮する必要があります。さらに、複数同時実行の実装はランタイムによって異なります。

## サポートされている言語
<a name="lambda-managed-instances-supported-runtimes"></a>

Lambda マネージドインスタンスは、次のプログラミング言語とランタイムで使用できます。
+ **Java:** Java 21 以降。
+ **Python:** Python 3.13 以降。
+ **Node.js:** Node.js 22 以降。
+ **.NET:** .NET 8 以降。
+ **Rust:** OS 専用ランタイム `provided.al2023` 以降でサポートされています。

## 言語固有の考慮事項
<a name="lambda-managed-instances-runtime-considerations"></a>

プログラミング言語によって、複数同時実行の実装方法はそれぞれ異なります。適切な同時実行のベストプラクティスを適用するには、選択したプログラミング言語で複数同時実行がどのように実装されるかを理解する必要があります。

**Java**

OS スレッドで単一のプロセスを使用して同時実行を行います。複数のスレッドがハンドラーメソッドを同時に実行するため、状態と共有リソースをスレッドセーフに処理する必要があります。

**Python**

各同時リクエストが個別のプロセスで実行される複数の Python プロセスが使用されます。これにより、ほとんどの同時実行の問題から保護できますが、`/tmp` ディレクトリなどの共有リソースに注意が必要です。

**Node.js**

非同期実行で[ワーカースレッド](https://nodejs.org/api/worker_threads.html)を使用します。同時リクエストはワーカースレッド全体に分散され、さらに各ワーカースレッドは同時リクエストを非同期で処理できるため、状態と共有リソースを安全に処理する必要があります。

**.NET**

複数同時リクエストの非同期処理で .NET タスクを使用します。状態と共有リソースを安全に処理する必要があります。

**Rust**

[Tokio](https://tokio.rs/) を搭載した非同期タスクで単一のプロセスを使用します。ハンドラー値は、`Clone` \$1 `Send` である必要があります。

## 次のステップ
<a name="lambda-managed-instances-runtime-next-steps"></a>

各ランタイムの詳細については、次のトピックを参照してください。
+ [Lambda マネージドインスタンスの Java ランタイム](lambda-managed-instances-java-runtime.md)
+ [Lambda マネージドインスタンスの Node.js ランタイム](lambda-managed-instances-nodejs-runtime.md)
+ [Lambda マネージドインスタンスの Python ランタイム](lambda-managed-instances-python-runtime.md)
+ [Lambda マネージドインスタンスの .NET ランタイム](lambda-managed-instances-dotnet-runtime.md)
+ [Lambda マネージドインスタンスの Rust サポート](lambda-managed-instances-rust.md)

# Lambda マネージドインスタンスの Java ランタイム
<a name="lambda-managed-instances-java-runtime"></a>

Java ランタイムの場合、Lambda マネージドインスタンスは同時実行に OS スレッドを使用します。Lambda は初期化中、実行環境ごとにハンドラーオブジェクトを 1 回ロードし、複数のスレッドを作成します。これらのスレッドは並行して実行されるため、状態と共有リソースをスレッドセーフに処理する必要があります。各スレッドは、同じハンドラーオブジェクトと静的フィールドを共有します。

## 同時実行数の設定
<a name="lambda-managed-instances-java-concurrency-config"></a>

Lambda が各実行環境に送信する同時リクエストの最大数は、関数設定の `PerExecutionEnvironmentMaxConcurrency` 設定で制御できます。これはオプションの設定となっており、デフォルト値はランタイムによって異なります。Java ランタイムの場合の同時リクエスト数は、vCPU あたり 32 件がデフォルト値になっていますが、独自の値を設定することもできます。この値により、Java ランタイムで使用されるスレッドの数も決まります。Lambda は、各実行環境の容量に応じて、設定された最大数までの同時リクエストの数を自動的に調整し、それらのリクエストを取得します。

## 同時実行のための関数の構築
<a name="lambda-managed-instances-java-building"></a>

Lambda マネージドインスタンスを使用する場合は、他のマルチスレッド環境と同じスレッドセーフな環境を適用する必要があります。ハンドラーオブジェクトはすべてのランタイムワーカースレッドで共有されるため、ミュータブルな状態はスレッドセーフである必要があります。これには、コレクション、データベース接続、およびリクエスト処理中に変更される静的オブジェクトが含まれます。

AWS SDK クライアントはスレッドセーフなため、特別な処理は必要ありません。

**例: データベース接続プール**

次のコードでは、スレッド間で共有される静的データベース接続オブジェクトを使用します。使用する接続ライブラリによっては、スレッドセーフではない場合があります。

```
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();
    }
}
```

接続プールを使用することで、スレッドセーフにアプローチできます。次の例では、関数ハンドラーはプールから接続を取得します。接続は 1 つのリクエストのコンテキストでのみ使用されます。

```
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();
    }
}
```

**例: コレクション**

以下の標準 Java コレクションはスレッドセーフではありません。

```
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";
    }
}
```

代わりに、以下のスレッドセーフコレクションを使用します。

```
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";
    }
}
```

## 共有の /tmp ディレクトリ
<a name="lambda-managed-instances-java-shared-tmp"></a>

`/tmp` ディレクトリは、実行環境内のすべての同時リクエスト間で共有されます。同じファイルに同時に書き込むと、別のプロセスによってファイルが上書きされるなど、データの破損が発生する可能性があります。これに対処するには、共有ファイルのファイルロックを実装するか、スレッドごとまたはリクエストごとに一意のファイル名を使用して競合を回避します。空き容量を占有しないよう、不要なファイルはクリーンアップしてください。

## ログ記録
<a name="lambda-managed-instances-java-logging"></a>

ログインターリービング (ログでインターリーブされるさまざまなリクエストからのログエントリ) は、複数同時実行システムでは正常です。

Lambda マネージドインスタンスを使用する関数は常に、[高度なログ記録コントロール](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)で導入した構造化された JSON ログ形式を使用します。この形式には `requestId` が含まれ、ログエントリを 1 つのリクエストに関連付けることができます。`context.getLogger()` から `LambdaLogger` オブジェクトを使用すると、`requestId` は各ログエントリに自動的に含まれます。詳細については、「[Java での Lambda の高度なログ記録コントロールの使用](java-logging.md#java-logging-advanced)」を参照してください。

## リクエストコンテキスト
<a name="lambda-managed-instances-java-request-context"></a>

`context` オブジェクトはリクエストスレッドにバインドされます。`context.getAwsRequestId()` を使用すると、現在のリクエストのリクエスト ID にスレッドセーフにアクセスできます。

`context.getXrayTraceId()` を使用して X-Ray トレース ID にアクセスします。これにより、現在のリクエストのトレース ID にスレッドセーフにアクセスできます。Lambda は、Lambda マネージドインスタンスの `_X_AMZN_TRACE_ID` 環境変数をサポートしていません。AWS SDK を使用すると、X-Ray トレース ID が自動的に伝播されます。

`com.amazonaws.services.lambda.runtime.Context.getRemainingTimeInMillis()` を使用してタイムアウトを検出します。詳細については「[エラー処理と復旧](lambda-managed-instances-execution-environment.md#lambda-managed-instances-error-handling)」を参照してください。

プログラムで仮想スレッドを使用する場合、または初期化中にスレッドを作成する場合は、必要なリクエストコンテキストをこれらのスレッドに渡す必要があります。

## 初期化とシャットダウン
<a name="lambda-managed-instances-java-init-shutdown"></a>

関数の初期化は、実行環境ごとに 1 回行われます。初期化中に作成されたオブジェクトは、スレッド間で共有されます。

拡張機能を持つ Lambda 関数の場合、実行環境はシャットダウン中に SIGTERM シグナルを出力します。このシグナルは拡張機能によって使用され、バッファのフラッシュなどのクリーンアップタスクをトリガーします。SIGTERM イベントにサブスクライブすることで、データベース接続を閉じるなどの関数のクリーンアップタスクを実行できます。実行環境のライフサイクルの詳細については、「[Lambda 実行環境のライフサイクルの概要](lambda-runtime-environment.md)」を参照してください。

## 依存関係バージョン
<a name="lambda-managed-instances-java-dependencies"></a>

Lambda マネージドインスタンスには、以下のパッケージバージョンの最小要件が必要です。
+ AWS SDK for Java 2.0: バージョン 2.34.0 以降
+ AWS X-Ray SDK for Java: バージョン 2.20.0 以降
+ AWS Distro for OpenTelemetry – Instrumentation for Java: バージョン 2.20.0 以降
+ Powertools for AWS Lambda (Java): バージョン 2.8.0 以降

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

Powertools for AWS Lambda (Java) は Lambda マネージドインスタンスと互換性があり、ログ記録、トレース、メトリクスなどのユーティリティを利用できます。詳細については、「[Powertools for AWS Lambda (Java)](https://github.com/aws-powertools/powertools-lambda-java)」を参照してください。

## 次のステップ
<a name="lambda-managed-instances-java-next-steps"></a>
+ 「[Lambda マネージドインスタンスの Node.js ランタイム](lambda-managed-instances-nodejs-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの Python ランタイム](lambda-managed-instances-python-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの .NET ランタイム](lambda-managed-instances-dotnet-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスのスケーリング](lambda-managed-instances-scaling.md)」について説明する

# Lambda マネージドインスタンスの Node.js ランタイム
<a name="lambda-managed-instances-nodejs-runtime"></a>

Node.js ランタイムの場合、Lambda マネージドインスタンスは `async` / `await` ベースの実行でワーカースレッドを使用して同時リクエストを処理します。関数の初期化はワーカースレッドごとに 1 回行われます。同時呼び出しは 2 つのディメンションにわたって処理され、ワーカースレッドは vCPU 間で並列処理を行い、非同期実行は各スレッド内で同時実行を行います。同じワーカースレッドで処理される各同時リクエストは、同じハンドラーオブジェクトとグローバル状態を共有するため、複数同時リクエストで安全に処理する必要があります。

## 最大同時実行数
<a name="lambda-managed-instances-nodejs-max-concurrency"></a>

Lambda が各実行環境に送信する同時リクエストの最大数は、関数設定の `PerExecutionEnvironmentMaxConcurrency` 設定で制御できます。これはオプションの設定となっており、デフォルト値はランタイムによって異なります。Node.js ランタイムの場合の同時リクエスト数は、vCPU あたり 64 件がデフォルト値になっていますが、独自の値を設定することもできます。Lambda は、各実行環境の容量に応じて、設定された最大数までの同時リクエストの数を自動的に調整し、それらのリクエストを取得します。

Node.js の場合、各実行環境が処理できる同時リクエストの数は、同時リクエストを非同期で処理するワーカースレッドの数と各ワーカースレッドの容量によって決まります。ワーカースレッドのデフォルトの数は、使用可能な vCPU の数によって決まります。または、`AWS_LAMBDA_NODEJS_WORKER_COUNT` 環境変数を設定してワーカースレッドの数を設定できます。各ワーカースレッドで数のリクエストを処理できるため、非同期関数ハンドラーを使用することをお勧めします。関数ハンドラーが同期の場合、各ワーカースレッドは一度に 1 つのリクエストのみを処理できます。

## 同時実行のための関数の構築
<a name="lambda-managed-instances-nodejs-building"></a>

非同期関数ハンドラーを使用すると、各ランタイムワーカーは複数のリクエストを同時に処理します。グローバルオブジェクトは、複数の同時リクエスト間で共有されます。ミュータブルなオブジェクトの場合は、グローバル状態を使用しないか、`AsyncLocalStorage` を使用します。

AWS SDK クライアントは非同期に対応しているため、特別な処理は必要ありません。

**例: グローバル状態**

次のコードでは、関数ハンドラー内で変更されるグローバルオブジェクトが使用されています。そのため、非同期に対応しません。

```
let state = {
    currentUser: null,
    requestData: null
};

export const handler = async (event, context) => {
    state.currentUser = event.userId;
    state.requestData = event.data;

    await processData(state.requestData);

    // state.currentUser might now belong to a different request
    return { user: state.currentUser };
};
```

以下のように関数ハンドラー内で `state` オブジェクトを初期化すると、共有グローバル状態を避けられます。

```
export const handler = async (event, context) => {
    let state = {
        currentUser: event.userId,
        requestData: event.data
    };
    
    await processData(state.requestData);

    return { user: state.currentUser };
};
```

**例: データベース接続**

次のコードは、複数の呼び出し間で共有される共有クライアントオブジェクトが使用されています。使用する接続ライブラリによっては、同時実行に対応しない場合があります。

```
const { Client } = require('pg');

// Single connection created at init time
const client = new Client({
  host: process.env.DB_HOST,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD
});

// Connect once during cold start
client.connect();

exports.handler = async (event) => {
  // Multiple parallel invocations share this single connection = BAD
  // With multi-concurrent Lambda, queries will collide
  const result = await client.query('SELECT * FROM users WHERE id = $1', [event.userId]);
  
  return {
    statusCode: 200,
    body: JSON.stringify(result.rows[0])
  };
};
```

同時実行に対応させるには、以下のように接続プールを使用します。プールは、同時データベースクエリごとに個別の接続を使用します。

```
const { Pool } = require('pg');

// Connection pool created at init time
const pool = new Pool({
  host: process.env.DB_HOST,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  max: 20,  // Max connections in pool
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000
});

exports.handler = async (event) => {
  // Pool gives each parallel invocation its own connection
  const result = await pool.query('SELECT * FROM users WHERE id = $1', [event.userId]);
  
  return {
    statusCode: 200,
    body: JSON.stringify(result.rows[0])
  };
};
```

## Node.js 22 コールバックベースのハンドラー
<a name="lambda-managed-instances-nodejs-callback-handlers"></a>

Node.js 22 を使用する場合、Lambda マネージドインスタンスでコールバックベースの関数ハンドラーを使用することはできません。コールバックベースのハンドラーは、Lambda (デフォルト) 関数でのみサポートされています。Node.js 24 以降のランタイムの場合、コールバックベースの関数ハンドラーは Lambda (デフォルト) と Lambda マネージドインスタンスの両方で廃止されています。

代わりに、Lambda マネージドインスタンスを使用する際には `async` 関数ハンドラーを使用します。詳細については、「[Node.js の Lambda 関数ハンドラーの定義](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html)」をご覧ください。

## 共有の /tmp ディレクトリ
<a name="lambda-managed-instances-nodejs-shared-tmp"></a>

`/tmp` ディレクトリは、実行環境内のすべての同時リクエスト間で共有されます。同じファイルに同時に書き込むと、別のプロセスによってファイルが上書きされるなど、データの破損が発生する可能性があります。これに対処するには、共有ファイルのファイルロックを実装するか、リクエストごとに一意のファイル名を使用して競合を回避します。空き容量を占有しないよう、不要なファイルはクリーンアップしてください。

## ログ記録
<a name="lambda-managed-instances-nodejs-logging"></a>

ログインターリービング (ログでインターリーブされるさまざまなリクエストからのログエントリ) は、複数同時実行システムでは正常です。Lambda マネージドインスタンスを使用する関数は常に、[高度なログ記録コントロール](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)で導入した構造化された JSON ログ形式を使用します。この形式には `requestId` が含まれ、ログエントリを 1 つのリクエストに関連付けることができます。`console` ロガーを使用すると、`requestId` が各ログエントリに自動的に含まれます。詳細については、「[Node.js での Lambda の高度なログ記録コントロールの使用](nodejs-logging.md#node-js-logging-advanced)」を参照してください。

[Winston](https://github.com/winstonjs/winston) などの一般的なサードパーティーのログ記録ライブラリには、通常、ログ出力にコンソールを使用できるサポートが含まれています。

## リクエストコンテキスト
<a name="lambda-managed-instances-nodejs-request-context"></a>

`context.awsRequestId` を使用すると、現在のリクエストのリクエスト ID に非同期対応でアクセスできます。

`context.xRayTraceId` を使用して X-Ray トレース ID にアクセスします。これにより、現在のリクエストのトレース ID への同時実行に対応したアクセスが可能になります。Lambda は、Lambda マネージドインスタンスの `_X_AMZN_TRACE_ID` 環境変数をサポートしていません。AWS SDK を使用すると、X-Ray トレース ID が自動的に伝播されます。

`context.getRemainingTimeInMillis()` を使用してタイムアウトを検出します。詳細については「[エラー処理と復旧](lambda-managed-instances-execution-environment.md#lambda-managed-instances-error-handling)」を参照してください。

## 初期化とシャットダウン
<a name="lambda-managed-instances-nodejs-init-shutdown"></a>

関数の初期化はワーカースレッドごとに 1 回行われます。関数が初期化中にログを発行すると、繰り返しログエントリが表示されることがあります。

拡張機能を持つ Lambda 関数の場合、実行環境はシャットダウン中に SIGTERM シグナルを出力します。このシグナルは拡張機能によって使用され、バッファのフラッシュなどのクリーンアップタスクをトリガーします。拡張機能を持つ Lambda (デフォルト) 関数は、`process.on()` を使用して SIGTERM シグナルにサブスクライブすることもできます。これは、ワーカースレッドでは `process.on()` を使用できないため、Lambda マネージドインスタンスを使用する関数ではサポートされていません。実行環境のライフサイクルの詳細については、「[Lambda 実行環境のライフサイクルの概要](lambda-runtime-environment.md)」を参照してください。

## 依存関係バージョン
<a name="lambda-managed-instances-nodejs-dependencies"></a>

Lambda マネージドインスタンスには、以下のパッケージバージョンの最小要件が必要です。
+ AWS SDK for JavaScript v3: バージョン 3.933.0 以降
+ AWS X-Ray SDK for Node.js: バージョン 3.12.0 以降
+ AWS Distro for OpenTelemetry – Instrumentation for JavaScript: バージョン 0.8.0 以降
+ Powertools for AWS Lambda (TypeScript): バージョン 2.29.0 以降

## Powertools for AWS Lambda (TypeScript)
<a name="lambda-managed-instances-nodejs-powertools"></a>

Powertools for AWS Lambda (TypeScript) は Lambda マネージドインスタンスと互換性があり、ログ記録、トレース、メトリクスなどのユーティリティを利用できます。詳細については、「[Powertools for AWS Lambda (TypeScript)](https://github.com/aws-powertools/powertools-lambda-typescript)」を参照してください。

## 次のステップ
<a name="lambda-managed-instances-nodejs-next-steps"></a>
+ 「[Lambda マネージドインスタンスの Java ランタイム](lambda-managed-instances-java-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの Python ランタイム](lambda-managed-instances-python-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの .NET ランタイム](lambda-managed-instances-dotnet-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスのスケーリング](lambda-managed-instances-scaling.md)」について説明する

# Lambda マネージドインスタンスの Python ランタイム
<a name="lambda-managed-instances-python-runtime"></a>

Lambda ランタイムは、複数の Python プロセスを使用して同時リクエストを処理します。各同時リクエストは、独自のメモリ容量と初期化を備えた個別のプロセスで実行されます。各プロセスは、一度に 1 つのリクエストを同期的に処理します。プロセスのメモリは直接共有されないため、グローバル変数、モジュールレベルのキャッシュ、およびシングルトンオブジェクトは同時リクエスト間で分離されます。

## 同時実行数の設定
<a name="lambda-managed-instances-python-concurrency-config"></a>

Lambda が各実行環境に送信する同時リクエストの最大数は、関数設定の `PerExecutionEnvironmentMaxConcurrency` 設定で制御できます。これはオプションの設定となっており、デフォルト値はランタイムによって異なります。Python ランタイムの場合の同時リクエスト数は、vCPU あたり 16 件がデフォルト値になっていますが、独自の値を設定することもできます。この値により、Python ランタイムで使用されるプロセスの数も決まります。Lambda は、各実行環境の容量に応じて、設定された最大数までの同時リクエストの数を自動的に調整し、それらのリクエストを取得します。

**重要**  
プロセスベースの同時実行を使用すると、各ランタイムワーカープロセスが独自に初期化を実行します。合計メモリ使用量は、プロセスごとのメモリに同時プロセス数を乗じたものと等しくなります。大きなライブラリまたはデータセットをロードしていて、同時実行性が高い場合は、メモリフットプリントが大きくなります。ワークロードによっては、CPU 対メモリの比率を調整するか、同時実行を低く設定して、利用可能なメモリを超過しないようにする必要があります。CloudWatch の `MemoryUtilization` メトリクスを使用して、メモリ消費量を追跡できます。

## 同時実行のための関数の構築
<a name="lambda-managed-instances-python-building"></a>

プロセスベースの複数同時実行モデルにより、Python ランタイムを使用する Lambda マネージドインスタンス関数は、複数の呼び出しからメモリ内リソースに同時にアクセスしません。メモリ内同時実行の安全性のためにコーディングプラクティスを適用する必要はありません。

## 共有の /tmp ディレクトリ
<a name="lambda-managed-instances-python-shared-tmp"></a>

`/tmp` ディレクトリは、実行環境内のすべての同時リクエスト間で共有されます。同じファイルに同時に書き込むと、別のプロセスによってファイルが上書きされるなど、データの破損が発生する可能性があります。これに対処するには、共有ファイルのファイルロックを実装するか、プロセスごとまたはリクエストごとに一意のファイル名を使用して競合を回避します。空き容量を占有しないよう、不要なファイルはクリーンアップしてください。

## ログ記録
<a name="lambda-managed-instances-python-logging"></a>

ログインターリービング (ログでインターリーブされるさまざまなリクエストからのログエントリ) は、複数同時実行システムでは正常です。

Lambda マネージドインスタンスを使用する関数は常に、[高度なログ記録コントロール](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)で導入した構造化された JSON ログ形式を使用します。この形式には `requestId` が含まれ、ログエントリを 1 つのリクエストに関連付けることができます。Lambda の Python 標準ライブラリの `logging` モジュールを使用すると、`requestId` が各ログエントリに自動的に含まれます。詳細については、「[Python での Lambda の高度なログ記録コントロールの使用](https://docs.aws.amazon.com/lambda/latest/dg/python-logging.html#python-logging-advanced)」を参照してください。

## リクエストコンテキスト
<a name="lambda-managed-instances-python-request-context"></a>

`context.aws_request_id` を使用して、現在のリクエストのリクエスト ID にアクセスします。

Python ランタイムでは、`_X_AMZN_TRACE_ID` 環境変数を使用して、Lambda マネージドインスタンスで X-Ray トレース ID にアクセスできます。AWS SDK を使用すると、X-Ray トレース ID が自動的に伝播されます。

`context.get_remaining_time_in_millis()` を使用してタイムアウトを検出します。詳細については「[エラー処理と復旧](lambda-managed-instances-execution-environment.md#lambda-managed-instances-error-handling)」を参照してください。

## 初期化とシャットダウン
<a name="lambda-managed-instances-python-init-shutdown"></a>

関数の初期化はプロセスごとに 1 回行われます。関数が初期化中にログを発行すると、繰り返しログエントリが表示されることがあります。

拡張機能を持つ Lambda 関数の場合、実行環境はシャットダウン中に SIGTERM シグナルを出力します。このシグナルは拡張機能によって使用され、バッファのフラッシュなどのクリーンアップタスクをトリガーします。SIGTERM イベントにサブスクライブすることで、データベース接続を閉じるなどの関数のクリーンアップタスクを実行できます。実行環境のライフサイクルの詳細については、「[Lambda 実行環境のライフサイクルの概要](lambda-runtime-environment.md)」を参照してください。

## 依存関係バージョン
<a name="lambda-managed-instances-python-dependencies"></a>

Lambda マネージドインスタンスには、以下のパッケージバージョンの最小要件が必要です。
+ Powertools for AWS Lambda (Python): バージョン 3.23.0 以降

## Powertools for AWS Lambda (Python)
<a name="lambda-managed-instances-python-powertools"></a>

Powertools for AWS Lambda (Python) は Lambda マネージドインスタンスと互換性があり、ログ記録、トレース、メトリクスなどのユーティリティを利用できます。詳細については、「[Powertools for AWS Lambda (Python)](https://github.com/aws-powertools/powertools-lambda-python)」を参照してください。

## 次のステップ
<a name="lambda-managed-instances-python-next-steps"></a>
+ 「[Lambda マネージドインスタンスの Java ランタイム](lambda-managed-instances-java-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの Node.js ランタイム](lambda-managed-instances-nodejs-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの .NET ランタイム](lambda-managed-instances-dotnet-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスのスケーリング](lambda-managed-instances-scaling.md)」について説明する

# Lambda マネージドインスタンスの .NET ランタイム
<a name="lambda-managed-instances-dotnet-runtime"></a>

.NET ランタイムの場合、Lambda マネージドインスタンスは実行環境ごとに 1 つの .NET プロセスを使用します。複数の同時リクエストは、.NET タスクを使用して処理されます。

## 同時実行数の設定
<a name="lambda-managed-instances-dotnet-concurrency-config"></a>

Lambda が各実行環境に送信する同時リクエストの最大数は、関数設定の `PerExecutionEnvironmentMaxConcurrency` 設定で制御できます。これはオプションの設定となっており、デフォルト値はランタイムによって異なります。.NET ランタイムの場合、デフォルト値は vCPU あたり 32 件の同時リクエスト数になります。または、独自の値を設定できます。Lambda は、各実行環境の容量に応じて、設定された最大数までの同時リクエストの数を自動的に調整し、それらのリクエストを取得します。

## 同時実行のための関数の構築
<a name="lambda-managed-instances-dotnet-building"></a>

Lambda マネージドインスタンスを使用する場合は、他の複数同時実行環境と同じ同時実行のセーフなプラクティスを適用する必要があります。ハンドラーオブジェクトはすべてのタスクで共有されるため、変更可能な状態はスレッドセーフである必要があります。これには、コレクション、データベース接続、およびリクエスト処理中に変更されるあらゆる静的オブジェクトが含まれます。

AWS SDK クライアントはスレッドセーフなため、特別な処理は必要ありません。

**例: データベース接続プール**

次のコードは、同時リクエスト間で共有される静的データベース接続オブジェクトを使用します。`SqlConnection` オブジェクトはスレッドセーフではありません。

```
public class DBQueryHandler
{
    // Single connection shared across threads - NOT SAFE
    private SqlConnection connection;

    public DBQueryHandler()
    {
        connection = new SqlConnection("your-connection-string-here");
        connection.Open();
    }

    public string Handle(object input, ILambdaContext context)
    {
        using var cmd = connection.CreateCommand();
        cmd.CommandText = "SELECT ..."; // your query

        using var reader = cmd.ExecuteReader();

        ...
    }
}
```

これに対処するには、接続プールから取得したリクエストごとに個別の接続を使用します。`Microsoft.Data.SqlClient` などの ADO.NET プロバイダーは、接続オブジェクトが開かれると、接続プーリングを自動的にサポートします。

```
public class DBQueryHandler
{
    public DBQueryHandler()
    {
    }

    public string Handle(object input, ILambdaContext context)
    {
        using var connection = new SqlConnection("your-connection-string-here");
        connection.Open();
        using var cmd = connection.CreateCommand();
        cmd.CommandText = "SELECT ..."; // your query

        using var reader = cmd.ExecuteReader();

        ...
    }
}
```

**例: コレクション**

標準の .NET コレクションはスレッドセーフではありません。

```
public class Handler
{
    private static List<string> items = new List<string>();
    private static Dictionary<string, object> cache = new Dictionary<string, object>();

    public string FunctionHandler(object input, ILambdaContext context)
    {
        items.Add(context.AwsRequestId);
        cache["key"] = input;

        return "Success";
    }
}
```

同時実行がセーフになるように、`System.Collections.Concurrent` 名前空間のコレクションを使用します。

```
public class Handler
{
    private static ConcurrentBag<string> items = new ConcurrentBag<string>();
    private static ConcurrentDictionary<string, object> cache = new ConcurrentDictionary<string, object>();

    public string FunctionHandler(object input, ILambdaContext context)
    {
        items.Add(context.AwsRequestId);
        cache["key"] = input;

        return "Success";
    }
}
```

## 共有の /tmp ディレクトリ
<a name="lambda-managed-instances-dotnet-shared-tmp"></a>

`/tmp` ディレクトリは、実行環境内のすべての同時リクエスト間で共有されます。同じファイルに同時に書き込むと、別のリクエストによってファイルが上書きされるなど、データの破損が発生する可能性があります。これに対処するには、共有ファイルのファイルロックを実装するか、リクエストごとに一意のファイル名を使用して競合を回避します。空き容量を占有しないよう、不要なファイルはクリーンアップしてください。

## ログ記録
<a name="lambda-managed-instances-dotnet-logging"></a>

ログインターリービング (ログでインターリーブされるさまざまなリクエストからのログエントリ) は、複数同時実行システムでは正常です。Lambda マネージドインスタンスを使用する関数は常に、[高度なログ記録コントロール](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)で導入した構造化された JSON ログ形式を使用します。この形式には `requestId` が含まれ、ログエントリを 1 つのリクエストに関連付けることができます。`context.Logger` オブジェクトを使用してログを生成すると、`requestId` は各ログエントリに自動的に含まれます。詳細については、「[.NET での Lambda の高度なログ記録コントロールの使用](csharp-logging.md#csharp-logging-advanced)」を参照してください。

## リクエストコンテキスト
<a name="lambda-managed-instances-dotnet-request-context"></a>

`context.AwsRequestId` プロパティを使用して、現在のリクエストのリクエスト ID にアクセスします。

`context.TraceId` プロパティを使用して、X-Ray トレース ID にアクセスします。これにより、現在のリクエストのトレース ID への同時実行に対応したアクセスが可能になります。Lambda は、Lambda マネージドインスタンスの `_X_AMZN_TRACE_ID` 環境変数をサポートしていません。AWS SDK を使用すると、X-Ray トレース ID が自動的に伝播されます。

`ILambdaContext.RemainingTime` を使用してタイムアウトを検出します。詳細については「[エラー処理と復旧](lambda-managed-instances-execution-environment.md#lambda-managed-instances-error-handling)」を参照してください。

## 初期化とシャットダウン
<a name="lambda-managed-instances-dotnet-init-shutdown"></a>

関数の初期化は、実行環境ごとに 1 回行われます。初期化中に作成されたオブジェクトは、リクエスト間で共有されます。

拡張機能を持つ Lambda 関数の場合、実行環境はシャットダウン中に SIGTERM シグナルを出力します。このシグナルは拡張機能によって使用され、バッファのフラッシュなどのクリーンアップタスクをトリガーします。SIGTERM イベントにサブスクライブすることで、データベース接続を閉じるなどの関数のクリーンアップタスクを実行できます。実行環境のライフサイクルの詳細については、「[Lambda 実行環境のライフサイクルの概要](lambda-runtime-environment.md)」を参照してください。

## 依存関係バージョン
<a name="lambda-managed-instances-dotnet-dependencies"></a>

Lambda マネージドインスタンスには、以下のパッケージバージョンの最小要件が必要です。
+ Amazon.Lambda.Core: バージョン 2.7.1 以降
+ Amazon.Lambda.RuntimeSupport: バージョン 1.14.1 以降
+ OpenTelemetry.Instrumentation.AWSLambda: バージョン 1.14.0 以降
+ AWSXRayRecorder.Core: バージョン 2.16.0 以降
+ AWSSDK.Core: バージョン 4.0.0.32 以降

## Powertools for AWS Lambda (.NET)
<a name="lambda-managed-instances-dotnet-powertools"></a>

[Powertools for AWS Lambda (.NET)](https://docs.aws.amazon.com/powertools/dotnet/) および [AWS Distro for OpenTelemetry – Instrumentation for DotNet](https://github.com/aws-observability/aws-otel-dotnet-instrumentation) は現在、Lambda マネージドインスタンスをサポートしていません。

## 次のステップ
<a name="lambda-managed-instances-dotnet-next-steps"></a>
+ 「[Lambda マネージドインスタンスの Java ランタイム](lambda-managed-instances-java-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの Node.js ランタイム](lambda-managed-instances-nodejs-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスの Python ランタイム](lambda-managed-instances-python-runtime.md)」を確認する
+ 「[Lambda マネージドインスタンスのスケーリング](lambda-managed-instances-scaling.md)」について説明する

# Lambda マネージドインスタンスの Rust サポート
<a name="lambda-managed-instances-rust"></a>

## 同時実行数の設定
<a name="lambda-managed-instances-rust-concurrency-config"></a>

Lambda が各実行環境に送信する同時リクエストの最大数は、関数設定の `PerExecutionEnvironmentMaxConcurrency` 設定で制御できます。これはオプション設定です。Rust のデフォルト値は vCPU ごとに 8 つの同時リクエストですが、独自の値を設定することも可能です。この値は、ランタイムによってスポーンされた Tokio タスクの数を決定するもので、実行環境の存続期間中は固定 (静的) となります。各ワーカーは実行中のリクエストを 1 つだけ処理し、多重処理することはありません。Lambda は、各実行環境の容量に応じて、設定された最大数までの同時リクエストの数を自動的に調整し、それらのリクエストを取得します。

## 同時実行のための関数の構築
<a name="lambda-managed-instances-rust-building"></a>

Lambda マネージドインスタンスを使用する場合は、他のマルチスレッド環境と同じスレッドセーフな環境を適用する必要があります。ハンドラーオブジェクトはすべてのワーカースレッドで共有されるため、ミュータブルな状態はスレッドセーフである必要があります。これには、コレクション、データベース接続、およびリクエスト処理中に変更される静的オブジェクトが含まれます。

同時リクエスト処理を有効にするには、 `concurrency-tokio` 機能フラグを `Cargo.toml` ファイルに追加します。

```
[dependencies]  
lambda_runtime = { version = "1", features = ["concurrency-tokio"] }
```

`lambda_runtime::run_concurrent(…)` エントリポイントは、通常メイン関数の `#[tokio::main]` 属性によって提供される Tokio ランタイム内から呼び出す必要があります。ハンドラークロージャは [https://doc.rust-lang.org/std/clone/trait.Clone.html](https://doc.rust-lang.org/std/clone/trait.Clone.html) \$1 [https://doc.rust-lang.org/std/marker/trait.Send.html](https://doc.rust-lang.org/std/marker/trait.Send.html) を実装する必要があります。これにより、フレームワークは複数の非同期タスク間でハンドラーを安全に共有できます。これらの境界が満たされない場合、コードはコンパイルエラーになります。

呼び出し間で共有される状態 (データベース接続プールや設定構造体など) が必要な場合は、それを [https://doc.rust-lang.org/std/sync/struct.Arc.html](https://doc.rust-lang.org/std/sync/struct.Arc.html) で包み、各呼び出しごとにその `Arc` をクローンします。

すべての AWS SDK for Rust クライアントは同時実行セーフであり、特別な処理は必要ありません。

### 例: AWS SDK クライアント
<a name="lambda-managed-instances-rust-example-sdk"></a>

次の例では、S3 クライアントを使用して、呼び出しごとにオブジェクトをアップロードします。クライアントは、`Arc` を介さず、直接クロージャ内へクローンされます。

```
let config = aws_config::load_defaults(BehaviorVersion::latest()).await;  
let s3_client = aws_sdk_s3::Client::new(&config);  
  
run_concurrent(service_fn(move |event: LambdaEvent<Request>| {  
    let s3_client = s3_client.clone(); // cheap clone, no Arc needed  
    async move {  
        s3_client.put_object()  
            .bucket(&event.payload.bucket)  
            .key(&event.payload.key)  
            .body(event.payload.body.into_bytes().into())  
            .send()  
            .await?;  
        Ok(Response { message: "uploaded".into() })  
    }  
}))  
.await
```

### 例: データベース接続プール
<a name="lambda-managed-instances-rust-example-db"></a>

クライアントや設定などの共有状態にハンドラからアクセスする必要がある場合は、それらを [https://doc.rust-lang.org/std/sync/struct.Arc.html](https://doc.rust-lang.org/std/sync/struct.Arc.html) で包み、各呼び出しごとにその `Arc` をクローンします。

```
#[derive(Debug)]  
struct AppState {  
    dynamodb_client: DynamoDbClient,  
    table_name: String,  
    cache_ttl: Duration,  
}  
  
let config = aws_config::load_defaults(BehaviorVersion::latest()).await;  
let state = Arc::new(AppState {  
    dynamodb_client: DynamoDbClient::new(&config),  
    table_name: std::env::var("TABLE_NAME").expect("TABLE_NAME must be set"),  
    cache_ttl: Duration::from_secs(300),  
});  
  
run_concurrent(service_fn(move |event: LambdaEvent<Request>| {  
    let state = state.clone();  
    async move { handle(event, state).await }  
}))  
.await
```

## 共有の /tmp ディレクトリ
<a name="lambda-managed-instances-rust-tmp"></a>

`/tmp` ディレクトリは、実行環境内のすべての同時呼び出し間で共有されます。呼び出しごとに一意のファイル名 (例えばリクエスト ID を含める) を使用するか、明示的なファイルロックを実装してデータの破損を回避します。

## ログ記録
<a name="lambda-managed-instances-rust-logging"></a>

ログインターリービング (ログでインターリーブされるさまざまなリクエストからのログエントリ) は、複数同時実行システムでは正常です。Lambda マネージドインスタンスを使用する関数は、Lambda の[高度なログ記録コントロール](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)を通じて、構造化された JSON ログ形式をサポートします。この形式には `requestId` が含まれ、ログエントリを 1 つのリクエストに関連付けることができます。詳細については、「[トレーシングクレートによる高度なログ記録機能の実装](rust-logging.md#rust-logging-tracing)」を参照してください。

## リクエストコンテキスト
<a name="lambda-managed-instances-rust-context"></a>

`Context` オブジェクトは各ハンドラー呼び出しに直接渡されます。`event.context.request_id` を使用して、現在のリクエストのリクエスト ID にアクセスします。

`event.context.xray_trace_id` を使用して X-Ray トレース ID にアクセスします。Lambda は、Lambda マネージドインスタンスの `_X_AMZN_TRACE_ID` 環境変数をサポートしていません。AWS SDK for Rust を使用すると、X-Ray トレース ID が自動的に伝播されます。

`event.context.deadline` を使用してタイムアウトを検出します。これには、呼び出しの期限がミリ秒単位で含まれます。

## 初期化とシャットダウン
<a name="lambda-managed-instances-rust-lifecycle"></a>

関数の初期化は、実行環境ごとに 1 回行われます。初期化中に作成されたオブジェクトは、リクエスト間で共有されます。

拡張機能を持つ Lambda 関数の場合、実行環境はシャットダウン中に SIGTERM シグナルを出力します。このシグナルは、バッファのフラッシュなどのクリーンアップタスクをトリガーするために拡張機能で使用されます。 `lambda_runtime` は、グレースフルシャットダウンのシグナル処理の設定を簡略化するヘルパー関数 [https://docs.rs/lambda_runtime/latest/lambda_runtime/fn.spawn_graceful_shutdown_handler.html](https://docs.rs/lambda_runtime/latest/lambda_runtime/fn.spawn_graceful_shutdown_handler.html) を提供しています。実行環境のライフサイクルの詳細については、「[Lambda 実行環境のライフサイクルの概要](lambda-runtime-environment.md)」を参照してください。

## 依存関係バージョン
<a name="lambda-managed-instances-rust-dependencies"></a>

Lambda マネージドインスタンスには、以下のパッケージバージョンの最小要件が必要です。
+ `lambda_runtime`: バージョン 1.1.1 以降 (`concurrency-tokio` 機能が有効であること)
+ 最小サポート Rust バージョン (MSRV) は 1.84.0 です。