Tips performa untuk Azure Cosmos DB dan .NET SDK v2

BERLAKU UNTUK: NoSQL

Azure Cosmos DB merupakan database terdistribusi yang cepat dan fleksibel yang menskalakan secara lancar dengan tingkat latensi dan throughput terjamin. Anda tidak perlu membuat perubahan arsitektur besar atau menulis kode kompleks untuk menskalakan database dengan Azure Cosmos DB. Peningkatan atau penurunan skala semudah memerintahkan satu API. Untuk mempelajari selengkapnya, lihat cara penyediaan throughput kontainer atau cara penyediaan throughput database. Karena Azure Cosmos DB diakses melalui perintah jaringan, Anda dapat membuat optimisasi sisi klien untuk mencapai kinerja puncak saat menggunakan SQL .NET SDK.

Jadi, jika Anda mencoba meningkatkan kinerja database Anda, pertimbangkan opsi ini:

Tingkatkan ke .NET V3 SDK

.NET v3 SDK dirilis. Jika Anda menggunakan .NET v3 SDK, lihat panduan kinerja .NET v3 untuk informasi berikut:

  • Default ke mode TCP Langsung
  • Dukungan Stream API
  • Dukung serializer kustom agar dapat menggunakan System.Text.JSON
  • Batch terintegrasi dan dukungan batch

Rekomendasi hosting

Nyalakan pengumpulan sampah sisi server

Pengurangan frekuensi pengumpulan sampah dapat membantu pada beberapa kasus. Dalam .NET, atur gcServer ke true.

Meluaskan skala beban kerja klien Anda

Jika Anda menguji pada tingkat throughput tinggi (lebih dari 50.000 RU/s), aplikasi klien dapat mengalami hambatan karena mesin menutup untuk CPU atau pemanfaatan jaringan. Jika mencapai titik ini, Anda dapat terus mendorong akun Azure Cosmos DB lebih jauh dengan meluaskan skala aplikasi klien di beberapa server.

Catatan

Penggunaan CPU yang tinggi dapat menyebabkan peningkatan latensi dan pengecualian waktu habis permintaan.

Operasi metadata

Jangan memverifikasi Database dan/atau Koleksi yang ada dengan menelepon Create...IfNotExistsAsync dan/atau Read...Async di jalur panas dan/atau sebelum melakukan operasi item. Validasi hanya boleh dilakukan pada startup aplikasi bila diperlukan, jika Anda mengharapkannya dihapus (jika tidak, itu tidak diperlukan). Operasi metadata ini akan menghasilkan latensi end-to-end tambahan, tidak memiliki SLA, dan keterbatasan terpisah mereka sendiri yang tidak berskala seperti operasi data.

Pencatatan dan pelacakan

Beberapa lingkungan mengaktifkan .NET DefaultTraceListener. DefaultTraceListener menimbulkan masalah performa pada lingkungan produksi yang menyebabkan penyempitan CPU dan I/O yang tinggi. Periksa dan pastikan bahwa DefaultTraceListener dinonaktifkan untuk aplikasi Anda dengan menghapusnya dari TraceListeners di lingkungan produksi.

Versi SDK terbaru (lebih besar dari 2.16.2) otomatis menghapus DefaultTraceListener saat mendeteksinya. Dengan versi yang lebih lama, Anda dapat menghapusnya dengan:

if (!Debugger.IsAttached)
{
    Type defaultTrace = Type.GetType("Microsoft.Azure.Documents.DefaultTrace,Microsoft.Azure.DocumentDB.Core");
    TraceSource traceSource = (TraceSource)defaultTrace.GetProperty("TraceSource").GetValue(null);
    traceSource.Listeners.Remove("Default");
    // Add your own trace listeners
}

Jaringan

Kebijakan koneksi: Gunakan mode koneksi langsung

Mode koneksi default .NET VA2 SDK merupakan gateway. Anda mengonfigurasi mode koneksi selama konstruksi instans DocumentClient dengan menggunakan parameter ConnectionPolicy. Jika Anda menggunakan mode langsung, Anda juga perlu mengatur Protocol dengan menggunakan parameter ConnectionPolicy. Untuk mempelajari selengkapnya tentang berbagai opsi konektivitas, lihat artikel mode konektivitas.

Uri serviceEndpoint = new Uri("https://contoso.documents.net");
string authKey = "your authKey from the Azure portal";
DocumentClient client = new DocumentClient(serviceEndpoint, authKey,
new ConnectionPolicy
{
   ConnectionMode = ConnectionMode.Direct, // ConnectionMode.Gateway is the default
   ConnectionProtocol = Protocol.Tcp
});

Kelelahan port sementara

Jika menghadapi volume koneksi tinggi atau penggunaan port tinggi pada instans, pertama-tama pastikan bahwa instans klien Anda adalah database tunggal. Dengan kata lain, instans klien harus unik untuk seumur hidup aplikasi.

Saat berjalan pada protokol TCP, klien mengoptimalkan latensi dengan menggunakan koneksi berumur panjang dibandingkan dengan protokol HTTPS, yang menghentikan koneksi setelah 2 menit tidak aktif.

Dalam skenario di mana aksesnya jarang, dan jika Anda melihat jumlah koneksi lebih tinggi jika dibandingkan dengan akses mode Gateway, Anda dapat:

  • Mengonfigurasi properti ConnectionPolicy.PortReuseMode ke PrivatePortPool (berlaku dengan versi kerangka kerja>= 4.6.1 dan versi .NET core >= 2.0): Properti ini memungkinkan SDK menggunakan sekumpulan kecil port sementara untuk titik akhir tujuan Azure Cosmos DB yang berbeda.
  • Mengonfigurasi properti ConnectionPolicy.IdleConnectionTimeout harus lebih lama dari atau sama dengan 10 menit. Nilai yang disarankan adalah antara 20 menit dan 24 jam.

Hubungi OpenAsync untuk menghindari latensi startup pada permintaan pertama

Secara default, permintaan pertama memiliki latensi yang lebih tinggi karena perlu mengambil tabel perutean alamat. Ketika Anda menggunakan SDK V2, hubungi OpenAsync() sekali selama inisialisasi untuk menghindari latensi startup ini pada permintaan pertama. Perintah terlihat seperti: await client.OpenAsync();

Catatan

OpenAsync akan menghasilkan permintaan untuk mendapatkan tabel perutean alamat untuk semua kontainer di akun. Untuk akun yang memiliki banyak kontainer dan aplikasinya mengakses subsetnya, OpenAsync akan menghasilkan sejumlah lalu lintas yang tidak perlu, yang akan membuat inisialisasi lambat. Jadi penggunaan OpenAsync mungkin tidak berguna dalam skenario ini karena memperlambat startup aplikasi.

Untuk kinerja, kolokasikan klien di region Azure yang sama

Jika memungkinkan, tempatkan aplikasi apa pun yang memerintahkan Azure Cosmos DB di region yang sama dengan database Azure Cosmos DB. Berikut adalah perkiraan perbandingan: perintah ke Azure Cosmos DB dalam region yang sama selesai dalam 1 ms hingga 2 ms, tetapi latensi antara pantai Barat dan Timur AS lebih dari 50 ms. Latensi ini dapat bervariasi dari permintaan ke permintaan, tergantung pada rute yang diambil oleh permintaan saat melewati klien ke batas pusat data Azure. Anda bisa mendapatkan latensi serendah mungkin dengan memastikan bahwa aplikasi perintah terletak di region Azure yang sama dengan titik akhir Azure Cosmos DB yang disediakan. Untuk daftar region yang tersedia, lihat Region Azure.

Kebijakan koneksi Azure Cosmos DB

Meningkatkan jumlah rangkaian/tugas

Karena perintah ke Azure Cosmos DB dilakukan melalui jaringan, Anda mungkin perlu mengubah derajat paralelisme permintaan Anda sehingga aplikasi klien menghabiskan waktu tunggu minimal antar permintaan. Contohnya, jika Anda menggunakan .NET Task Parallel Library, buat ratusan tugas yang dibaca dari atau ditulis ke Azure Cosmos DB.

Aktifkan jaringan terakselerasi

Untuk mengurangi latensi dan jitter CPU, kami menyarankan agar Anda mengaktifkan penjaringan terakselerasi pada komputer virtual klien. Lihat Membuat komputer virtual Windows dengan penjaringan terakselerasi atau Buat komputer virtual Linux dengan penjaringan terakselerasi.

Penggunaan SDK

Menginstal SDK terbaru

Azure Cosmos DB SDK terus ditingkatkan untuk memberikan performa terbaik. Lihat halaman Azure Cosmos DB SDK untuk menentukan SDK terbaru dan meninjau peningkatan.

Menggunakan klien database tunggal Azure Cosmos DB sepanjang siklus hidup aplikasi Anda

Setiap DocumentClient instans aman untuk rangkaian dan melakukan manajemen koneksi dan penembolokan alamat yang efisien saat beroperasi dalam mode Direct. Untuk memungkinkan manajemen koneksi yang efisien dan kinerja klien SDK yang lebih baik, kami menyarankan Anda menggunakan satu instans per AppDomain sepanjang siklus hidup aplikasi.

Hindari memblokir panggilan

Azure Cosmos DB SDK harus dirancang untuk memproses banyak permintaan secara bersamaan. API asinkron memungkinkan kumpulan kecil utas untuk menangani ribuan permintaan bersamaan dengan tidak menunggu pemblokiran panggilan. Alih-alih menunggu tugas sinkron yang sudah berjalan lama untuk diselesaikan, utas dapat bekerja pada permintaan lain.

Masalah performa umum dalam aplikasi yang menggunakan Azure Cosmos DB SDK adalah memblokir panggilan yang bisa asinkron. Banyak pemblokiran panggilan sinkron menyebabkan kurangnya Kumpulan Utas dan waktu respons yang menurun.

Jangan:

  • Blokir eksekusi asinkron dengan memanggil Task.Wait atau Task.Result.
  • Gunakan Task.Run untuk membuat API sinkron menjadi asinkron.
  • Dapatkan kunci di jalur kode umum. Azure Cosmos DB .NET SDK paling berkinerja ketika dirancang untuk menjalankan kode secara paralel.
  • Panggil Task.Run dan segera tunggu. ASP.NET Core sudah menjalankan kode aplikasi pada rangkaian Kumpulan Utas normal, jadi memanggil Task.Run hanya menghasilkan penjadwalan Kumpulan Utas yang tidak perlu. Bahkan jika kode yang dijadwalkan akan memblokir utas, Task.Run tidak mencegahnya.
  • Gunakan ToList() yang DocumentClient.CreateDocumentQuery(...) menggunakan pemblokiran panggilan untuk mengkuras kueri secara sinkron. Gunakan AsDocumentQuery() untuk menguras kueri secara asinkron.

Lakukan:

  • Panggil API .NET Azure Cosmos DB secara asinkron.
  • Seluruh tumpukan panggilan asinkron untuk mendapatkan manfaat dari pola asinkron/await.

Profiler, seperti PerfView, dapat digunakan untuk menemukan utas yang sering ditambahkan ke Kumpulan Utas. Acara Microsoft-Windows-DotNETRuntime/ThreadPoolWorkerThread/Start tersebut menunjukkan utas yang ditambahkan ke kumpulan utas.

Meningkatkan System.Net MaxConnections per hos saat menggunakan mode gateway

Permintaan Azure Cosmos DB dibuat melalui HTTPS/REST saat Anda menggunakan mode gateway. Mereka tunduk pada batas koneksi default per nama hos atau alamat IP. Anda mungkin perlu mengatur MaxConnections ke nilai yang lebih tinggi (dari 100 hingga 1.000) sehingga pustaka klien dapat menggunakan beberapa koneksi simultan ke Azure Cosmos DB. Dalam .NET SDK 1.8.0 dan yang lebih baru, nilai default untuk ServicePointManager.DefaultConnectionLimit adalah 50. Untuk mengubah nilai, Anda dapat mengatur Dokumen.Klien.KebijakanKoneksi.BatasKoneksiMaks ke nilai yang lebih tinggi.

Menerapkan backoff pada interval RetryAfter

Selama pengujian performa, Anda harus meningkatkan beban sampai tingkat permintaan yang kecil dibatasi. Jika permintaan dibatasi, aplikasi klien harus mundur dari pembatasan untuk interval coba ulang yang ditentukan server. Memperhatikan backoff akan memastikan bahwa Anda menghabiskan sedikit waktu saat menunggu antar coba ulang.

Dukungan kebijakan coba lagi disertakan dalam SDK berikut:

Untuk informasi selengkapnya, lihat RetryAfter.

Di .NET SDK versi 1.19 dan yang lebih baru, ada mekanisme untuk mencatat informasi diagnostik tambahan dan memecahkan masalah latensi, seperti yang ditunjukkan dalam sampel berikut. Anda dapat mencatat string diagnostik untuk permintaan yang memiliki latensi baca lebih tinggi. String diagnostik yang diambil akan membantu Anda memahami berapa kali Anda menerima eror 429 untuk permintaan tertentu.

ResourceResponse<Document> readDocument = await this.readClient.ReadDocumentAsync(oldDocuments[i].SelfLink);
readDocument.RequestDiagnosticsString 

Penembolokan dokumen URI untuk latensi baca yang lebih rendah

Lakukan penembolokan pada URI dokumen jika memungkinkan untuk kinerja baca terbaik. Anda perlu menentukan logika untuk menyimpan ID sumber daya saat Anda membuat sumber daya. Pencarian berdasarkan ID sumber daya lebih cepat daripada pencarian berbasis nama, sehingga penembolokan nilai-nilai ini meningkatkan kinerja.

Meningkatkan jumlah rangkaian/tugas

Lihat Meningkatkan jumlah rangkaian/tugas di bagian penjaringan dari artikel ini.

Operasi kueri

Untuk operasi kueri, buka tips performa untuk kueri.

Kebijakan pengindeksan

Mengecualikan jalur yang tidak digunakan dari pengindeksan untuk penulisan yang lebih cepat

Kebijakan pengindeksan Azure Cosmos DB juga memungkinkan Anda menentukan jalur dokumen mana yang akan disertakan atau dikecualikan dari pengindeksan dengan menggunakan jalur pengindeksan (IndexingPolicy.IncludedPaths dan IndexingPolicy.ExcludedPaths). Jalur pengindeksan dapat meningkatkan kinerja tulis dan mengurangi penyimpanan indeks untuk skenario di mana pola kueri diketahui sebelumnya. Ini karena biaya pengindeksan berkorelasi langsung dengan jumlah jalur unik yang diindeks. Contohnya, kode berikut menunjukkan cara mengecualikan seluruh bagian dokumen (subtree) dari pengindeksan dengan menggunakan wildcard "*":

var collection = new DocumentCollection { Id = "excludedPathCollection" };
collection.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
collection.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/nonIndexedContent/*");
collection = await client.CreateDocumentCollectionAsync(UriFactory.CreateDatabaseUri("db"), collection);

Untuk informasi selengkapnya, lihat kebijakan pengindeksan Azure Cosmos DB.

Throughput

Mengukur dan menyetel Unit Permintaan yang lebih rendah/penggunaan kedua

Azure Cosmos DB menawarkan serangkaian operasi database yang kaya. Operasi ini mencakup kueri relasional dan hierarkis dengan file Universal Disk Format (UDF), prosedur tersimpan, dan pemicu, yang semuanya beroperasi pada dokumen dalam koleksi database. Biaya yang terkait dengan masing-masing operasi ini bervariasi berdasarkan CPU, IO, dan memori yang diperlukan untuk menyelesaikan operasi. Daripada memikirkan dan mengelola sumber daya perangkat keras, Anda dapat memikirkan Unit Permintaan (Request Unit/RU) sebagai ukuran tunggal untuk sumber daya yang diperlukan untuk melakukan berbagai operasi database dan melayani permintaan aplikasi.

Throughput disediakan berdasarkan jumlah Unit Permintaan yang ditetapkan untuk setiap kontainer. Konsumsi Unit Permintaan dievaluasi sebagai tarif per detik. Aplikasi yang melebihi tarif Unit Permintaan yang disediakan untuk kontainer dibatasi hingga tarif turun di bawah tingkat yang disediakan untuk kontainer. Jika aplikasi Anda memerlukan tingkat throughput yang lebih tinggi, Anda dapat meningkatkan throughput dengan menyediakan Unit Permintaan tambahan.

Kompleksitas sebuah kueri memengaruhi jumlah Unit Permintaan yang digunakan pada sebuah operasi. Jumlah predikat, sifat predikat, jumlah file UDF, dan ukuran set data sumber memengaruhi biaya operasi kueri.

Untuk mengukur overhead operasi apa pun (buat, perbarui, atau hapus), periksa header x-ms-request-charge (atau properti RequestCharge yang setara di ResourceResponse\<T> atau FeedResponse\<T> di .NET SDK) untuk mengukur jumlah Unit Permintaan yang digunakan oleh operasi:

// Measure the performance (Request Units) of writes
ResourceResponse<Document> response = await client.CreateDocumentAsync(collectionSelfLink, myDocument);
Console.WriteLine("Insert of document consumed {0} request units", response.RequestCharge);
// Measure the performance (Request Units) of queries
IDocumentQuery<dynamic> queryable = client.CreateDocumentQuery(collectionSelfLink, queryString).AsDocumentQuery();
while (queryable.HasMoreResults)
    {
        FeedResponse<dynamic> queryResponse = await queryable.ExecuteNextAsync<dynamic>();
        Console.WriteLine("Query batch consumed {0} request units", queryResponse.RequestCharge);
    }

Biaya permintaan yang dikembalikan di header ini adalah sebagian kecil dari throughput yang Anda sediakan yaitu 2.000 RU / detik). Misalnya, jika kueri sebelumnya mengembalikan 1.000 dokumen 1-KB, biaya operasinya adalah 1.000. Jadi, dalam satu detik, server hanya mengindahkan dua permintaan tersebut sebelum tarif membatasi permintaan selanjutnya. Untuk informasi selengkapnya, lihat Unit Permintaan dan kalkulator Unit Permintaan.

Tangani pembatasan tarif/tarif permintaan yang terlalu besar

Ketika klien mencoba melebihi throughput yang dipesan untuk akun, tidak ada penurunan kinerja di server dan tidak ada penggunaan kapasitas throughput di luar tingkat yang dipesan. Server secara mandiri mengakhiri permintaan dengan RequestRateTooLarge (kode status HTTP 429). Ini mengembalikan header x-ms-retry-after-ms yang menunjukkan jumlah waktu, dalam milidetik, bahwa pengguna harus menunggu sebelum mencoba permintaan lagi.

HTTP Status 429,
Status Line: RequestRateTooLarge
x-ms-retry-after-ms :100

SDK secara implisit menangkap respons ini, mengindahkan header coba-lagi yang ditentukan server, dan mengulang permintaan. Kecuali akun Anda diakses secara bersamaan oleh beberapa klien, percobaan berikutnya akan berhasil.

Jika Anda memiliki lebih dari satu klien yang secara kumulatif beroperasi secara konsisten di atas tingkat permintaan, jumlah coba ulang default yang saat ini diatur secara internal ke 9 oleh mungkin tidak cukup. Dalam hal ini, klien melempar CosmosException dengan kode status 429 ke aplikasi.

Anda dapat mengubah jumlah coba ulang default dengan mengatur RetryOptions pada instans ConnectionPolicy. Secara default, DocumentClientException dengan kode status 429 dikembalikan setelah waktu tunggu kumulatif 30 detik jika permintaan terus beroperasi di atas kecepatan permintaan. Eror ini ditampilkan meskipun jumlah coba ulang saat ini kurang dari jumlah coba ulang maksimum, meski nilai saat ini adalah default 9 atau nilai yang ditentukan pengguna.

Perilaku coba ulang otomatis membantu meningkatkan ketahanan dan kegunaan untuk sebagian besar aplikasi. Tapi itu mungkin bukan perilaku terbaik untuk melakukan tolok ukur kinerja, terutama ketika Anda mengukur latensi. Latensi yang diamati klien akan melonjak jika eksperimen mencapai pembatasan server dan menyebabkan SDK klien mencoba ulang secara diam-diam. Untuk menghindari lonjakan latensi selama eksperimen performa, ukur biaya yang dikembalikan oleh setiap operasi dan pastikan bahwa permintaan beroperasi di bawah tarif permintaan yang dipesan. Untuk informasi selengkapnya, lihat Unit Permintaan.

Desain dokumen yang lebih kecil untuk throughput yang lebih tinggi

Biaya permintaan (yaitu, biaya pemrosesan permintaan) dari operasi tertentu berkorelasi langsung dengan ukuran dokumen. Operasi pada dokumen besar lebih mahal daripada operasi pada dokumen kecil.

Langkah berikutnya

Untuk contoh aplikasi yang digunakan untuk mengevaluasi Azure Cosmos DB untuk skenario kinerja tinggi pada beberapa mesin klien, lihat Pengujian kinerja dan skala dengan Azure Cosmos DB.

Untuk mempelajari selengkapnya tentang perancangan aplikasi Anda untuk skala dan kinerja tinggi, lihat Pemartisian dan penyekalaan di Azure Cosmos DB.