インスタンスの同時実行数とは、各関数インスタンスが一度に処理できる同時リクエストの最大数を指定するものです。Function Compute のインスタンス同時実行機能を使用すると、トラフィックのピーク時にリソース使用量を効率的に管理し、コールドスタートの影響を軽減できます。これにより、パフォーマンスの向上とコストの削減に役立ちます。
背景情報
Function Compute のリソース使用量は、関数インスタンスの実行時間と仕様に基づいて課金されます。したがって、関数インスタンスの実行時間が長くなるほど、リソース使用料は高くなります。
たとえば、一度に 3 つのリクエストを処理する必要があり、各リクエストの処理には 10 秒かかるとします。以下に、異なる同時実行数設定での実行時間を示します。
インスタンスの同時実行数を 1 に設定した場合、各インスタンスは一度に 1 つのリクエストしか処理できません。Function Compute は 3 つのインスタンスを作成して 3 つのリクエストを処理します。合計実行時間は 30 秒です。
インスタンスの同時実行数を 10 に設定し、この同時実行数がインスタンスの 1 秒あたりのクエリ数 (QPS) 制限を超えない場合、各インスタンスは一度に 10 個のリクエストを処理できます。Function Compute は 1 つのインスタンスのみを作成して 3 つのリクエストを処理します。合計実行時間は 10 秒です。
関数インスタンスの同時実行数を 1 に設定した場合、各インスタンスは一度に 1 つのリクエストしか処理できません。インスタンスの同時実行数を 1 より大きい値に設定した場合、Function Compute は、既存のインスタンスで同時に処理されるリクエスト数が指定値を超えた場合にのみ、新しいインスタンスを作成します。
インスタンスの同時実行数は、通常、インスタンスの仕様と一緒に設定されます。これにより、関数のパフォーマンスを最適化し、コストを削減できます。
次の図は、インスタンスの同時実行数を異なる値に設定した場合のリクエスト実行の違いを示しています。
メリット
実行時間とコストの削減
たとえば、多数の I/O 操作を伴う関数では、1 つのインスタンスを使用して複数のリクエストを同時に処理できます。これにより、リクエストの処理に使用されるインスタンスの数が減り、リクエストの合計実行時間が短縮されます。
リクエスト間での状態の共有
複数のリクエストが 1 つのインスタンス内でデータベースの接続プールを共有できるため、リクエストとデータベース間の接続を最小限に抑えることができます。
コールドスタートの頻度の削減
1 つのインスタンスで複数のリクエストを処理できるため、新しいインスタンスの数が減り、コールドスタートの頻度が低下します。
Virtual Private Cloud (VPC) で使用される IP アドレス数の削減
処理するリクエスト数が固定の場合、各インスタンスが複数のリクエストを処理できれば、必要なインスタンスの数が減ります。これにより、VPC で使用される IP アドレスの数が削減されます。
重要VPC に関連付けられている vSwitch に、少なくとも 2 つの利用可能な IP アドレスがあることを確認してください。そうでない場合、サービスが利用できなくなり、リクエストが失敗する可能性があります。
利用シーン
関数がダウンストリームサービスから応答を得るのに時間がかかる場合は、単一のインスタンスを使用して複数のリクエストを同時に処理することを推奨します。ほとんどの場合、応答を待っている間はリソースを消費しません。1 つのインスタンスで複数のリクエストを同時に処理することで、コストを節約し、アプリケーションの応答性とスループットを向上させることができます。
制限事項
項目 | 制限 |
サポートされるランタイム環境 |
|
インスタンスの同時実行数の有効値 | 1 から 200 |
X-Fc-Log-Result レスポンスヘッダーで提供される関数実行ログ | インスタンスの同時実行数が 1 より大きい値に設定されている場合はサポートされません |
操作手順
関数の作成時に、その関数のインスタンス同時実行数を指定できます。
作成済みの関数のインスタンス同時実行数を変更するには、関数の詳細ページに移動し、 [設定] タブをクリックします。次に、 [インスタンス設定] セクションで [変更] をクリックします。表示されたパネルで、インスタンスの同時実行数を変更します。
影響
このセクションでは、インスタンスが一度に 1 つのリクエストしか処理できないシナリオ (インスタンスの同時実行数 = 1) と、インスタンスが一度に複数のリクエストを処理できるシナリオ (インスタンスの同時実行数 > 1) の違いについて説明します。
課金
関数インスタンスの実行時間とコストは、インスタンスの同時実行数によって異なります。詳細については、「課金の概要」をご参照ください。
インスタンスの同時実行数 = 1
インスタンスは一度に 1 つのリクエストしか処理できません。課金時間は、最初のリクエストの処理が開始されたときに始まり、最後のリクエストが処理されたときに終了します。
インスタンスの同時実行数 > 1
インスタンスは一度に複数のリクエストを処理できます。インスタンスの実際の実行時間が、関数の実行時間を測定するために使用されます。課金時間は、最初のリクエストの処理が開始されたときに始まり、最後のリクエストが処理されたときに終了します。
同時実行数の制限
デフォルトでは、Function Compute は 1 つのリージョンで最大 100 のオンデマンドインスタンスをサポートします。1 つのリージョンで同時に処理できるリクエストの最大数は、次の式を使用して計算されます:100 × インスタンスの同時実行数。たとえば、インスタンスの同時実行数を 10 に設定した場合、1 つのリージョンで最大 1,000 の同時リクエストを処理できます。同時リクエスト数が Function Compute が処理できる最大リクエスト数を超えると、スロットリングエラー ResourceExhausted が報告されます。
リージョン内のインスタンスの最大数を増やすには、お問い合わせください。
ログ
インスタンスの同時実行数が 1 に設定されている場合、関数を呼び出す際に HTTP リクエストヘッダーで
X-Fc-Log-Type: Tailを指定すると、Function Compute はX-Fc-Log-Resultレスポンスヘッダーに関数ログを返します。インスタンスの同時実行数が 1 より大きい値に設定されている場合、同時リクエストの中から特定のリクエストのログを取得できないため、レスポンスヘッダーには関数ログが含まれません。Node.js ランタイムの場合、関数
console.info()はリクエスト ID を含むログを返すために使用されていました。インスタンスの同時実行数が 1 より大きい値に設定されている場合、console.info()はリクエスト ID を期待どおりに表示できません。すべてのリクエスト ID はreq 2として表示されます。次の例はサンプルログです。2019-11-06T14:23:37.587Z req1 [info] logger begin 2019-11-06T14:23:37.587Z req1 [info] ctxlogger begin 2019-11-06T14:23:37.587Z req2 [info] logger begin 2019-11-06T14:23:37.587Z req2 [info] ctxlogger begin 2019-11-06T14:23:40.587Z req1 [info] ctxlogger end 2019-11-06T14:23:40.587Z req2 [info] ctxlogger end 2019-11-06T14:23:37.587Z req2 [info] logger end 2019-11-06T14:23:37.587Z req2 [info] logger endこの場合、ログを出力するには
context.logger.info()を使用することを推奨します。このメソッドを使用すると、リクエスト ID が期待どおりに表示されます。次のサンプルコードに例を示します。exports.handler = (event, context, callback) => { console.info('logger begin'); context.logger.info('ctxlogger begin'); setTimeout(function() { context.logger.info('ctxlogger end'); console.info('logger end'); callback(null, 'hello world'); }, 3000); };
エラー処理
インスタンスが複数のリクエストを同時に処理する場合、失敗したリクエストによって引き起こされる予期せぬプロセスの終了は、他の同時リクエストに影響を与えます。したがって、他のリクエストへの影響を防ぐために、関数コード内でリクエストレベルの例外をキャッチするロジックを記述する必要があります。次の例は、Node.js のサンプルコードです。
exports.handler = (event, context, callback) => {
try {
JSON.parse(event);
} catch (ex) {
callback(ex);
}
callback(null, 'hello world');
}; 共有変数
インスタンスが複数のリクエストを同時に処理する場合、複数のリクエストが同時に同じ変数を変更しようとするとエラーが発生する可能性があります。スレッドセーフでない変数の変更を防ぐために、コード内で相互排他を使用する必要があります。次の例は、Java のサンプルコードです。
public class App implements StreamRequestHandler
{
private static int counter = 0;
@Override
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
synchronized (this) {
counter = counter + 1;
}
outputStream.write(new String("hello world").getBytes());
}
}