Cloud Run 関数の実行環境

Cloud Run 関数は、インフラストラクチャ、オペレーティング システム、およびランタイム環境を運用する、フルマネージド サーバーレス環境で動作します。各関数は、互いに切り離された独自の安全な実行コンテキストで動作し、自動的にスケーリングします。また、そのライフサイクルは他の関数とは独立しています。

ランタイム

Cloud Run 関数では、複数の言語のランタイムをサポートしています。各パッケージには、システム パッケージの標準セットと、その言語に必要なツールとライブラリが含まれています。コマンドラインから、または Terraform を介して関数をデプロイする場合は、ランタイム ID 値が必要になります。

セキュリティとメンテナンスの更新は、すべての Cloud Run 関数と Cloud Run 関数(第 1 世代)の実行環境で利用可能です。これらの更新は、環境と構成に応じて自動または手動で適用されます。実行環境の更新の詳細については、Cloud Run 関数の保護をご覧ください。

ランタイム イメージは、Artifact Registry が利用可能なすべてのリージョンでホストされます。URI の最初の部分を目的のリージョンに置き換えることで、ランタイム イメージのパスをカスタマイズできます。

REGION-docker.pkg.dev/serverless-runtimes/STACK/runtimes/RUNTIME_ID

次のように置き換えます。

  • REGION: 優先するリージョン(us-central1 など)
  • STACK: 優先オペレーティング システム スタック(google-22-full など)
  • RUNTIME_ID は、関数で使用されるランタイム ID(python310 など)に置き換えます。

たとえば、google-22-full スタックを使用して us-central1 でホストされている最新の Node.js 20 ベースイメージは、次の URL で参照されます: us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22

Node.js

ランタイム ランタイム ID スタック ランタイム ベースイメージ
Node.js 22
(プレビュー版のみ)
nodejs22
  • google-22(デフォルト)
  • google-22-full
  • google-22/nodejs22
  • google-22-full/nodejs22
  • Node.js 20 nodejs20
  • google-22(デフォルト)
  • google-22-full
  • google-22/nodejs20
  • google-22-full/nodejs20
  • Node.js 18 nodejs18
  • google-22(デフォルト)
  • google-22-full
  • google-22/nodejs18
  • google-22-full/nodejs18
  • Node.js 16 nodejs16 google-18-full google-18-full/nodjes16
    Node.js 14 nodejs14 google-18-full google-18-full/nodjes14
    Node.js 12 nodejs12 google-18-full google-18-full/nodjes14
    Node.js 10 nodejs10 google-18-full google-18-full/nodjes10
    Node.js 8 nodejs8 廃止 廃止
    Node.js 6 nodejs6 廃止 廃止

    Python

    ランタイム ランタイム ID スタック ランタイム ベースイメージ
    Python 3.12 python312
  • google-22(デフォルト)
  • google-22-full
  • google-22/python312
  • google-22-full/python312
  • Python 3.11 python311
  • google-22(デフォルト)
  • google-22-full
  • google-22/python311
  • google-22-full/python311
  • Python 3.10 python310
  • google-22(デフォルト)
  • google-22-full
  • google-22/python310
  • google-22-full/python311
  • Python 3.9 python39 google-18-full google-18-full/python39
    Python 3.8 python38 google-18-full google-18-full/python38
    Python 3.7 python37 google-18-full google-18-full/python37

    Go

    ランタイム ランタイム ID スタック ランタイム ベースイメージ
    Go 1.22 go122
  • google-22(デフォルト)
  • google-22-full
  • google-22/go122
  • google-22-full/go122
  • Go 1.21 go121
  • google-22(デフォルト)
  • google-22-full
  • google-22/go121
  • google-22-full/go121
  • Go 1.20 go120
  • google-22(デフォルト)
  • google-22-full
  • google-22/go120
  • google-22-full/go120
  • Go 1.19 go119
  • google-22(デフォルト)
  • google-22-full
  • google-22/go119
  • google-22-full/go119
  • Go 1.18 go118
  • google-22(デフォルト)
  • google-22-full
  • google-22/go118
  • google-22-full/go120
  • Go 1.16 go116 google-18-full google-18-full/go116
    Go 1.13 go113 google-18-full google-18-full/go113
    Go 1.11 go111 廃止 廃止

    Java

    ランタイム ランタイム ID スタック ランタイム ベースイメージ
    Java 21 java21
  • google-22(デフォルト)
  • google-22-full
  • google-22/java21
  • google-22-full/java21
  • Java 17 java17
  • google-22(デフォルト)
  • google-22-full
  • google-22/java17
  • google-22-full/java17
  • Java 11 java11 google-18 google-18/java11

    Ruby

    ランタイム ランタイム ID スタック ランタイム ベースイメージ
    Ruby 3.3 ruby33
  • google-22(デフォルト)
  • google-22-full
  • google-22/ruby33
  • google-22-full/ruby33
  • Ruby 3.2 ruby32
  • google-22(デフォルト)
  • google-22-full
  • google-22/ruby32
  • google-22-full/ruby32
  • Ruby 3.0 ruby30 google-18-full google-18-full/ruby30
    Ruby 2.7 ruby27 google-18-full google-18-full/ruby27
    Ruby 2.6 ruby26 google-18-full google-18-full/ruby26

    PHP

    ランタイム ランタイム ID スタック ランタイム ベースイメージ
    PHP 8.3 php83
  • google-22(デフォルト)
  • google-22-full
  • google-22/php83
  • google-22-full/php83
  • PHP 8.2 php82
  • google-22(デフォルト)
  • google-22-full
  • google-22/php82
  • google-22-full/php82
  • PHP 8.1 php81 google-18-full google-18-full/php81
    PHP 7.4 php74 google-18-full google-18-full/php74

    .NET Core

    ランタイム ランタイム ID スタック ランタイム ベースイメージ
    .NET Core 8 dotnet8
  • google-22(デフォルト)
  • google-22-full
  • google-22/dotnet8
  • google-22-full/dotnet8
  • .NET Core 6 dotnet6
  • google-22(デフォルト)
  • google-22-full
  • google-22/dotnet6
  • google-22-full/dotnet6
  • .NET Core 3 dotnet3 google-18-full google-18-full/dotnet3

    自動スケーリングの動作

    Cloud Run 関数はサーバーレス パラダイムを実装しています。このパラダイムでは、サーバーや仮想マシンなどの基礎となるインフラストラクチャを意識せずにコードを実行できます。デプロイ後、関数は自動的に管理され、スケーリングされます。

    Cloud Run 関数は、受信したリクエストを関数のインスタンスに割り当てて処理します。リクエストの量と既存の関数インスタンスの数に応じて、Cloud Run 関数は既存のインスタンスに要求を割り当てるか、新しいインスタンスを作成します。

    インバウンド リクエストの量が既存のインスタンス数を超えた場合、Cloud Run 関数は複数の新しいインスタンスを開始し、リクエストを処理します。この自動スケーリングにより、Cloud Run 関数は関数の異なるインスタンスを使用して、複数のリクエストを同時に処理できるようになります。

    無制限のスケーリングが好ましくない場合もあります。これに対応するため、Cloud Run 関数では、特定の関数について任意の時点で共存可能な最大インスタンス数を構成できます。

    ステートレス性

    関数の自動管理とスケーリングを有効にするには、関数がステートレスである必要があります。つまり、1 つの関数呼び出しが、前の呼び出しで設定されたメモリ内の状態に依存しないようにする必要があります。呼び出しは、グローバル変数、メモリ、ファイル システムなどの状態を共有しない別の関数インスタンスによって処理されます。

    関数呼び出し間で状態を共有する必要がある場合は、関数で MemorystoreDatastoreFirestoreCloud Storage などのサービスを使用してデータを保持する必要があります。Google Cloud が提供するデータベースとストレージ オプションの詳細については、Google Cloud データベースGoogle Cloud ストレージ プロダクトをご覧ください。

    同時実行

    Cloud Run 関数

    Cloud Run 関数では、1 つの関数インスタンスで複数の同時リクエストを処理できます。これは、すでにウォーム状態のインスタンスが複数のリクエストを同時に処理できるため、コールド スタートの発生を防ぎ、全体的なレイテンシを短縮するのに役立ちます。詳しくは、同時実行をご覧ください。

    Cloud Run 関数(第 1 世代)

    Cloud Run 関数(第 1 世代)では、関数の各インスタンスは一度に 1 つの同時リクエストを処理します。コードが 1 つのリクエストを処理している間、次のリクエストが同じインスタンスにルーティングされることはありません。元のリクエストは、割り当てられたリソース(メモリと CPU)のすべてを使用できます。

    Cloud Run 関数(第 1 世代)の同時リクエストはさまざまな関数インスタンスで処理されるため、変数やローカルメモリは共有されません。詳細については、ステートレス性関数インスタンスの寿命をご覧ください。

    コールド スタート

    新しい関数インスタンスは、次の 2 つのケースで開始されます。

    • 関数がデプロイされた時点

    • 負荷をスケールアップするため、または、場合によっては既存のインスタンスを置き換えるために、新しい関数インスタンスが自動的に作成された時点

    新しい関数インスタンスを開始すると、ランタイムとコードが読み込まれます。関数インスタンスのスタートアップ(コールド スタート)を含むリクエストは、既存の関数インスタンスに送られたリクエストより遅くなる可能性があります。ただし、関数にかかる負荷が安定している場合は、関数が頻繁にクラッシュして、関数環境の再起動が必要にならない限り、コールド スタートの回数は無視できます。

    関数コードがキャッチされていない例外をスローしたか、現在のプロセスをクラッシュさせた場合、関数インスタンスが再起動されることがあります。これにより、コールド スタートが増え、レイテンシが増加する可能性があります。例外をキャッチし、現在のプロセスの終了を回避することをおすすめします。Cloud Run 関数でエラーを処理して報告する方法については、エラーの報告をご覧ください。

    関数がレイテンシの影響を受けやすい場合は、コールド スタートを回避できるようインスタンスの最小数を設定することを検討してください。

    関数インスタンスの寿命

    一般に、関数インスタンスは、持続トラフィックの不足や関数のクラッシュによってインスタンス数がスケールダウンされない限り、回復力があり、後続の関数呼び出しで再利用されます。つまり、ある関数の実行が終了すると、別の関数呼び出しが同じ関数インスタンスによって処理されます。

    関数スコープとグローバル スコープ

    単一の関数呼び出しでは、エントリ ポイントとして宣言された関数の本体だけが実行されます。関数のソースコードのグローバル スコープは、コールド スタートでのみ実行されます。すでに初期化されているインスタンスでは実行されません。

    Node.js

    const functions = require('@google-cloud/functions-framework');
    
    // TODO(developer): Define your own computations
    const {lightComputation, heavyComputation} = require('./computations');
    
    // Global (instance-wide) scope
    // This computation runs once (at instance cold-start)
    const instanceVar = heavyComputation();
    
    /**
     * HTTP function that declares a variable.
     *
     * @param {Object} req request context.
     * @param {Object} res response context.
     */
    functions.http('scopeDemo', (req, res) => {
      // Per-function scope
      // This computation runs every time this function is called
      const functionVar = lightComputation();
    
      res.send(`Per instance: ${instanceVar}, per function: ${functionVar}`);
    });

    Python

    import time
    
    import functions_framework
    
    
    # Placeholder
    def heavy_computation():
        return time.time()
    
    
    # Placeholder
    def light_computation():
        return time.time()
    
    
    # Global (instance-wide) scope
    # This computation runs at instance cold-start
    instance_var = heavy_computation()
    
    
    @functions_framework.http
    def scope_demo(request):
        """
        HTTP Cloud Function that declares a variable.
        Args:
            request (flask.Request): The request object.
            <http://flask.pocoo.org/docs/1.0/api/#flask.Request>
        Returns:
            The response text, or any set of values that can be turned into a
            Response object using `make_response`
            <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>.
        """
    
        # Per-function scope
        # This computation runs every time this function is called
        function_var = light_computation()
        return f"Instance: {instance_var}; function: {function_var}"
    
    

    Go

    
    // h is in the global (instance-wide) scope.
    var h string
    
    // init runs during package initialization. So, this will only run during an
    // an instance's cold start.
    func init() {
    	h = heavyComputation()
    	functions.HTTP("ScopeDemo", ScopeDemo)
    }
    
    // ScopeDemo is an example of using globally and locally
    // scoped variables in a function.
    func ScopeDemo(w http.ResponseWriter, r *http.Request) {
    	l := lightComputation()
    	fmt.Fprintf(w, "Global: %q, Local: %q", h, l)
    }
    

    Java

    
    import com.google.cloud.functions.HttpFunction;
    import com.google.cloud.functions.HttpRequest;
    import com.google.cloud.functions.HttpResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Arrays;
    
    public class Scopes implements HttpFunction {
      // Global (instance-wide) scope
      // This computation runs at instance cold-start.
      // Warning: Class variables used in functions code must be thread-safe.
      private static final int INSTANCE_VAR = heavyComputation();
    
      @Override
      public void service(HttpRequest request, HttpResponse response)
          throws IOException {
        // Per-function scope
        // This computation runs every time this function is called
        int functionVar = lightComputation();
    
        var writer = new PrintWriter(response.getWriter());
        writer.printf("Instance: %s; function: %s", INSTANCE_VAR, functionVar);
      }
    
      private static int lightComputation() {
        int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        return Arrays.stream(numbers).sum();
      }
    
      private static int heavyComputation() {
        int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        return Arrays.stream(numbers).reduce((t, x) -> t * x).getAsInt();
      }
    }

    Ruby

    # Global (instance-wide) scope.
    # This block runs on cold start, before any function is invoked.
    #
    # Note: It is usually best to run global initialization in an on_startup block
    # instead at the top level of the Ruby file. This is because top-level code
    # could be executed to verify the function during deployment, whereas an
    # on_startup block is run only when an actual function instance is starting up.
    FunctionsFramework.on_startup do
      instance_data = perform_heavy_computation
    
      # To pass data into function invocations, the best practice is to set a
      # key-value pair using the Ruby Function Framework's built-in "set_global"
      # method. Functions can call the "global" method to retrieve the data by key.
      # (You can also use Ruby global variables or "toplevel" local variables, but
      # they can make it difficult to isolate global data for testing.)
      set_global :my_instance_data, instance_data
    end
    
    FunctionsFramework.http "tips_scopes" do |_request|
      # Per-function scope.
      # This method is called every time this function is called.
      invocation_data = perform_light_computation
    
      # Retrieve the data computed by the on_startup block.
      instance_data = global :my_instance_data
    
      "instance: #{instance_data}; function: #{invocation_data}"
    end

    パフォーマンスを最適化するためにグローバル変数を使用できますが、以前の関数呼び出しでグローバル スコープに設定された状態に依存しないでください。詳細については、ステートレス性をご覧ください。

    関数インスタンスごとに、関数コードの呼び出し前にグローバル スコープが 1 回だけ実行されていると想定できますが、グローバル スコープの総実行回数やタイミングは自動スケーリングのアクティビティによって異なる可能性があるため、これらに依存しないようにしてください。

    関数実行タイムライン

    関数は、その実行期間にのみ、割り当てられたリソース(メモリと CPU)にアクセスできます。実行期間外に実行されるコードは必ず実行されるとは限りません。これらのコードはいつでも停止できます。そのため、必ず、関数実行の終了を正確に通知して、それを超えたコードの実行を回避する必要があります。詳細については、HTTP 関数バックグラウンド関数CloudEvent 関数をご覧ください。

    関数の実行には、関数のタイムアウト時間も適用されます。詳細については、関数のタイムアウトをご覧ください。

    アプリケーションを初期化する場合は、実行タイムラインを考慮してください。バックグラウンド タスクは初期化時にグローバル スコープで作成しないでください。作成すると、リクエストがリクエストの処理時間外に実行されます。

    実行保証

    通常、関数は、送られてきたイベントごとに 1 回ずつ呼び出されます。ただし、Cloud Run 関数は、エラーシナリオに違いがあるため、すべてのケースで単一の呼び出しを保証するわけではありません。

    1 つのイベントで関数が呼び出される最大回数または最小回数は、関数の種類によって異なります。

    • HTTP 関数は、多くても 1 回しか呼び出されません。これは HTTP 呼び出しの同期性によるもので、関数呼び出し中に発生したエラーは再試行されずに返されることを意味します。HTTP 関数の呼び出し側は、エラーを処理し、必要に応じて再試行する必要があります。

    • イベント ドリブン関数は少なくとも 1 回呼び出されます。イベントの処理は基本的に非同期で行われます。つまり、呼び出し側がレスポンスを待つ必要はありません。まれなケースですが、イベントを確実に処理するため、イベント ドリブン関数が 2 回以上呼び出されることもあります。イベント ドリブン関数の呼び出しがエラーで失敗した場合、その関数に対する失敗時の再試行が有効になっていない限り、再び呼び出されることはありません。

    関数が再実行時に正しく動作することを保証するには、イベントが複数回発生した場合でも望ましい結果(および副作用)をもたらすように関数を実装することで、関数をべき等にする必要があります。HTTP 関数の場合は、呼び出し側が HTTP 関数エンドポイントに対する呼び出しを再試行した場合でも、関数が望ましい値を返すことも意味します。関数をべき等にする方法の詳細については、イベント ドリブン関数の再試行をご覧ください。

    メモリとファイル システム

    各関数には一定量のメモリが割り当てられます。デプロイ時にメモリ容量を構成できます。詳細については、メモリ上限をご覧ください。

    関数の実行環境には、関数でデプロイされたソースファイルとディレクトリを含むインメモリ ファイル システムが含まれています(ソースコードの構造化をご覧ください)。ソースファイルを含むディレクトリは読み取り専用ですが、ファイル システムの残りの部分は書き込み可能です(オペレーティング システムで使用されるファイルを除く)。ファイル システムの使用は、関数のメモリ使用量にカウントされます。

    関数は、各プログラミング言語の標準メソッドを使用して、ファイル システムを操作できます。

    ネットワーク

    関数は、ランタイムに提供される組み込みライブラリか、依存関係として含まれるサードパーティ ライブラリを使用して、各プログラミング言語の標準メソッドを使用して公共のインターネットにアクセスできます。

    ネットワークの最適化で説明されているように、関数呼び出し間でネットワーク接続を再利用してみてください。ただし、システムが 10 分以上未使用状態の接続を閉じた後、切断された接続を再利用しようとすると、「接続のリセット」エラーが発生することがあります。コードは、閉じられた接続を適切に処理するライブラリを使用するか、低レベルのネットワーキング構造を使用している場合は、閉じられた接続を明示的に処理する必要があります。

    関数の分離

    デプロイされた関数は他のすべての関数から分離されます。これには、同じソースファイルからデプロイされたものも含まれます。特に、メモリ、グローバル変数、ファイル システムなどの状態は共有されません。

    デプロイされた関数間でデータを共有するには、MemorystoreDatastoreFirestoreCloud Storage などのサービスを使用します。また、関数で適切なトリガーを使用して必要なデータを渡し、別の関数を呼び出すこともできます。たとえば、HTTP 関数のエンドポイントに HTTP リクエストを送信します。また、Pub/Sub トピックにメッセージをパブリッシュして Pub/Sub 関数をトリガーします。