Cloud Functions 実行環境

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

ランタイム

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

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

Node.js

ランタイム 生成 環境 ランタイム ID ランタイム イメージ
Node.js 22(プレビュー版のみ) 第 2 世代 Ubuntu 22.04 nodejs22 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22
Node.js 20 第 1 世代、第 2 世代 Ubuntu 22.04 nodejs20 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs20
Node.js 18 第 1 世代、第 2 世代 Ubuntu 22.04 nodejs18 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs18
Node.js 16 第 1 世代、第 2 世代 Ubuntu 18.04 nodejs16 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs16
Node.js 14 第 1 世代、第 2 世代 Ubuntu 18.04 nodejs14 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs14
Node.js 12 第 1 世代、第 2 世代 Ubuntu 18.04 nodejs12 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs12
Node.js 10 第 1 世代、第 2 世代 Ubuntu 18.04 nodejs10 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs10
Node.js 8 第 1 世代、第 2 世代 Ubuntu 18.04 nodejs8 廃止
Node.js 6 第 1 世代、第 2 世代 Ubuntu 18.04 nodejs6 廃止

Python

ランタイム 生成 環境 ランタイム ID ランタイム イメージ
Python 3.12 第 1 世代、第 2 世代 Ubuntu 22.04 python312 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python312
Python 3.11 第 1 世代、第 2 世代 Ubuntu 22.04 python311 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python311
Python 3.10 第 1 世代、第 2 世代 Ubuntu 22.04 python310 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python310
Python 3.9 第 1 世代、第 2 世代 Ubuntu 18.04 python39 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python39
Python 3.8 第 1 世代、第 2 世代 Ubuntu 18.04 python38 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python38
Python 3.7 第 1 世代 Ubuntu 18.04 python37 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python37

Go

ランタイム 生成 環境 ランタイム ID ランタイム イメージ
Go 1.22 第 2 世代 Ubuntu 22.04 go122 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go122
Go 1.21 第 1 世代、第 2 世代 Ubuntu 22.04 go121 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go121
Go 1.20 第 1 世代、第 2 世代 Ubuntu 22.04 go120 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go120
Go 1.19 第 1 世代、第 2 世代 Ubuntu 22.04 go119 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go119
Go 1.18 第 1 世代、第 2 世代 Ubuntu 22.04 go118 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go118
Go 1.16 第 1 世代、第 2 世代 Ubuntu 18.04 go116 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go116
Go 1.13 第 1 世代、第 2 世代 Ubuntu 18.04 go113 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go113
Go 1.11 第 1 世代、第 2 世代 Ubuntu 18.04 go111 廃止

Java

ランタイム 生成 環境 ランタイム ID ランタイム イメージ
Java 21 第 2 世代 Ubuntu 22.04 java21 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java21
Java 17 第 1 世代、第 2 世代 Ubuntu 22.04 java17 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java17
Java 11 第 1 世代、第 2 世代 Ubuntu 18.04 java11 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/java11

Ruby

ランタイム 生成 環境 ランタイム ID ランタイム イメージ
Ruby 3.3 第 1 世代、第 2 世代 Ubuntu 22.04 ruby33 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.2 第 1 世代、第 2 世代 Ubuntu 22.04 ruby32 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.0 第 1 世代、第 2 世代 Ubuntu 18.04 ruby30 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby30
Ruby 2.7 第 1 世代、第 2 世代 Ubuntu 18.04 ruby27 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby27
Ruby 2.6 第 1 世代、第 2 世代 Ubuntu 18.04 ruby26 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby26

PHP

ランタイム 環境 生成 ランタイム ID ランタイム イメージ
PHP 8.3 第 2 世代 Ubuntu 22.04 php83 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php83
PHP 8.2 第 1 世代、第 2 世代 Ubuntu 22.04 php82 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php82
PHP 8.1 第 1 世代、第 2 世代 Ubuntu 18.04 php81 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php81
PHP 7.4 第 1 世代、第 2 世代 Ubuntu 18.04 php74 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php74

.NET Core

ランタイム 生成 環境 ランタイム ID ランタイム イメージ
.NET Core 8 第 2 世代 Ubuntu 22.04 dotnet8 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet8
.NET Core 6 第 1 世代、第 2 世代 Ubuntu 22.04 dotnet6 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet6
.NET Core 3 第 1 世代、第 2 世代 Ubuntu 18.04 dotnet3 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/dotnet3

自動スケーリングの動作

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

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

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

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

ステートレス性

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

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

同時実行

Cloud Run functions(第 2 世代)

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

Cloud Run functions(第 1 世代)

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

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

コールド スタート

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

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

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

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

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

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

関数インスタンスの寿命

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

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

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

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 functions は、エラーシナリオに違いがあるため、すべてのケースで単一の呼び出しを保証するわけではありません。

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

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

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

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

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

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

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

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

ネットワーク

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

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

関数の分離

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

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