Halaman ini menjelaskan konsep lanjutan sesi di Spanner, termasuk praktik terbaik untuk sesi saat membuat library klien, menggunakan REST API 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 dalam database Spanner. Setiap sesi berlaku untuk satu database.
Sesi dapat menjalankan satu atau beberapa transaksi sekaligus. Saat melakukan beberapa transaksi, sesi tersebut disebut sesi yang di-multiplex.
Operasi baca, tulis, dan kueri mandiri menggunakan satu transaksi secara internal.
Manfaat performa kumpulan sesi
Membuat sesi itu mahal. Untuk menghindari biaya performa setiap kali operasi database dilakukan, klien harus menyimpan kumpulan sesi, yaitu kumpulan sesi yang tersedia dan siap digunakan. Pool 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 channel gRPC
Channel gRPC digunakan oleh klien Spanner untuk komunikasi. Satu saluran gRPC kira-kira setara dengan koneksi TCP. Satu channel gRPC dapat menangani hingga 100 permintaan serentak. Artinya, aplikasi akan memerlukan setidaknya sebanyak channel gRPC seperti jumlah permintaan serentak yang akan dieksekusi aplikasi, dibagi dengan 100.
Klien Spanner membuat kumpulan channel gRPC saat Anda membuatnya.
Praktik terbaik saat menggunakan library klien Google
Berikut ini dijelaskan praktik terbaik saat menggunakan library klien Google untuk Spanner.
Mengonfigurasi jumlah sesi dan saluran gRPC di kumpulan
Library klien memiliki jumlah sesi default di kumpulan sesi dan jumlah channel gRPC default di kumpulan channel. Kedua setelan default sudah memadai untuk sebagian besar kasus. Berikut adalah sesi minimum dan maksimum default serta jumlah channel gRPC default 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 beberapa saluran gRPC. Oleh karena itu, sebaiknya buat beberapa klien, bukan meningkatkan ukuran kumpulan sesi di luar 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 luar 100 sesi untuk satu klien.
MinSessions: 10
MaxSessions: 100
Jumlah sesi yang digunakan aplikasi Anda sama dengan jumlah transaksi serentak yang dijalankan aplikasi Anda. Anda hanya boleh mengubah setelan pool sesi default jika Anda memperkirakan satu instance aplikasi akan menjalankan lebih banyak transaksi serentak daripada yang dapat ditangani oleh pool sesi default.
Untuk aplikasi dengan konkurensi tinggi, berikut adalah rekomendasi yang diberikan:
- Tetapkan
MinSessions
ke perkiraan jumlah transaksi serentak yang akan dieksekusi 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 penskalaan pool sesi ke atas atau ke bawah. Menskalakan kumpulan sesi ke atas atau ke bawah juga menggunakan beberapa resource. - Tetapkan
NumChannels
keMaxSessions / 100
. Satu channel gRPC dapat menangani hingga 100 permintaan secara serentak. Tingkatkan nilai ini jika Anda mengamati latensi ekor yang tinggi (latensi p95/p99), karena hal ini dapat menjadi indikasi kemacetan saluran gRPC.
Meningkatkan jumlah sesi aktif akan menggunakan resource tambahan di layanan database Spanner dan di 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 pool sesi di luar konkurensi maksimum yang dapat ditangani oleh satu instance aplikasi tidak direkomendasikan. Jika aplikasi menerima lonjakan permintaan yang melampaui jumlah sesi dalam pool, permintaan akan diantrekan sambil 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 berada di atas thread yang digunakan aplikasi untuk logika bisnisnya sendiri.
Meningkatkan ukuran pool sesi di luar jumlah maksimum thread yang dapat ditangani oleh satu instance aplikasi tidak direkomendasikan. Sebagai gantinya, tambah jumlah instance aplikasi.
Mengelola fraksi sesi penulisan
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 penulisan, Anda dapat menetapkan fraksi sesi penulisan.
C++
Semua sesi C++ sama. Tidak ada sesi hanya baca atau baca-tulis saja.
C#
Fraksi sesi penulisan default untuk C# adalah 0,2. Anda dapat mengubah
pecahan menggunakan kolom WriteSessionsFraction dari
SessionPoolOptions
.
Go
Semua sesi Go sama. Tidak ada sesi hanya baca atau baca-tulis saja.
Java
Semua sesi Java sama. Tidak ada sesi hanya baca atau baca-tulis saja.
Node.js
Semua sesi Node.js sama. Tidak ada sesi hanya baca atau baca-tulis saja.
PHP
Semua sesi PHP sama. Tidak ada sesi hanya baca atau baca-tulis saja.
Python
Python mendukung empat jenis kumpulan sesi berbeda yang dapat Anda gunakan untuk mengelola sesi baca dan baca-tulis.
Ruby
Fraksi sesi penulisan 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 ini dijelaskan praktik terbaik untuk menerapkan sesi di library klien untuk Spanner, atau untuk menggunakan sesi dengan API REST atau RPC.
Praktik terbaik ini hanya berlaku jika Anda mengembangkan library klien, atau jika Anda menggunakan REST/RPC API. Jika Anda menggunakan salah satu library klien Google untuk Spanner, lihat Praktik terbaik saat menggunakan library klien Google.
Membuat dan menentukan ukuran kumpulan sesi
Untuk menentukan ukuran optimal kumpulan sesi untuk proses klien, tetapkan batas bawah ke jumlah transaksi serentak yang diharapkan, dan tetapkan batas atas ke angka pengujian awal, seperti 100. Jika batas atas tidak memadai, tingkatkan batas atas. Meningkatkan jumlah sesi aktif menggunakan resource tambahan pada layanan database Spanner, sehingga kegagalan membersihkan sesi yang tidak digunakan dapat menurunkan performa. Untuk pengguna yang menggunakan RPC API, sebaiknya tidak 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 tidak aktif selama lebih dari 1 jam.
- Layanan database Spanner dapat menghapus sesi jika sesi tersebut sudah berusia lebih dari 28 hari.
Upaya untuk menggunakan sesi yang dihapus akan menghasilkan NOT_FOUND
. Jika Anda mengalami
error ini, buat dan gunakan sesi baru, tambahkan sesi baru ke kumpulan, dan
hapus sesi yang dihapus dari kumpulan.
Mempertahankan sesi tidak ada aktivitas
Layanan database Spanner berhak menghentikan sesi yang tidak digunakan. Jika Anda benar-benar perlu menjaga sesi tidak aktif tetap aktif, misalnya, jika
penggunaan database diperkirakan akan meningkat secara signifikan dalam waktu dekat, Anda dapat mencegah
sesi dihentikan. Lakukan operasi yang tidak mahal seperti
menjalankan kueri SQL SELECT 1
agar sesi tetap aktif. Jika Anda memiliki sesi tidak aktif yang tidak diperlukan untuk penggunaan dalam waktu dekat, biarkan Spanner menghentikan sesi, lalu buat sesi baru pada saat sesi diperlukan berikutnya.
Salah satu skenario untuk menjaga sesi tetap aktif adalah menangani permintaan puncak reguler di database. Jika penggunaan database berat terjadi setiap hari dari pukul 09.00 hingga 18.00, Anda harus menjaga beberapa sesi tidak aktif tetap aktif selama waktu tersebut, karena kemungkinan diperlukan untuk penggunaan puncak. Setelah pukul 18.00, Anda dapat membiarkan Spanner menghentikan sesi tidak aktif. Sebelum pukul 09.00 setiap hari, buat beberapa sesi baru agar siap untuk permintaan yang diperkirakan.
Skenario lainnya adalah jika Anda memiliki aplikasi yang menggunakan Spanner, tetapi harus menghindari overhead koneksi saat melakukannya. Anda dapat mempertahankan sekumpulan sesi agar tetap aktif untuk menghindari overhead koneksi.
Menyembunyikan detail sesi dari pengguna library klien
Jika Anda membuat library klien, jangan ekspos sesi ke konsumen library klien. Memberikan kemampuan bagi klien untuk melakukan panggilan database tanpa kerumitan dalam membuat dan mempertahankan 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 bersifat idempoten
Transaksi tulis tanpa perlindungan replay dapat menerapkan mutasi lebih dari sekali.
Jika mutasi tidak idempoten, mutasi yang diterapkan lebih dari sekali dapat menyebabkan kegagalan. Misalnya, penyisipan dapat gagal dengan
ALREADY_EXISTS
meskipun baris tidak ada sebelum
upaya penulisan. Hal ini dapat terjadi jika server backend melakukan mutasi, tetapi
tidak dapat mengomunikasikan keberhasilan kepada klien. Dalam peristiwa tersebut, mutasi dapat dicoba lagi, sehingga menyebabkan kegagalan ALREADY_EXISTS
.
Berikut kemungkinan cara untuk mengatasi skenario ini saat Anda menerapkan library klien sendiri atau menggunakan REST API:
- Strukturkan penulisan Anda agar idempoten.
- Menggunakan penulisan dengan perlindungan replay.
- Terapkan metode yang melakukan logika "upsert": sisipkan jika baru atau perbarui jika ada.
- Menangani error atas nama klien.
Mempertahankan 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 Anda saat 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 Anda menggunakan proxy antara klien dan Spanner, Anda harus mempertahankan 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
menampilkan 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 Anda, termasuk kapan sesi dibuat dan kapan sesi terakhir digunakan. Menganalisis data ini akan
menunjukkan arah yang benar 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 mengetahui informasi selengkapnya tentang kolom approximate_last_use_time
.
Lihat referensi REST API, referensi RPC API, atau referensi alat command line gcloud untuk mengetahui informasi selengkapnya tentang penggunaan ListSessions
.
Pembersihan otomatis kebocoran sesi
Saat Anda menggunakan semua sesi di kumpulan sesi, setiap transaksi baru akan menunggu hingga sesi dikembalikan ke kumpulan. Saat sesi dibuat, tetapi tidak dikembalikan ke kumpulan sesi untuk digunakan kembali, hal ini disebut kebocoran sesi. Jika terjadi kebocoran sesi, transaksi yang menunggu sesi terbuka akan macet tanpa batas waktu dan memblokir aplikasi. Kebocoran sesi sering disebabkan oleh transaksi bermasalah yang berjalan sangat lama dan tidak di-commit.
Anda dapat menyiapkan kumpulan sesi untuk menyelesaikan transaksi tidak aktif ini secara otomatis. Saat Anda mengaktifkan library klien untuk otomatis menyelesaikan transisi tidak aktif, library akan mengidentifikasi transaksi bermasalah yang dapat menyebabkan kebocoran sesi, menghapusnya dari kumpulan sesi, dan menggantinya dengan sesi baru.
Logging juga dapat membantu mengidentifikasi transaksi bermasalah ini. Jika logging diaktifkan, log peringatan dibagikan secara default jika lebih dari 95% kumpulan sesi Anda sedang digunakan. Jika penggunaan sesi Anda lebih dari 95%, Anda perlu menambah jumlah sesi maksimum yang diizinkan di kumpulan sesi, atau Anda mungkin mengalami kebocoran sesi. Log peringatan berisi stack trace transaksi yang berjalan lebih lama dari yang diharapkan dan dapat membantu mengidentifikasi penyebab penggunaan pool sesi yang tinggi. Log peringatan akan dikirimkan bergantung pada konfigurasi eksportir log Anda.
Mengaktifkan library klien untuk menyelesaikan transaksi tidak aktif secara otomatis
Anda dapat mengaktifkan library klien untuk mengirim log peringatan dan menyelesaikan transaksi yang tidak aktif secara otomatis, atau mengaktifkan library klien untuk 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 hanya menerima log peringatan, 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 hanya menerima log peringatan, 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 yang di-multiplex
Sesi yang di-multiplex memungkinkan Anda membuat sejumlah besar permintaan serentak dalam satu sesi. Sesi yang di-multiplex adalah ID yang Anda gunakan di beberapa channel gRPC. Tidak ada hambatan tambahan. Sesi yang di-multiplex memiliki keunggulan berikut:
- Pengurangan konsumsi resource backend karena protokol pengelolaan sesi yang lebih sederhana. Misalnya, mereka menghindari aktivitas pemeliharaan sesi yang terkait dengan pemeliharaan kepemilikan sesi dan pengumpulan sampah.
- Sesi berdurasi panjang yang tidak memerlukan permintaan tetap aktif saat tidak ada aktivitas.
Sesi yang di-multiplexing didukung di:
- 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, driver database atau SQL, dan GORM. Anda dapat menggunakan metrik OpenTelemetry untuk melihat cara traffic dibagi antara kumpulan sesi yang ada dan sesi yang di-multiplex. OpenTelemetry memiliki filter metrik,
is_multiplexed
, yang menampilkan sesi yang di-multiplexing jika disetel ketrue
.
Sesi yang di-multiplexing didukung untuk semua jenis transaksi.
Library klien merotasi sesi yang di-multiplex setiap 7 hari untuk mencegah pengiriman transaksi pada sesi yang sudah tidak berlaku.
Sesi multipleks dinonaktifkan secara default. Anda harus menggunakan variabel lingkungan untuk mengaktifkan sesi yang di-multiplex sebelum dapat menggunakannya di aplikasi klien. Untuk mengaktifkan sesi yang di-multiplex menggunakan Java atau Go, lihat Mengaktifkan sesi yang di-multiplex.
Pertimbangan
Jika Anda mencoba melakukan transaksi baca atau tulis yang kosong atau transaksi yang setiap kueri atau pernyataan DML-nya gagal, ada beberapa skenario yang perlu dipertimbangkan dengan sesi yang di-multiplex. Sesi yang di-multiplex memerlukan
Anda untuk menyertakan token pra-commit yang dibuat server di setiap permintaan commit. Untuk transaksi yang berisi kueri atau DML, harus ada minimal satu transaksi kueri atau DML yang berhasil sebelumnya agar server dapat mengirim kembali token yang valid ke library klien. Jika belum ada kueri atau transaksi DML yang berhasil, library klien akan menambahkan SELECT 1
secara implisit sebelum melakukan commit.
Untuk transaksi baca atau tulis pada sesi yang di-multiplex 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 yang di-multiplex
Untuk menggunakan sesi yang di-multiplex di aplikasi klien, Anda harus menyetel variabel lingkungan terlebih dahulu untuk mengaktifkannya.
Untuk mengaktifkan sesi yang di-multiplex, tetapkan variabel lingkungan
GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
ke TRUE
. Flag ini juga mengaktifkan dukungan sesi yang di-multiplex untuk transaksi ReadOnly
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE
Untuk mengaktifkan dukungan operasi yang dipartisi untuk sesi yang di-multiplex, tetapkan variabel lingkungan
GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS
ke TRUE
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS=TRUE
Untuk mengaktifkan dukungan transaksi baca-tulis untuk sesi yang di-multiplex, tetapkan variabel lingkungan
GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW
ke
TRUE
.
export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW=True
Anda harus menyetel GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS
ke TRUE
sebagai
prasyarat untuk mendukung transaksi pada sesi yang di-multiplex.
Melihat traffic untuk sesi reguler dan yang di-multiplex
Opentelemetry memiliki filter is_multiplexed
untuk menampilkan traffic untuk sesi yang di-multiplex. Anda menyetel filter ini ke true to view multiplexed sessions
and
false` untuk melihat sesi reguler.
- Siapkan Opentelemetry untuk Spanner menggunakan prosedur di bagian Spanner Opentelemetry Sebelum Anda memulai.
Buka Metrics Explorer.
Di drop-down Metrik, filter menurut
generic
.Klik Generic Task, lalu buka Spanner > Spanner/num_acquired_sessions.
Di kolom Filter, pilih salah satu opsi berikut:
a.
is_multiplexed = false
untuk melihat sesi reguler. b.is_multiplexed = true
untuk melihat sesi yang di-multiplex.Gambar berikut menunjukkan opsi Filter dengan sesi yang di-multiplexing dipilih.
Untuk mengetahui informasi selengkapnya tentang cara menggunakan OpenTelemetry dengan Spanner, lihat Memanfaatkan OpenTelemetry untuk mendemokratisasi Kemampuan Observasi Spanner dan Memeriksa latensi di komponen Spanner dengan OpenTelemetry.