Tips performa untuk Azure Cosmos DB dan .NET SDK v2

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 utama atau menulis kode kompleks untuk menskalakan database Anda dengan Azure Cosmos DB. Peningkatan atau penurunan skala semudah menjalankan satu panggilan API. Untuk mempelajari lebih lanjut, lihat cara menyediakan throughput kontainer atau cara menyediakan throughput database. Tetapi karena Azure Cosmos DB diakses melalui panggilan jaringan, ada pengoptimalan sisi klien yang dapat Anda lakukan untuk mencapai performa puncak saat Anda menggunakan SQL .NET SDK.

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

Tingkatkan ke .NET V3 SDK

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

  • Secara default menggunakan mode TCP Langsung
  • Dukungan STREAM API
  • Mendukung pengatur serial khusus agar dapat menggunakan System.Text.JSON
  • Dukungan batch dan jumlah besar terintegrasi

Rekomendasi hosting

Mengaktifkan pengumpulan sampah sisi server (GC)

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/dtk), aplikasi klien bisa menjadi hambatan karena mesin mencapai batas maksimum pada pemanfaatan CPU atau jaringan. Jika mencapai titik ini, Anda dapat terus mendorong akun Azure Cosmos DB lebih jauh dengan meluaskan skala aplikasi klien di beberapa server.

Nota

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

Operasi metadata

Jangan verifikasi keberadaan Database dan/atau Koleksi dengan memanggil Create...IfNotExistsAsync dan/atau Read...Async di jalur kritis dan/atau sebelum melakukan operasi pada item. Validasi hanya boleh dilakukan pada startup aplikasi ketika diperlukan, jika Anda mengharapkannya dihapus (jika tidak, tidak diperlukan). Operasi metadata ini akan menghasilkan latensi end-to-end tambahan, tidak memiliki SLA, serta memiliki batasan tersendiri 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) secara otomatis menghapusnya ketika mereka 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 V2 SDK adalah gateway. Anda mengonfigurasi mode koneksi selama pembangunan DocumentClient instans dengan menggunakan ConnectionPolicy parameter . Jika Anda menggunakan mode langsung, Anda juga perlu mengatur Protocol dengan menggunakan ConnectionPolicy parameter . 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 Anda melihat volume koneksi tinggi atau penggunaan port tinggi pada instans, pertama-tama pastikan bahwa instans klien Anda adalah singleton. 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 mengakhiri koneksi setelah 2 menit tidak aktif.

Dalam skenario di mana Anda memiliki akses terbatas dan jika Anda melihat jumlah koneksi yang lebih tinggi dibandingkan dengan akses dalam mode gateway, Anda dapat:

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

Panggil OpenAsync untuk menghindari latensi startup pada permintaan pertama

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

Nota

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

Untuk performa, kolokasikan klien di wilayah 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: panggilan ke Azure Cosmos DB dalam wilayah yang sama selesai dalam waktu 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 aplikasi panggilan terletak di dalam wilayah Azure yang sama dengan titik akhir Azure Cosmos DB yang disediakan. Untuk daftar region yang tersedia, lihat Region Azure.

Kebijakan koneksi Azure Cosmos DB

Menambah jumlah utas/tugas

Karena panggilan ke Azure Cosmos DB dilakukan melalui jaringan, Anda mungkin perlu memvariasi tingkat paralelisme permintaan Anda sehingga aplikasi klien menghabiskan waktu minimal menunggu di antara 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 sarankan Anda mengaktifkan jaringan terakselerasi pada komputer virtual klien. Lihat Membuat komputer virtual Windows dengan jaringan yang dipercepat atau Membuat komputer virtual Linux dengan jaringan yang dipercepat.

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 instans DocumentClient aman bagi utas dan melakukan pengelolaan koneksi serta penembolokan alamat yang efisien saat beroperasi dalam modus langsung. Untuk memungkinkan manajemen koneksi yang efisien dan performa klien SDK yang lebih baik, kami sarankan Anda menggunakan satu instans per AppDomain untuk masa pakai 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 kekurangan sumber daya pada 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 utas Thread Pool yang normal, jadi memanggil Task.Run hanya menghasilkan penjadwalan utas yang tidak perlu. Meskipun kode terjadwal dapat memblokir utas, Task.Run tidak akan mencegah hal itu terjadi.
  • Gunakan ToList() pada DocumentClient.CreateDocumentQuery(...) yang menggunakan pemanggilan blokir untuk menguras kueri secara sinkron. Gunakan AsDocumentQuery() untuk menguras kueri secara asinkron.

Lakukan:

  • Panggil API .NET Azure Cosmos DB secara asinkron.
  • Seluruh tumpukan panggilan bersifat asinkron untuk memanfaatkan pola async/await.

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

Tingkatkan System.Net MaxConnections per host 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 host atau alamat IP. Anda mungkin perlu mengatur MaxConnections ke nilai yang lebih tinggi (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 Documents.Client.ConnectionPolicy.MaxConnectionLimit ke nilai yang lebih tinggi.

Menerapkan jeda balik sesuai interval RetryAfter

Selama pengujian performa, Anda harus meningkatkan beban hingga sejumlah kecil permintaan-permintaan tersebut ditunda. Jika permintaan dibatasi, aplikasi klien harus mengurangi permintaan untuk interval coba lagi yang ditentukan oleh server. Mematuhi backoff memastikan Anda menghabiskan waktu minimal menunggu di antara percobaan ulang.

Dukungan kebijakan coba lagi disertakan dalam SDK ini:

Untuk informasi selengkapnya, lihat RetryAfter.

Dalam versi 1.19 dan yang lebih baru dari .NET SDK, 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 yang lebih tinggi. String diagnostik yang diambil akan membantu Anda memahami berapa kali Anda menerima kesalahan 429 untuk permintaan tertentu.

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

URI dokumen cache untuk latensi baca yang lebih rendah

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

Meningkatkan jumlah rangkaian/tugas

Lihat Menambah jumlah threads/tugas di bagian jaringan dalam artikel ini.

Operasi Query

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 performa 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. Misalnya, kode ini menunjukkan cara mengecualikan seluruh bagian dokumen (subtree) dari pengindeksan dengan menggunakan kartubebas "*":

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.

Daya Tampung

Mengukur dan menyetel untuk penggunaan Unit Permintaan per detik yang lebih rendah

Azure Cosmos DB menawarkan serangkaian operasi database yang kaya. Operasi ini termasuk kueri relasional dan hierarkis dengan UDF, prosedur tersimpan, dan pemicu, semua beroperasi pada dokumen dalam koleksi database. Biaya yang terkait dengan masing-masing operasi ini bervariasi tergantung pada CPU, IO, dan memori yang diperlukan untuk menyelesaikan operasi. Alih-alih memikirkan dan mengelola sumber daya perangkat keras, Anda dapat menganggap Unit Permintaan (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. Unit Permintaan diukur dengan tingkat konsumsi per detik. Aplikasi yang melebihi tingkat Unit Permintaan yang dialokasikan untuk kontainernya akan dibatasi sampai tingkat permintaan turun ke bawah tingkat yang dialokasikan untuk kontainer tersebut. Jika aplikasi Anda memerlukan tingkat throughput yang lebih tinggi, Anda dapat meningkatkan throughput dengan menyediakan Unit Permintaan tambahan.

Kompleksitas kueri memengaruhi berapa banyak Unit Permintaan yang digunakan untuk operasi. Jumlah predikat, sifat predikat, jumlah UDF, dan ukuran himpunan data sumber semuanya memengaruhi biaya operasi kueri.

Untuk mengukur overhead operasi apa pun (membuat, memperbarui, atau menghapus), periksa header x-ms-request-charge (atau properti yang setara RequestCharge 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 melayani dua permintaan tersebut sebelum membatasi permintaan berikutnya. Untuk informasi selengkapnya, lihat Unit Permintaan dan kalkulator Unit Permintaan.

Tangani pembatasan laju/laju permintaan yang terlalu tinggi

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 akan terlebih dahulu mengakhiri permintaan dengan RequestRateTooLarge (kode status HTTP 429). Ini akan mengembalikan header x-ms-retry-after-ms yang menunjukkan jumlah waktu dalam milidetik yang harus ditunggu pengguna sebelum melakukan permintaan lagi.

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

SDK-SDK tersebut secara implisit menangani respons ini, mematuhi header coba-lagi yang ditentukan server, dan mengirim ulang 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 lagi default yang saat ini diatur ke 9 secara internal oleh klien mungkin tidak cukup. Dalam hal ini, klien melempar DocumentClientException 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 tingkat permintaan. Kesalahan ini muncul kembali bahkan ketika jumlah percobaan ulang saat ini lebih sedikit dari jumlah percobaan ulang maksimum, baik 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 oleh klien akan melonjak jika eksperimen mencapai batas server dan menyebabkan SDK klien melakukan percobaan ulang tanpa pemberitahuan. Untuk menghindari lonjakan latensi selama eksperimen performa, ukur muatan yang dikembalikan oleh setiap operasi dan pastikan bahwa permintaan beroperasi di bawah tingkat permintaan yang telah dipesan. Untuk informasi selengkapnya, lihat Unit Permintaan.

Untuk throughput yang lebih tinggi, rancang dokumen yang lebih kecil

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 aplikasi sampel yang digunakan untuk mengevaluasi Azure Cosmos DB untuk skenario performa tinggi pada beberapa komputer klien, lihat Pengujian performa 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.