Halaman ini menjelaskan konsep lanjutan sesi di Spanner, termasuk praktik terbaik untuk sesi saat membuat library klien, menggunakan REST atau RPC API, atau menggunakan library klien Google.
Ringkasan Sesi
Sesi mewakili saluran komunikasi dengan layanan database Spanner. Sesi digunakan untuk melakukan transaksi yang membaca, menulis, atau mengubah data di database Spanner. Setiap sesi berlaku untuk satu {i>database<i}.
Sesi dapat menjalankan satu atau beberapa transaksi sekaligus. Saat melakukan beberapa transaksi, sesi ini disebut sesi multipleks.
Operasi baca, tulis, dan kueri mandiri menggunakan satu transaksi secara internal.
Manfaat performa dari kumpulan sesi
Membuat sesi mahal. Untuk menghindari biaya performa setiap kali operasi database dilakukan, klien harus menyimpan kumpulan sesi, yang merupakan kumpulan sesi yang tersedia dan siap digunakan. Kumpulan ini harus menyimpan sesi yang ada dan menampilkan jenis sesi yang sesuai saat diminta, serta menangani pembersihan sesi yang tidak digunakan. Untuk contoh cara menerapkan kumpulan sesi, lihat kode sumber untuk salah satu library klien Spanner, seperti library klien Go atau library klien Java.
Sesi dimaksudkan untuk berumur panjang, jadi setelah sesi digunakan untuk operasi database, klien harus mengembalikan sesi ke kumpulan untuk digunakan kembali.
Ringkasan saluran gRPC
Saluran gRPC digunakan oleh klien Spanner untuk komunikasi. Satu saluran gRPC kurang lebih setara dengan koneksi TCP. Satu saluran gRPC dapat menangani hingga 100 permintaan serentak. Artinya, aplikasi akan memerlukan setidaknya saluran gRPC sebanyak jumlah permintaan serentak yang akan dijalankan aplikasi, dibagi 100.
Klien Spanner membuat kumpulan saluran gRPC saat Anda membuatnya.
Praktik terbaik saat menggunakan library klien Google
Berikut adalah praktik terbaik saat menggunakan library klien Google untuk Spanner.
Mengonfigurasi jumlah sesi dan saluran gRPC dalam kumpulan
Library klien memiliki jumlah sesi default dalam kumpulan sesi dan jumlah saluran gRPC default di kumpulan saluran. Kedua setelan default sudah memadai untuk sebagian besar kasus. Berikut adalah sesi minimum dan maksimum default serta jumlah default saluran gRPC untuk setiap bahasa pemrograman.
C++
MinSessions: 100
MaxSessions: 400
NumChannels: 4
C#
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Go
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Java
MinSessions: 100
MaxSessions: 400
NumChannels: 4
Node.js
Klien Node.js tidak mendukung lebih dari satu saluran gRPC. Oleh karena itu, sebaiknya buat beberapa klien, bukan meningkatkan ukuran kumpulan sesi di atas 100 sesi untuk satu klien.
MinSessions: 25
MaxSessions: 100
PHP
Klien PHP tidak mendukung jumlah saluran gRPC yang dapat dikonfigurasi.
MinSessions: 1
MaxSessions: 500
Python
Python mendukung empat jenis kumpulan sesi berbeda yang dapat Anda gunakan untuk mengelola sesi.
Ruby
Klien Ruby tidak mendukung beberapa saluran gRPC. Oleh karena itu, sebaiknya buat beberapa klien, bukan meningkatkan ukuran kumpulan sesi di atas 100 sesi untuk satu klien.
MinSessions: 10
MaxSessions: 100
Jumlah sesi yang digunakan aplikasi Anda sama dengan jumlah transaksi serentak yang dijalankan aplikasi Anda. Sebaiknya ubah setelan kumpulan sesi default hanya jika Anda mengharapkan satu instance aplikasi untuk menjalankan lebih banyak transaksi serentak daripada yang dapat ditangani oleh kumpulan sesi default.
Untuk aplikasi konkurensi tinggi, berikut ini direkomendasikan:
- Tetapkan
MinSessions
ke jumlah transaksi serentak yang diharapkan yang akan dijalankan oleh satu klien. - Tetapkan
MaxSessions
ke jumlah maksimum transaksi serentak yang dapat dijalankan oleh satu klien. - Tetapkan
MinSessions=MaxSessions
jika konkurensi yang diharapkan tidak banyak berubah selama masa aktif aplikasi. Hal ini mencegah kumpulan sesi dari peningkatan atau penurunan skala. Menskalakan kumpulan sesi, meningkatkan atau menurunkannya, juga menghabiskan beberapa resource. - Tetapkan
NumChannels
keMaxSessions / 100
. Satu saluran gRPC dapat menangani hingga 100 permintaan secara serentak. Tingkatkan nilai ini jika Anda mengamati latensi high tail (latensi p95/p99), karena ini mungkin merupakan indikasi kemacetan saluran gRPC.
Peningkatan jumlah sesi aktif akan menggunakan resource tambahan pada layanan database Spanner dan library klien. Meningkatkan jumlah sesi di luar kebutuhan aplikasi yang sebenarnya dapat menurunkan performa sistem Anda.
Meningkatkan kumpulan sesi versus meningkatkan jumlah klien
Ukuran kumpulan sesi untuk aplikasi menentukan jumlah transaksi serentak yang dapat dieksekusi oleh satu instance aplikasi. Meningkatkan ukuran kumpulan sesi di luar konkurensi maksimum yang dapat ditangani satu instance aplikasi tidak direkomendasikan. Jika aplikasi menerima burst permintaan yang melampaui jumlah sesi dalam kumpulan, permintaan tersebut akan dimasukkan ke dalam antrean saat menunggu sesi tersedia.
Resource yang digunakan oleh library klien adalah sebagai berikut:
- Setiap saluran gRPC menggunakan satu koneksi TCP.
- Setiap pemanggilan gRPC memerlukan thread. Jumlah maksimum thread yang digunakan oleh library klien sama dengan jumlah maksimum kueri serentak yang dijalankan aplikasi. Thread ini ditempatkan di atas thread yang digunakan aplikasi untuk logika bisnisnya sendiri.
Sebaiknya jangan meningkatkan ukuran kumpulan sesi di luar jumlah maksimum thread yang dapat ditangani oleh satu instance aplikasi. Sebagai gantinya, tingkatkan jumlah instance aplikasi.
Mengelola fraksi sesi tulis
Untuk beberapa library klien, Spanner mencadangkan sebagian sesi untuk transaksi baca-tulis, yang disebut fraksi sesi tulis. Jika aplikasi Anda
menggunakan semua sesi baca, Spanner akan menggunakan sesi baca-tulis, bahkan untuk transaksi hanya baca. Sesi baca-tulis memerlukan spanner.databases.beginOrRollbackReadWriteTransaction
. Jika pengguna memiliki peran IAM
spanner.databaseReader
, panggilan akan gagal
dan Spanner akan menampilkan pesan error ini:
generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction
Untuk library klien yang mempertahankan fraksi sesi tulis, Anda dapat menetapkan fraksi sesi tulis.
C++
Semua sesi C++ sama. Tidak ada sesi hanya baca atau baca-tulis.
C#
Fraksi sesi tulis default untuk C# adalah 0,2. Anda dapat mengubah
fraksi menggunakan kolom WriteSessionsFraction
SessionPoolOptions
.
Go
Semua sesi Go sama. Tidak ada sesi hanya baca atau baca-tulis.
Java
Semua sesi Java sama. Tidak ada sesi hanya baca atau baca-tulis.
Node.js
Semua sesi Node.js sama. Tidak ada sesi hanya baca atau baca-tulis.
PHP
Semua sesi PHP sama. Tidak ada sesi hanya baca atau baca-tulis.
Python
Python mendukung empat jenis kumpulan sesi berbeda yang dapat Anda gunakan untuk mengelola sesi baca dan baca-tulis.
Ruby
Fraksi sesi tulis default untuk Ruby adalah 0,3. Anda dapat mengubah pecahan menggunakan metode inisialisasi client.
Praktik terbaik saat membuat library klien atau menggunakan REST/RPC
Berikut adalah praktik terbaik untuk menerapkan sesi di library klien untuk Spanner, atau untuk menggunakan sesi dengan REST atau RPC API.
Praktik terbaik ini hanya berlaku jika Anda mengembangkan library klien, atau jika menggunakan API REST/RPC. Jika Anda menggunakan salah satu library klien Google untuk Spanner, lihat Praktik terbaik saat menggunakan library klien Google.
Membuat dan mengukur kumpulan sesi
Untuk menentukan ukuran kumpulan sesi yang optimal untuk proses klien, tetapkan batas bawah ke jumlah transaksi serentak yang diharapkan, dan tetapkan batas atas ke angka pengujian awal, misalnya 100. Jika batas atas tidak memadai, tingkatkan batas atas. Peningkatan jumlah sesi aktif akan menggunakan resource tambahan di layanan database Spanner, sehingga kegagalan membersihkan sesi yang tidak digunakan dapat menurunkan performa. Untuk pengguna yang menggunakan RPC API, sebaiknya jangan tetapkan lebih dari 100 sesi per saluran gRPC.
Menangani sesi yang dihapus
Ada tiga cara untuk menghapus sesi:
- Klien dapat menghapus sesi.
- Layanan database Spanner dapat menghapus sesi saat sesi tersebut tidak ada aktivitas selama lebih dari 1 jam.
- Layanan database Spanner dapat menghapus sesi jika sesi tersebut berlangsung lebih dari 28 hari.
Percobaan untuk menggunakan hasil sesi yang dihapus di NOT_FOUND
. Jika Anda mengalami
error ini, buat dan gunakan sesi baru, tambahkan sesi baru ke kumpulan, lalu
hapus sesi yang dihapus dari kumpulan.
Membuat sesi tidak ada aktivitas tetap aktif
Layanan database Spanner berhak menghapus sesi
yang tidak digunakan. Jika benar-benar perlu menjaga sesi tidak ada aktivitas tetap aktif, misalnya, jika
diharapkan peningkatan penggunaan database jangka pendek yang signifikan, Anda dapat mencegah
sesi agar tidak dihapus. Lakukan operasi murah seperti
mengeksekusi kueri SQL SELECT 1
agar sesi tetap aktif. Jika Anda memiliki
sesi tidak ada aktivitas yang tidak diperlukan untuk penggunaan jangka pendek, biarkan Spanner menghapus
sesi, lalu buat sesi baru saat sesi diperlukan lagi.
Salah satu skenario untuk menjaga agar sesi tetap aktif adalah menangani puncak permintaan reguler pada database. Jika penggunaan database yang berat terjadi setiap hari dari pukul 09.00 hingga 18.00, Anda harus menjaga beberapa sesi tidak ada aktivitas tetap aktif selama waktu tersebut, karena sesi tersebut kemungkinan diperlukan untuk penggunaan puncak. Setelah pukul 18.00, Anda dapat mengizinkan Spanner menghentikan sesi tidak ada aktivitas. Sebelum pukul 09.00 setiap hari, buat beberapa sesi baru agar siap untuk permintaan yang diharapkan.
Skenario lainnya adalah jika Anda memiliki aplikasi yang menggunakan Spanner, tetapi harus menghindari overhead koneksi saat menggunakannya. Anda dapat menjaga serangkaian sesi tetap aktif untuk menghindari overhead koneksi.
Menyembunyikan detail sesi dari pengguna library klien
Jika Anda membuat library klien, jangan tampilkan sesi ke konsumen library klien. Beri klien kemampuan untuk melakukan panggilan database tanpa kerumitan dalam membuat dan mengelola sesi. Untuk contoh library klien yang menyembunyikan detail sesi dari konsumen library klien, lihat library klien Spanner untuk Java.
Menangani error untuk transaksi tulis yang tidak idempoten
Transaksi tulis tanpa perlindungan replay dapat menerapkan mutasi lebih dari sekali.
Jika mutasi tidak bersifat idempoten, mutasi yang diterapkan lebih dari sekali dapat
menyebabkan kegagalan. Misalnya, penyisipan mungkin gagal dengan
ALREADY_EXISTS
meskipun baris tersebut tidak ada sebelum
upaya tulis. Hal ini dapat terjadi jika server backend melakukan mutasi, tetapi
tidak dapat memberitahukan keberhasilan kepada klien. Dalam hal ini, mutasi dapat dicoba lagi, sehingga menyebabkan kegagalan ALREADY_EXISTS
.
Berikut beberapa cara untuk mengatasi skenario ini saat Anda menerapkan library klien Anda sendiri atau menggunakan REST API:
- Buat struktur penulisan agar idempoten.
- Menggunakan penulisan dengan perlindungan replay.
- Implementasikan metode yang menjalankan logika "upsert": masukkan jika baru atau perbarui jika ada.
- Menangani error atas nama klien.
Menjaga koneksi yang stabil
Untuk mendapatkan performa terbaik, koneksi yang Anda gunakan untuk menghosting sesi harus tetap stabil. Saat koneksi yang menghosting sesi berubah, Spanner dapat membatalkan transaksi aktif pada sesi dan menyebabkan sedikit beban tambahan pada database selagi Spanner memperbarui metadata sesi. Tidak masalah jika beberapa koneksi berubah secara sporadis, tetapi Anda harus menghindari situasi yang akan mengubah sejumlah besar koneksi secara bersamaan. Jika menggunakan proxy antara klien dan Spanner, Anda harus menjaga stabilitas koneksi untuk setiap sesi.
Memantau sesi aktif
Anda dapat menggunakan perintah ListSessions
untuk memantau sesi aktif di database dari command line, dengan REST API, atau dengan RPC API. ListSessions
menunjukkan sesi aktif untuk database tertentu. Hal ini
berguna jika Anda perlu menemukan penyebab kebocoran sesi. (Kebocoran sesi adalah insiden saat sesi dibuat, tetapi tidak dikembalikan ke kumpulan sesi untuk digunakan kembali.)
ListSessions
memungkinkan Anda melihat metadata tentang sesi aktif, termasuk kapan
sesi dibuat dan kapan sesi terakhir digunakan. Menganalisis data ini akan mengarahkan Anda ke arah yang tepat saat memecahkan masalah sesi. Jika sebagian besar sesi aktif
tidak memiliki approximate_last_use_time
terbaru, hal ini dapat menunjukkan
bahwa sesi tidak digunakan kembali dengan benar oleh aplikasi Anda. Lihat referensi
RPC API untuk informasi selengkapnya tentang kolom approximate_last_use_time
.
Lihat referensi REST API, referensi RPC API, atau referensi alat command line gcloud untuk mengetahui informasi lebih lanjut tentang penggunaan ListSessions
.
Pembersihan otomatis kebocoran sesi
Jika Anda menggunakan semua sesi di kumpulan sesi, setiap transaksi baru akan menunggu hingga sesi dikembalikan ke kumpulan. Jika sesi dibuat tetapi tidak dikembalikan ke kumpulan sesi untuk digunakan kembali, hal ini disebut kebocoran sesi. Saat ada kebocoran sesi, transaksi yang menunggu sesi terbuka akan terhenti tanpa batas dan memblokir aplikasi. Kebocoran sesi sering disebabkan oleh transaksi bermasalah yang berjalan dalam waktu yang sangat lama dan tidak dilakukan.
Anda dapat menyiapkan kumpulan sesi untuk otomatis menyelesaikan transaksi yang tidak aktif ini. Saat Anda mengaktifkan library klien untuk secara otomatis menyelesaikan transisi tidak aktif, library ini akan mengidentifikasi transaksi bermasalah yang mungkin menyebabkan kebocoran sesi, menghapusnya dari kumpulan sesi, dan menggantinya dengan sesi baru.
Pencatatan log juga dapat membantu mengidentifikasi transaksi yang bermasalah ini. Jika logging diaktifkan, log peringatan akan dibagikan secara default saat lebih dari 95% kumpulan sesi Anda digunakan. Jika penggunaan sesi lebih besar dari 95%, Anda perlu meningkatkan sesi maksimum yang diizinkan dalam kumpulan sesi, atau Anda mungkin mengalami kebocoran sesi. Log peringatan berisi stack trace transaksi yang berjalan lebih lama dari yang diperkirakan dan dapat membantu mengidentifikasi penyebab penggunaan kumpulan sesi yang tinggi. Log peringatan akan dikirim bergantung pada konfigurasi pengekspor log Anda.
Aktifkan library klien untuk otomatis menyelesaikan transaksi yang tidak aktif
Anda dapat mengaktifkan library klien untuk mengirim log peringatan dan menyelesaikan transaksi yang tidak aktif secara otomatis, atau mengaktifkan library klien agar hanya menerima log peringatan.
Java
Untuk menerima log peringatan dan menghapus transaksi yang tidak aktif, gunakan setWarnAndCloseIfInactiveTransactions
.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnAndCloseIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Untuk menerima log peringatan saja, gunakan
setWarnIfInactiveTransactions
.
final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnIfInactiveTransactions().build()
final Spanner spanner =
SpannerOptions.newBuilder()
.setSessionPoolOption(sessionPoolOptions)
.build()
.getService();
final DatabaseClient client = spanner.getDatabaseClient(databaseId);
Go
Untuk menerima log peringatan dan menghapus transaksi yang tidak aktif, gunakan
SessionPoolConfig
dengan InactiveTransactionRemovalOptions
.
client, err := spanner.NewClientWithConfig(
ctx, database, spanner.ClientConfig{SessionPoolConfig: spanner.SessionPoolConfig{
InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{
ActionOnInactiveTransaction: spanner.WarnAndClose,
}
}},
)
if err != nil {
return err
}
defer client.Close()
Untuk menerima log peringatan saja, gunakan customLogger
.
customLogger := log.New(os.Stdout, "spanner-client: ", log.Lshortfile)
// Create a logger instance using the golang log package
cfg := spanner.ClientConfig{
Logger: customLogger,
}
client, err := spanner.NewClientWithConfig(ctx, db, cfg)
Sesi multipleks
Sesi multipleks memungkinkan Anda membuat permintaan serentak dalam jumlah besar pada satu sesi. Sesi multipleks adalah ID yang Anda gunakan di beberapa saluran gRPC. Hal ini tidak menimbulkan bottleneck tambahan. Sesi multipleks memiliki keuntungan berikut:
- Mengurangi konsumsi resource backend karena protokol pengelolaan sesi yang lebih sederhana. Misalnya, mereka menghindari aktivitas pemeliharaan sesi yang terkait dengan pemeliharaan kepemilikan sesi dan pembersihan sampah memori.
- Sesi berumur panjang yang tidak memerlukan permintaan keep-alive saat tidak ada aktivitas.
Sesi multipleks didukung dalam hal berikut:
- Library klien Java dan Go.
Alat ekosistem Spanner yang bergantung pada Library klien Java dan Go, seperti PGAdapter, JDBC, Hibernate, driver database/sql, dan GORM.
Alat ekosistem Spanner yang bergantung pada Library klien Java dan Go, seperti PGAdapter, JDBC, Hibernate, database atau driver sql, dan GORM. Anda dapat menggunakan metrik OpenTelemetry untuk melihat cara membagi traffic antara kumpulan sesi yang ada dan sesi multipleks. OpenTelemetry memiliki filter metrik,
is_multiplexed
, yang menunjukkan sesi multipleks saat ditetapkan ketrue
.
Sesi multipleks didukung untuk semua jenis transaksi.
Library klien merotasi sesi multipleks setiap 7 hari untuk mencegah pengiriman transaksi pada sesi yang tidak berlaku.
Sesi multipleks dinonaktifkan secara default. Anda harus menggunakan variabel lingkungan untuk mengaktifkan sesi multipleks sebelum dapat menggunakannya di aplikasi klien. Untuk mengaktifkan sesi multipleks menggunakan Java atau Go, lihat Mengaktifkan sesi multipleks.
Pertimbangan
Jika Anda mencoba meng-commit isi transaksi baca atau tulis kosong atau transaksi di mana setiap kueri atau pernyataan DML gagal, ada beberapa skenario yang dapat dipertimbangkan dengan sesi multipleks. Sesi multipleks mengharuskan Anda menyertakan token pra-commit yang dibuat server dalam setiap permintaan commit. Untuk transaksi yang berisi kueri atau DML, setidaknya harus ada satu kueri atau transaksi DML sebelumnya yang berhasil agar server dapat mengirimkan kembali token yang valid ke library klien. Jika belum ada kueri atau transaksi DML
yang berhasil, library klien secara implisit akan menambahkan SELECT 1
sebelum commit.
Untuk transaksi baca atau tulis pada sesi multipleks yang hanya memiliki
mutasi, jika salah satu mutasi ditujukan untuk tabel atau
kolom yang TIDAK ada dalam skema, klien dapat menampilkan
error INVALID_ARGUMENT
, bukan error NOT_FOUND
.
Mengaktifkan sesi multipleks
Untuk menggunakan sesi multipleks di aplikasi klien, Anda harus terlebih dahulu menetapkan variabel lingkungan untuk mengaktifkannya.
Untuk mengaktifkan sesi multipleks, tetapkan
variabel lingkungan GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
ke TRUE
. Flag
ini juga mengaktifkan dukungan sesi multipleks untuk transaksi ReadOnly
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE
Guna mengaktifkan dukungan operasi yang dipartisi untuk sesi multipleks, tetapkan variabel lingkungan GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS
ke TRUE
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS=TRUE
Guna mengaktifkan dukungan transaksi baca-tulis untuk sesi multipleks, tetapkan variabel lingkungan GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW
ke TRUE
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW=True
Anda harus menetapkan GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
ke TRUE
sebagai prasyarat untuk mendukung transaksi pada sesi multipleks.
Melihat traffic untuk sesi reguler dan multipleks
Opentelemetry memiliki filter is_multiplexed
untuk menampilkan traffic untuk
sesi multipleks. Anda menetapkan filter ini ke true to view multiplexed sessions
and
false` untuk melihat sesi reguler.
- Siapkan Opentelemetry untuk Spanner menggunakan prosedur di bagian Opentelemetry Spanner Sebelum memulai.
Buka Metrics Explorer.
Di drop-down Metrik, filter
generic
.Klik Generic Task dan buka Spanner > Spanner/num_acquired_sessions.
Di kolom Filter, pilih dari opsi berikut:
a.
is_multiplexed = false
untuk melihat sesi reguler. b.is_multiplexed = true
untuk melihat sesi multipleks.Gambar berikut menunjukkan opsi Filter dengan sesi multipleks yang dipilih.
Untuk mengetahui informasi selengkapnya tentang penggunaan OpenTelemetry dengan Spanner, lihat Memanfaatkan OpenTelemetry untuk mendemokrasikan Kemampuan Observasi Spanner dan Memeriksa latensi di komponen Spanner dengan OpenTelemetry.