Lingkungan eksekusi fungsi Cloud Run

Fungsi Cloud Run berjalan di lingkungan serverless yang terkelola sepenuhnya, tempat Google menangani infrastruktur, sistem operasi, dan lingkungan runtime. Setiap fungsi berjalan dalam konteks eksekusi aman yang terisolasi, diskalakan secara otomatis, dan memiliki siklus proses yang tidak bergantung pada fungsi lainnya.

Runtime

Fungsi Cloud Run mendukung runtime multi-bahasa. Masing-masing berisi kumpulan standar paket sistem, serta alat dan library yang diperlukan untuk bahasa tersebut Anda memerlukan nilai Runtime ID jika men-deploy fungsi dari command line atau melalui Terraform.

Update keamanan dan pemeliharaan tersedia untuk semua fungsi Cloud Run dan lingkungan eksekusi fungsi Cloud Run (generasi ke-1). Update ini diterapkan secara otomatis atau manual, bergantung pada lingkungan dan cara konfigurasinya. Untuk mengetahui informasi selengkapnya tentang update lingkungan eksekusi, lihat Mengamankan fungsi Cloud Run Anda.

Image runtime dihosting di setiap region tempat Artifact Registry tersedia. Anda dapat menyesuaikan jalur image runtime dengan mengganti bagian pertama URI dengan region pilihan Anda:

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

Ganti:

  • REGION dengan region pilihan, misalnya us-central1
  • STACK dengan stack sistem operasi pilihan, misalnya google-22-full
  • RUNTIME_ID dengan ID runtime yang digunakan oleh fungsi Anda, misalnya python310

Misalnya, image dasar Node.js 20 terbaru yang menggunakan stack google-22-full, yang dihosting di us-central1 akan direferensikan dengan URL ini: us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22

Node.js

Runtime Generation ID Runtime Stack Image dasar runtime
Node.js 22 Menjalankan fungsi nodejs22 google-22-full google-22-full/nodejs22
Node.js 20 Fungsi Run, generasi ke-1 nodejs20 google-22-full google-22-full/nodejs20
Node.js 18 Fungsi Run, generasi ke-1 nodejs18 google-22-full google-22-full/nodejs18
Node.js 16 Fungsi Run, generasi ke-1 nodejs16 google-18-full google-18-full/nodjes16
Node.js 14 Fungsi Run, generasi ke-1 nodejs14 google-18-full google-18-full/nodjes14
Node.js 12 Fungsi Run, generasi ke-1 nodejs12 google-18-full google-18-full/nodjes14
Node.js 10 Fungsi Run, generasi ke-1 nodejs10 google-18-full google-18-full/nodjes10
Node.js 8 Fungsi Run, generasi ke-1 nodejs8 Dinonaktifkan Dinonaktifkan
Node.js 6 Fungsi Run, generasi ke-1 nodejs6 Dinonaktifkan Dinonaktifkan

Python

Runtime Generation ID Runtime Stack Image dasar runtime
Python 3.12 Fungsi Run, generasi ke-1 python312 google-22-full google-22-full/python312
Python 3.11 Fungsi Run, generasi ke-1 python311 google-22-full google-22-full/python311
Python 3.10 Fungsi Run, generasi ke-1 python310 google-22-full google-22-full/python310
Python 3.9 Fungsi Run, generasi ke-1 python39 google-18-full google-18-full/python39
Python 3.8 Fungsi Run, generasi ke-1 python38 google-18-full google-18-full/python38
Python 3.7 Fungsi Run, generasi ke-1 python37 google-18-full google-18-full/python37

Go

Runtime Generation ID Runtime Stack Image dasar runtime
Go 1.23
(Khusus pratinjau)
Menjalankan fungsi go123 google-22-full google-22-full/go123
Go 1.22 Menjalankan fungsi go122 google-22-full google-22-full/go122
Go 1.21 Menjalankan fungsi go121 google-22-full google-22-full/go121
Go 1.20 Menjalankan fungsi go120 google-22-full google-22-full/go120
Go 1.19 Fungsi Run, generasi ke-1 go119 google-22-full google-22-full/go119
Go 1.18 Fungsi Run, generasi ke-1 go118 google-22-full google-22-full/go120
Go 1.16 Fungsi Run, generasi ke-1 go116 google-18-full google-18-full/go116
Go 1.13 Fungsi Run, generasi ke-1 go113 google-18-full google-18-full/go113
Go 1.11 Fungsi Run, generasi ke-1 go111 Dinonaktifkan Dinonaktifkan

Java

Runtime Generation ID Runtime Stack Image dasar runtime
Java 21 Menjalankan fungsi java21 google-22-full google-22-full/java21
Java 17 Fungsi Run, generasi ke-1 java17 google-22-full google-22-full/java17
Java 11 Fungsi Run, generasi ke-1 java11 google-18 google-18/java11

Ruby

Runtime Generation ID Runtime Stack Image dasar runtime
Ruby 3.3 Fungsi Run, generasi ke-1 ruby33 google-22-full google-22-full/ruby33
Ruby 3.2 Fungsi Run, generasi ke-1 ruby32 google-22-full google-22-full/ruby32
Ruby 3.0 Fungsi Run, generasi ke-1 ruby30 google-18-full google-18-full/ruby30
Ruby 2.7 Fungsi Run, generasi ke-1 ruby27 google-18-full google-18-full/ruby27
Ruby 2.6 Fungsi Run, generasi ke-1 ruby26 google-18-full google-18-full/ruby26

PHP

Runtime Generation ID Runtime Stack Image dasar runtime
PHP 8.3 Menjalankan fungsi php83 google-22-full google-22-full/php83
PHP 8.2 Fungsi Run, generasi ke-1 php82 google-22-full google-22-full/php82
PHP 8.1 Fungsi Run, generasi ke-1 php81 google-18-full google-18-full/php81
PHP 7.4 Fungsi Run, generasi ke-1 php74 google-18-full google-18-full/php74

.NET Core

Runtime Generation ID Runtime Stack Image dasar runtime
.NET Core 8 Menjalankan fungsi dotnet8 google-22-full google-22-full/dotnet8
.NET Core 6 Fungsi Run, generasi ke-1 dotnet6 google-22-full google-22-full/dotnet6
.NET Core 3 Fungsi Run, generasi ke-1 dotnet3 google-18-full google-18-full/dotnet3

Perilaku penskalaan otomatis

Fungsi Cloud Run menerapkan paradigma serverless, yang memungkinkan Anda menjalankan kode tanpa mengkhawatirkan infrastruktur yang mendasarinya, seperti server atau virtual machine. Setelah di-deploy, fungsi Anda akan dikelola dan diskalakan secara otomatis.

Fungsi Cloud Run menangani permintaan masuk dengan menetapkannya ke instance fungsi Anda. Bergantung pada volume permintaan dan jumlah instance fungsi yang ada, fungsi Cloud Run dapat menetapkan permintaan ke instance yang ada atau membuat instance baru.

Jika volume permintaan masuk melebihi jumlah instance yang ada, fungsi Cloud Run dapat memulai beberapa instance baru untuk menangani permintaan. Dengan perilaku penskalaan yang otomatis ini, fungsi Cloud Run dapat menangani banyak permintaan secara paralel, masing-masing menggunakan suatu instance yang berbeda pada fungsi Anda.

Dalam beberapa kasus, penskalaan tanpa batas mungkin tidak diinginkan. Untuk mengatasi hal ini, fungsi Cloud Run memungkinkan Anda mengonfigurasi jumlah maksimum instance yang dapat muncul berdampingan pada waktu tertentu untuk fungsi tertentu.

Stateless

Untuk mengaktifkan pengelolaan otomatis dan penskalaan fungsi, fungsi harus bersifat stateless—satu pemanggilan fungsi tidak boleh bergantung pada status dalam memori yang ditetapkan oleh pemanggilan sebelumnya. Pemanggilan dapat ditangani oleh instance fungsi yang berbeda, yang tidak membagikan variabel global, memori, sistem file, atau status lainnya.

Jika Anda perlu membagikan status di seluruh pemanggilan fungsi, fungsi Anda harus menggunakan layanan sepertiMemorystore ,Datastore ,Firestore, atau Cloud Storage untuk mempertahankan data. Lihat database Google Cloud dan produk penyimpanan Google Cloud untuk mengetahui informasi selengkapnya tentang opsi database dan penyimpanan yang disediakan oleh Google Cloud.

Serentak

Fungsi Cloud Run

Fungsi Cloud Run mendukung penanganan beberapa permintaan serentak pada satu instance fungsi. Hal ini dapat membantu mencegah cold start karena instance yang sudah dihangatkan dapat memproses beberapa permintaan secara bersamaan, sehingga mengurangi keseluruhan latensi. Untuk mengetahui detailnya, lihat Konkurensi.

Fungsi Cloud Run (generasi ke-1)

Di fungsi Cloud Run (generasi ke-1), setiap instance fungsi hanya menangani satu permintaan serentak dalam satu waktu. Artinya, saat kode Anda memproses satu permintaan, tidak ada kemungkinan permintaan kedua dirutekan ke instance yang sama. Dengan demikian, permintaan asli dapat menggunakan seluruh jumlah resource (memori dan CPU) yang Anda alokasikan.

Karena permintaan serentak di fungsi Cloud Run (generasi ke-1) diproses oleh instance fungsi yang berbeda, permintaan tersebut tidak membagikan variabel atau memori lokal. Lihat Statelessness dan Masa aktif instance fungsi untuk mengetahui informasi selengkapnya.

Cold start

Instance fungsi baru dimulai dalam dua kasus:

  • Saat Anda men-deploy fungsi.

  • Saat instance fungsi baru dibuat secara otomatis untuk meningkatkan skalanya sesuai beban, atau terkadang untuk mengganti instance yang ada.

Memulai instance fungsi baru melibatkan pemuatan runtime dan kode Anda. Permintaan yang menyertakan startup instance fungsi, yang disebut cold start, dapat lebih lambat daripada permintaan yang dirutekan ke instance fungsi yang ada. Namun, jika fungsi Anda menerima beban stabil, jumlah cold start biasanya dapat diabaikan, kecuali jika fungsi Anda sering mengalami error dan mengharuskan Anda memulai ulang lingkungan fungsi.

Jika kode fungsi Anda menampilkan pengecualian yang tidak tertangkap atau membuat error proses saat ini, instance fungsi mungkin akan dimulai ulang. Hal ini dapat menyebabkan lebih banyak cold start, yang menghasilkan latensi yang lebih tinggi. Oleh karena itu, sebaiknya tangkap pengecualian dan hindari menghentikan proses saat ini. Baca bagian Melaporkan error untuk membahas cara menangani dan melaporkan error di fungsi Cloud Run.

Jika fungsi Anda sensitif terhadap latensi, pertimbangkan untuk menetapkan jumlah minimum instance untuk menghindari cold start.

Masa aktif instance fungsi

Instance fungsi biasanya bersifat tangguh dan digunakan kembali oleh pemanggilan fungsi berikutnya, kecuali jika jumlah instance diturunkan skalanya karena tidak adanya traffic yang sedang berlangsung atau fungsi Anda error. Ini berarti bahwa saat satu eksekusi fungsi berakhir, pemanggilan fungsi lainnya dapat ditangani oleh instance fungsi yang sama.

Cakupan fungsi versus cakupan global

Pemanggilan fungsi tunggal menghasilkan eksekusi khusus isi fungsi yang dideklarasikan sebagai titik masuk. Cakupan global kode sumber fungsi Anda hanya dijalankan pada cold start, dan bukan pada instance yang telah diinisialisasi.

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

Anda dapat menggunakan variabel global sebagai pengoptimalan performa, tetapi Anda tidak boleh mengandalkan status yang ditetapkan dalam cakupan global oleh pemanggilan fungsi sebelumnya - lihat Statelessness untuk informasi selengkapnya.

Anda dapat berasumsi bahwa untuk setiap instance fungsi, cakupan global telah dieksekusi tepat satu kali sebelum kode fungsi Anda dipanggil. Namun, Anda tidak boleh bergantung pada jumlah total atau waktu eksekusi cakupan global, karena eksekusi dapat bervariasi bergantung pada aktivitas penskalaan otomatis.

Linimasa eksekusi fungsi

Fungsi memiliki akses ke resource yang dialokasikan (memori dan CPU) hanya selama durasi eksekusi fungsi. Kode yang dijalankan di luar periode eksekusi tidak dijamin untuk dijalankan, dan dapat dihentikan kapan saja. Oleh karena itu, Anda harus selalu memberi sinyal akhir dari eksekusi fungsi dengan benar dan menghindari menjalankan kode apa pun di luarnya. Lihat Fungsi HTTP, Fungsi Latar Belakang, dan Fungsi CloudEvent untuk mendapatkan panduan.

Eksekusi fungsi juga tunduk pada durasi waktu tunggu fungsi. Lihat Waktu tunggu fungsi untuk informasi selengkapnya.

Memperhitungkan timeline eksekusi ketika menginisialisasi aplikasi Anda. Tugas latar belakang tidak boleh dibuat dalam cakupan global selama inisialisasi, karena tugas tersebut akan dijalankan di luar durasi permintaan.

Jaminan eksekusi

Fungsi Anda biasanya dipanggil satu kali untuk setiap peristiwa yang masuk. Namun, fungsi Cloud Run tidak menjamin akan ada satu pemanggilan di semua kasus karena perbedaan skenario error.

Frekuensi maksimum atau minimum fungsi dapat dipanggil untuk satu peristiwa bergantung pada jenis fungsi Anda:

  • Fungsi HTTP dipanggil maksimal satu kali. Hal ini dikarenakan sifat panggilan HTTP yang sinkron, yaitu bahwa setiap error yang terjadi selama pemanggilan fungsi akan ditampilkan tanpa mencoba ulang. Pemanggil fungsi HTTP diharapkan dapat menangani error dan mencoba lagi jika diperlukan.

  • Fungsi berbasis peristiwa dipanggil setidaknya satu kali. Hal ini karena sifat peristiwa asinkron, yaitu tidak ada pemanggil yang menunggu respons. Dalam situasi yang jarang terjadi, sistem mungkin memanggil fungsi yang dipicu peristiwa lebih dari sekali untuk memastikan pengiriman peristiwa. Jika pemanggilan fungsi berbasis peristiwa gagal dengan error, fungsi tersebut tidak akan dipanggil lagi kecuali jika percobaan ulang ketika gagal diaktifkan untuk fungsi tersebut.

Untuk memastikan bahwa fungsi berperilaku dengan benar pada upaya eksekusi yang dicoba ulang, Anda harus membuatnya idempoten dengan menerapkannya sehingga hasil (dan efek samping) yang diinginkan tetap tercapai meskipun sebuah peristiwa dikirimkan beberapa kali. Dalam kasus fungsi HTTP, ini juga berarti menampilkan nilai yang diinginkan meskipun pemanggil mencoba kembali panggilan ke endpoint fungsi HTTP. Lihat Mencoba Ulang Fungsi Berbasis Peristiwa untuk mengetahui informasi selengkapnya tentang cara membuat fungsi menjadi idempoten.

Memori dan sistem file

Setiap fungsi memiliki sejumlah memori yang dialokasikan untuk penggunaannya. Anda dapat mengonfigurasi jumlah memori saat deployment - lihat Batas memori untuk mengetahui informasi selengkapnya.

Lingkungan eksekusi fungsi mencakup sistem file dalam memori yang berisi file sumber dan direktori yang di-deploy dengan fungsi Anda (lihat Membuat struktur kode sumber). Direktori yang berisi file sumber Anda bersifat hanya baca, tetapi bagian lain dari sistem file dapat ditulisi (kecuali untuk file yang digunakan oleh sistem operasi). Penggunaan sistem file diperhitungkan dalam penggunaan memori fungsi.

Fungsi Anda dapat berinteraksi dengan sistem file menggunakan metode standar di setiap bahasa pemrograman.

Jaringan

Fungsi Anda dapat mengakses internet publik menggunakan metode standar di setiap bahasa pemrograman, baik melalui library bawaan yang ditawarkan oleh runtime atau library pihak ketiga yang Anda sertakan sebagai dependensi.

Coba gunakan kembali koneksi jaringan untuk pemanggilan fungsi, seperti yang dijelaskan dalam Mengoptimalkan Jaringan. Namun, perlu diperhatikan bahwa koneksi yang tidak digunakan selama 10 menit mungkin akan ditutup oleh sistem, dan upaya lebih lanjut untuk menggunakan koneksi tertutup akan mengakibatkan error "reset koneksi". Kode Anda harus menggunakan library yang menangani koneksi tertutup dengan baik, atau menanganinya secara eksplisit jika menggunakan konstruksi jaringan tingkat rendah.

Isolasi fungsi

Setiap fungsi yang di-deploy diisolasi dari semua fungsi lain—bahkan fungsi yang di-deploy dari file sumber yang sama. Secara khusus, mereka tidak membagikan memori, variabel global, sistem file, atau status lainnya.

Untuk berbagi data di seluruh fungsi yang di-deploy, Anda dapat menggunakan layanan seperti Memorystore, Datastore, Firestore, atau Cloud Storage. Atau, Anda dapat memanggil satu fungsi dari fungsi lainnya menggunakan pemicu yang sesuai dan meneruskan data yang diperlukan. Misalnya, buat permintaan HTTP ke endpoint fungsi HTTP atau publikasikan pesan ke topik Pub/Sub untuk memicu fungsi Pub/Sub.