Cloud Functions 執行環境

Cloud Run 函式會在全代管無伺服器環境中執行,Google 會處理基礎架構、作業系統和執行階段環境。每個函式都會在獨立的安全執行環境中執行、自動調整規模,且生命週期不受其他函式影響。

執行階段

Cloud Run functions 支援多種語言的執行階段。每個映像檔都包含一組標準的系統套件,以及該語言所需的工具和程式庫。如果您要透過指令列Terraform 部署函式,則需要「執行階段 ID」值。

所有第 1 代和第 2 代執行環境都會收到安全防護和維護更新。這些更新會自動或手動套用,具體取決於環境和設定方式。如要進一步瞭解執行環境更新,請參閱「保護 Cloud Run 函式安全」。

Node.js

執行階段 產生 環境 執行階段 ID 執行階段映像檔
Node.js 24
(僅限預先發布版)
第 2 代 Ubuntu 24.04 nodejs24 us-central1-docker.pkg.dev/serverless-runtimes/google-24-full/runtimes/nodejs24
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.13 第 2 代 Ubuntu 22.04 python313 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python313
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.25 第 2 代 Ubuntu 22.04 go125 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go125
Go 1.24 第 2 代 Ubuntu 22.04 go124 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go124
Go 1.23 第 2 代 Ubuntu 22.04 go123 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go123
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.4 第 2 代 Ubuntu 22.04 ruby34 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby34
Ruby 3.3 第 1 代、第 2 代 Ubuntu 22.04 ruby33 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby33
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.4 第 2 代 Ubuntu 22.04 php84 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php84
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 函式可能會將要求指派給現有執行個體,或建立新的執行個體。

如果傳入要求量超過現有執行個體數量,Cloud Run functions 可能會啟動多個新執行個體來處理要求。這種自動調整資源配置的行為,可讓 Cloud Run functions 平行處理多個要求,每個要求使用不同的函式執行個體。

在某些情況下,您可能不希望無限制縮放。為解決這個問題,Cloud Run 函式可讓您設定特定函式在任何時間點可共存的執行個體數量上限

無狀態

如要啟用函式的自動管理和調度功能,函式必須是無狀態函式,也就是函式叫用作業不得依賴先前叫用作業設定的記憶體內狀態。呼叫作業可能會由不同的函式例項處理,這些例項不會共用全域變數、記憶體、檔案系統或其他狀態。

如要在函式呼叫之間共用狀態,函式應使用 MemorystoreDatastoreFirestoreCloud Storage 等服務來保存資料。如要進一步瞭解 Google Cloud提供的資料庫和儲存空間選項,請參閱Google Cloud 資料庫Google Cloud 儲存空間產品

並行

Cloud Run functions (第 2 代)

Cloud Run functions (第 2 代) 支援在單一函式執行個體上處理多個並行要求。這有助於避免冷啟動,因為暖機完成的執行個體可以同時處理多個要求,進而縮短整體延遲時間。詳情請參閱「並行」。

Cloud Run functions (第 1 代)

在 Cloud Run 函式 (第 1 代) 中,每個函式執行個體一次只能處理一個並行要求。也就是說,程式碼處理一項要求時,第二項要求不可能傳送至相同執行個體。因此,原始要求可使用您分配的全部資源 (記憶體和 CPU)。

由於 Cloud Run functions (第 1 代) 中的並行要求是由不同的函式執行個體處理,因此不會共用變數或本機記憶體。詳情請參閱「無狀態」和「函式執行個體生命週期」。

冷啟動

新函式執行個體會在下列兩種情況啟動:

  • 當您部署函式時。

  • 系統會自動建立新的函式執行個體,以因應負載增加的情況,或偶爾取代現有執行個體。

啟動新的函式例項時,需要載入執行階段和程式碼。包含函式執行個體啟動的請求 (稱為冷啟動) 可能會比傳送至現有函式執行個體的請求慢。不過,如果函式接收的負載穩定,冷啟動次數通常可忽略不計,除非函式經常當機,需要重新啟動函式環境。

如果函式程式碼擲回未擷取的例外狀況,或導致目前程序當機,函式執行個體可能會重新啟動。這可能會導致更多冷啟動,進而增加延遲時間,因此建議您擷取例外狀況,並避免終止目前的程序。

如果函式對延遲時間很敏感,請考慮設定最低執行個體數量,避免冷啟動。

函式執行個體生命週期

函式執行個體通常具有彈性,且會由後續函式呼叫重複使用,除非執行個體數量因持續流量不足而縮減,或函式當機。也就是說,當一個函式執行完畢後,同一個函式例項可以處理另一個函式叫用。

函式範圍與全域範圍

單一函式叫用只會執行宣告為進入點的函式主體。函式原始碼的全域範圍只會在冷啟動時執行,不會在已初始化的執行個體上執行。

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

您可以使用全域變數來提升效能,但不得依賴先前函式調用在全域範圍中設定的狀態,詳情請參閱「無狀態」。

您可以假設在叫用函式程式碼之前,每個函式例項的全球範圍都已執行一次。不過,您不得依賴全域範圍執行的總次數或時間,因為這些可能會因自動調度資源活動而異。

函式執行時間軸

函式只能在執行期間存取所分配的資源 (記憶體和 CPU)。如果程式碼在執行期間外執行,系統不保證會執行,而且隨時可以停止。因此,您應一律正確發出函式執行結束的信號,並避免在信號之後執行任何程式碼。如需相關指引,請參閱「HTTP 函式」、「背景函式」和「CloudEvent 函式」。

函式執行作業也會受到函式逾時時間長度的限制。詳情請參閱「函式逾時」。

初始化應用程式時,請將執行時間表納入考量。初始化期間不應在全域範圍內建立背景工作,因為這些工作會在要求持續時間外執行。

執行保證

通常會針對每個連入事件叫用一次函式。不過,由於錯誤情境不同,Cloud Run functions 無法保證在所有情況下都會單次叫用。

單一事件可叫用函式的次數上限或下限,取決於函式類型:

  • HTTP 函式「最多」會叫用一次。這是因為 HTTP 呼叫的同步性質,表示函式叫用期間發生的任何錯誤都會傳回,不會重試。HTTP 函式的呼叫端應處理錯誤,並視需要重試。

  • 以事件為準的函式至少會叫用一次。這是因為事件的非同步性質,沒有呼叫端會等待回應。在極少數情況下,系統可能會多次叫用事件驅動函式,確保事件能順利傳送。如果事件驅動函式叫用失敗並發生錯誤,除非為該函式啟用「失敗時重試」,否則系統不會再次叫用函式。

為確保函式在重試執行時能正常運作,您應實作等冪函式,即使事件多次傳送,也能產生所需結果 (和附帶影響)。如果是 HTTP 函式,這也表示即使呼叫端重試呼叫 HTTP 函式端點,仍會傳回所需值。如要進一步瞭解如何讓函式具備等冪性,請參閱「重試事件驅動型函式」。

記憶體和檔案系統

每個函式都有一定量的記憶體可供使用。您可以在部署時設定記憶體容量,詳情請參閱「設定記憶體」。

函式執行環境包含內建的檔案系統,其中含有與函式一併部署的來源檔案和目錄 (請參閱「結構化原始碼」)。含有來源檔案的目錄為唯讀,但其餘檔案系統皆可寫入 (作業系統使用的檔案除外)。使用檔案系統會計入函式的記憶體用量。

您的函式可以使用各程式設計語言的標準方法與檔案系統互動。

網路

無論是透過執行階段提供的內建程式庫,還是您以依附元件形式納入的第三方程式庫,函式都能使用各程式設計語言的標準方法存取公用網際網路。

嘗試在函式呼叫之間重複使用網路連線。 不過請注意,如果連線閒置 10 分鐘,系統可能會關閉連線,如果後續嘗試使用已關閉的連線,就會導致「連線重設」錯誤。您的程式碼應使用程式庫來很好地處理關閉的連線,或在使用低層級網路結構的情況下,明確處理這些連線。

函式隔離

每個部署的函式都會與其他所有函式隔離開,就算是從相同來源檔案部署的函式也是如此。特別是記憶體、全域變數、檔案系統或其他狀態。

如要在已部署的函式之間共用資料,可以使用 MemorystoreDatastoreFirestoreCloud Storage 等服務。或者,您也可以使用適當的觸發條件從另一個函式叫用一個函式,並傳遞必要資料。舉例來說,您可以對 HTTP 函式的端點提出 HTTP 要求,或是將訊息發布至 Pub/Sub 主題,藉此觸發 Pub/Sub 函式。