Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Important
Artikel ini membahas pemecahan masalah untuk Azure Cosmos DB Java SDK v4 saja. Lihat catatan Rilis Azure Cosmos DB Java SDK v4, repositori Maven, dan tips performa untuk informasi selengkapnya. Jika saat ini Anda menggunakan versi yang lebih lama dari v4, lihat panduan Migrasi ke Azure Cosmos DB Java SDK v4 untuk bantuan peningkatan ke v4.
Artikel ini membahas masalah umum, solusi, langkah diagnostik, dan alat saat Anda menggunakan Azure Cosmos DB Java SDK v4 dengan Azure Cosmos DB untuk akun NoSQL. Azure Cosmos DB Java SDK v4 menyediakan representasi logis sisi klien untuk mengakses Azure Cosmos DB for NoSQL. Artikel ini menjelaskan alat dan pendekatan untuk membantu Anda jika mengalami masalah.
Mulai dengan daftar ini:
- Lihat bagian Masalah umum dan solusi dalam artikel ini.
- Lihat Java SDK di repositori pusat Azure Cosmos DB, yang tersedia sumber terbuka di GitHub. Ini memiliki bagian masalah yang dipantau secara aktif. Periksa untuk melihat apakah ada masalah serupa dengan solusi yang sudah diajukan. Salah satu tip bermanfaat adalah memfilter masalah menurut
*cosmos:v4-item*tag. - Tinjau tips performa untuk Azure Cosmos DB Java SDK v4, dan ikuti praktik yang disarankan.
- Baca artikel lainnya, jika Anda tidak menemukan solusi. Kemudian ajukan masalah GitHub. Jika ada opsi untuk menambahkan tag ke masalah GitHub Anda, tambahkan
*cosmos:v4-item*tag.
Menangkap diagnostik
Database, kontainer, item, dan respons kueri di Java V4 SDK memiliki properti Diagnostik. Properti ini mencatat semua informasi yang terkait dengan satu permintaan, termasuk apakah ada permintaan ulang atau kegagalan sementara.
Diagnostik dikembalikan sebagai string. String berubah dengan setiap versi karena ditingkatkan untuk memecahkan masalah skenario yang berbeda dengan lebih baik. Dengan setiap versi SDK, string mungkin mengubah formatnya. Jangan mengurai string agar tidak terjadi perubahan yang merusak.
Sampel kode berikut menunjukkan cara membaca log diagnostik menggunakan Java V4 SDK:
Important
Sebaiknya validasi versi minimum yang direkomendasikan dari Java V4 SDK dan pastikan Anda menggunakan versi ini atau yang lebih tinggi. Anda dapat memeriksa versi yang direkomendasikan di sini.
Operasi Database.
CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists(databaseName);
CosmosDiagnostics diagnostics = databaseResponse.getDiagnostics();
logger.info("Create database diagnostics : {}", diagnostics);
Operasi Kontainer
CosmosContainerResponse containerResponse = database.createContainerIfNotExists(containerProperties,
throughputProperties);
CosmosDiagnostics diagnostics = containerResponse.getDiagnostics();
logger.info("Create container diagnostics : {}", diagnostics);
Operasi Item
// Write Item
CosmosItemResponse<Family> item = container.createItem(family, new PartitionKey(family.getLastName()),
new CosmosItemRequestOptions());
CosmosDiagnostics diagnostics = item.getDiagnostics();
logger.info("Create item diagnostics : {}", diagnostics);
// Read Item
CosmosItemResponse<Family> familyCosmosItemResponse = container.readItem(documentId,
new PartitionKey(documentLastName), Family.class);
CosmosDiagnostics diagnostics = familyCosmosItemResponse.getDiagnostics();
logger.info("Read item diagnostics : {}", diagnostics);
Operasi Kueri
String sql = "SELECT * FROM c WHERE c.lastName = 'Witherspoon'";
CosmosPagedIterable<Family> filteredFamilies = container.queryItems(sql, new CosmosQueryRequestOptions(),
Family.class);
// Add handler to capture diagnostics
filteredFamilies = filteredFamilies.handle(familyFeedResponse -> {
logger.info("Query Item diagnostics through handle : {}",
familyFeedResponse.getCosmosDiagnostics());
});
// Or capture diagnostics through iterableByPage() APIs.
filteredFamilies.iterableByPage().forEach(familyFeedResponse -> {
logger.info("Query item diagnostics through iterableByPage : {}",
familyFeedResponse.getCosmosDiagnostics());
});
Pengecualian Azure Cosmos DB
try {
CosmosItemResponse<Family> familyCosmosItemResponse = container.readItem(documentId,
new PartitionKey(documentLastName), Family.class);
} catch (CosmosException ex) {
CosmosDiagnostics diagnostics = ex.getDiagnostics();
logger.error("Read item failure diagnostics : {}", diagnostics);
}
Mencatat diagnostik
Java V4 SDK versi v4.43.0 ke atas mendukung pengelogan otomatis Diagnostik Cosmos untuk semua permintaan atau kesalahan jika memenuhi kriteria tertentu. Pengembang aplikasi dapat menentukan ambang batas untuk latensi (untuk operasi titik (buat, baca, ganti, upsert, patch) atau operasi non-titik (kueri, umpan perubahan, massal, dan batch)), biaya permintaan, dan ukuran payload. Jika permintaan melebihi ambang batas yang ditentukan ini, diagnostik kosmos untuk permintaan tersebut akan dipancarkan secara otomatis.
Secara default, Java v4 SDK mencatat diagnostik ini secara otomatis dalam format tertentu. Namun, ini dapat diubah dengan menerapkan CosmosDiagnosticsHandler antarmuka dan menyediakan Handler Diagnostik kustom Anda sendiri.
Ini CosmosDiagnosticsThresholds dan CosmosDiagnosticsHandler kemudian dapat digunakan dalam CosmosClientTelemetryConfig objek, yang harus diteruskan ke CosmosClientBuilder saat membuat sinkronisasi atau klien asinkron.
CATATAN: Ambang diagnostik ini diterapkan di berbagai jenis diagnostik termasuk pengelogan, pelacakan, dan telemetri klien.
Sampel kode berikut menunjukkan cara menentukan ambang diagnostik, pencatat diagnostik kustom, dan menggunakannya melalui konfigurasi telemetri klien:
Menentukan Ambang Diagnostik kustom
// Create diagnostics threshold
CosmosDiagnosticsThresholds cosmosDiagnosticsThresholds = new CosmosDiagnosticsThresholds();
// These thresholds are for demo purposes
// NOTE: Do not use the same thresholds for production
cosmosDiagnosticsThresholds.setPayloadSizeThreshold(100_00);
cosmosDiagnosticsThresholds.setPointOperationLatencyThreshold(Duration.ofSeconds(1));
cosmosDiagnosticsThresholds.setNonPointOperationLatencyThreshold(Duration.ofSeconds(5));
cosmosDiagnosticsThresholds.setRequestChargeThreshold(100f);
Menentukan Pengelola Diagnostik Sesuaian
// By default, DEFAULT_LOGGING_HANDLER can be used
CosmosDiagnosticsHandler cosmosDiagnosticsHandler = CosmosDiagnosticsHandler.DEFAULT_LOGGING_HANDLER;
// App developers can also define their own diagnostics handler
cosmosDiagnosticsHandler = new CosmosDiagnosticsHandler() {
@Override
public void handleDiagnostics(CosmosDiagnosticsContext diagnosticsContext, Context traceContext) {
logger.info("This is custom diagnostics handler: {}", diagnosticsContext.toJson());
}
};
Menentukan CosmosClientTelemetryConfig
// Create Client Telemetry Config
CosmosClientTelemetryConfig cosmosClientTelemetryConfig =
new CosmosClientTelemetryConfig();
cosmosClientTelemetryConfig.diagnosticsHandler(cosmosDiagnosticsHandler);
cosmosClientTelemetryConfig.diagnosticsThresholds(cosmosDiagnosticsThresholds);
// Create sync client
CosmosClient client = new CosmosClientBuilder()
.endpoint(AccountSettings.HOST)
.key(AccountSettings.MASTER_KEY)
.clientTelemetryConfig(cosmosClientTelemetryConfig)
.buildClient();
Coba lagi desain
Lihat panduan kami untuk merancang aplikasi yang tangguh dengan Azure Cosmos DB SDK guna mendapatkan panduan tentang cara merancang aplikasi tangguh dan mempelajari semantik pengulangan dari SDK tersebut.
Masalah umum dan solusi
Periksa metrik portal
Memeriksa metrik portal membantu menentukan apakah itu masalah sisi klien atau apakah ada masalah dengan layanan. Misalnya, jika metrik berisi permintaan yang dibatasi dengan tingkat yang tinggi (kode status HTTP 429), yang berarti permintaan tersebut sedang dibatasi, maka periksa bagian Tingkat permintaan terlalu besar.
Masalah jaringan, kegagalan pembacaan batas waktu Netty, throughput rendah, latensi tinggi
Saran umum
Untuk performa terbaik:
- Pastikan aplikasi berjalan di wilayah yang sama dengan akun Azure Cosmos DB Anda.
- Periksa penggunaan CPU pada host tempat aplikasi berjalan. Jika penggunaan CPU adalah 50 persen atau lebih, jalankan aplikasi Anda di host dengan konfigurasi yang lebih tinggi. Atau Anda dapat mendistribusikan beban pada lebih banyak komputer.
- Jika menjalankan aplikasi di Azure Kubernetes Service, Anda dapat menggunakan Azure Monitor untuk memantau pemanfaatan CPU.
Pembatasan laju koneksi
Pembatasan koneksi dapat terjadi karena batas koneksi pada komputer host atau kelelahan port Azure SNAT (PAT).
Batas koneksi pada komputer host
Beberapa sistem Linux, seperti Red Hat, memiliki batas atas jumlah total file terbuka. Soket di Linux diimplementasikan sebagai file, sehingga jumlah ini juga membatasi jumlah total koneksi. Jalankan perintah berikut.
ulimit -a
Jumlah file terbuka maksimum yang diizinkan, yang diidentifikasi sebagai "nofile", harus setidaknya dua kali lipat ukuran kumpulan koneksi Anda. Untuk informasi selengkapnya, lihat tips performa Azure Cosmos DB Java SDK v4.
Kekurangan port Azure SNAT (PAT)
Jika aplikasi Anda disebarkan di Azure Virtual Machines tanpa alamat IP publik, secara default port Azure SNAT membuat koneksi ke titik akhir apa pun di luar VM Anda. Jumlah koneksi yang diizinkan dari VM ke titik akhir Azure Cosmos DB dibatasi oleh konfigurasi Azure SNAT.
Port Azure SNAT hanya digunakan saat VM Anda memiliki alamat IP privat dan proses dari VM mencoba menyambungkan ke alamat IP publik. Ada dua solusi untuk menghindari batasan Azure SNAT:
Menambahkan titik akhir layanan Azure Cosmos DB Anda ke subnet jaringan virtual Azure Virtual Machines Anda. Untuk informasi selengkapnya, lihat Titik akhir layanan Microsoft Microsoft Azure Virtual Network.
Ketika titik akhir layanan diaktifkan, permintaan tidak lagi dikirimkan dari IP publik ke Azure Cosmos DB. Sebagai gantinya, jaringan virtual dan identitas subnet dikirim. Perubahan ini dapat mengakibatkan firewall turun jika hanya IP publik yang diizinkan. Jika Anda menggunakan firewall, saat Anda mengaktifkan titik akhir layanan, tambahkan subnet ke firewall menggunakan Virtual Network ACL.
Tetapkan IP publik ke Azure VM Anda.
Tidak dapat mengakses Layanan - firewall
ConnectTimeoutException menunjukkan bahwa SDK tidak dapat menjangkau layanan.
Anda mungkin mendapatkan kegagalan yang mirip dengan yang berikut ini saat menggunakan mode langsung:
GoneException{error=null, resourceAddress='https://cdb-ms-prod-westus-fd4.documents.azure.com:14940/apps/e41242a5-2d71-5acb-2e00-5e5f744b12de/services/d8aa21a5-340b-21d4-b1a2-4a5333e7ed8a/partitions/ed028254-b613-4c2a-bf3c-14bd5eb64500/replicas/131298754052060051p//', statusCode=410, message=Message: The requested resource is no longer available at the server., getCauseInfo=[class: class io.netty.channel.ConnectTimeoutException, message: connection timed out: cdb-ms-prod-westus-fd4.documents.azure.com/101.13.12.5:14940]
Jika Anda memiliki firewall yang berjalan di mesin aplikasi Anda, buka rentang port 10.000 hingga 20.000, yang digunakan oleh mode langsung. Ikuti juga Batas koneksi pada komputer host.
UnknownHostException
UnknownHostException berarti bahwa kerangka kerja Java tidak dapat menyelesaikan entri DNS untuk titik akhir Azure Cosmos DB di komputer yang terpengaruh. Anda harus memverifikasi bahwa mesin dapat menyelesaikan entri DNS atau jika Anda memiliki perangkat lunak resolusi DNS kustom (seperti VPN atau Proksi, atau solusi kustom), pastikan komputer tersebut berisi konfigurasi yang tepat untuk titik akhir DNS yang diklaim kesalahan tidak dapat diselesaikan. Jika kesalahan tetap ada, Anda dapat memverifikasi resolusi DNS komputer melalui perintah curl ke titik akhir yang dijelaskan dalam kesalahan.
Proksi HTTP
Jika Anda menggunakan proksi HTTP, pastikan proksi tersebut dapat mendukung jumlah koneksi yang dikonfigurasi di SDK ConnectionPolicy.
Jika tidak, Anda akan menghadapi masalah koneksi.
Pola penyandian tidak valid: Utas IO Netty terblokir
SDK menggunakan pustaka Netty IO untuk berkomunikasi dengan Azure Cosmos DB. SDK memiliki API Asinkron dan menggunakan API IO nonblocking Netty. Pekerjaan IO SDK dilakukan pada utas IO Netty. Jumlah utas IO Netty dikonfigurasi agar sama dengan jumlah inti CPU komputer aplikasi.
Utas IO Netty dimaksudkan untuk digunakan hanya untuk pekerjaan IO Netty yang tidak diblokir. SDK mengembalikan hasil pemanggilan API pada salah satu utas IO Netty ke kode aplikasi. Jika aplikasi melakukan operasi jangka panjang setelah menerima hasil pada utas Netty, SDK mungkin tidak memiliki cukup utas IO untuk melakukan pekerjaan IO internalnya. Pengkodean aplikasi tersebut dapat mengakibatkan throughput rendah, latensi tinggi, dan io.netty.handler.timeout.ReadTimeoutException kegagalan. Solusi sementara adalah mengalihkan thread saat Anda tahu operasi membutuhkan waktu.
Misalnya, lihat cuplikan kode berikut, yang menambahkan item ke kontainer (lihat di sini untuk panduan tentang menyiapkan database dan kontainer.) Anda mungkin melakukan pekerjaan jangka panjang yang membutuhkan lebih dari beberapa milidetik pada utas Netty. Jika demikian, Anda akhirnya dapat mencapai status di mana tidak ada utas IO Netty yang hadir untuk memproses pekerjaan IO. Akibatnya, Anda mendapatkan kegagalan ReadTimeoutException.
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
//Bad code with read timeout exception
int requestTimeoutInSeconds = 10;
/* ... */
AtomicInteger failureCount = new AtomicInteger();
// Max number of concurrent item inserts is # CPU cores + 1
Flux<Family> familyPub =
Flux.just(Families.getAndersenFamilyItem(), Families.getAndersenFamilyItem(), Families.getJohnsonFamilyItem());
familyPub.flatMap(family -> {
return container.createItem(family);
}).flatMap(r -> {
try {
// Time-consuming work is, for example,
// writing to a file, computationally heavy work, or just sleep.
// Basically, it's anything that takes more than a few milliseconds.
// Doing such operations on the IO Netty thread
// without a proper scheduler will cause problems.
// The subscriber will get a ReadTimeoutException failure.
TimeUnit.SECONDS.sleep(2 * requestTimeoutInSeconds);
} catch (Exception e) {
}
return Mono.empty();
}).doOnError(Exception.class, exception -> {
failureCount.incrementAndGet();
}).blockLast();
assert(failureCount.get() > 0);
Solusi alternatif adalah dengan mengubah utas tempat Anda melakukan pekerjaan yang memerlukan waktu. Tentukan instans singleton penjadwal untuk aplikasi Anda.
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
// Have a singleton instance of an executor and a scheduler.
ExecutorService ex = Executors.newFixedThreadPool(30);
Scheduler customScheduler = Schedulers.fromExecutor(ex);
Anda mungkin perlu melakukan pekerjaan yang membutuhkan waktu, misalnya, pekerjaan yang berat secara komputasi atau memblokir IO. Dalam hal ini, alihkan utas ke pekerja yang disediakan oleh customScheduler dengan menggunakan API .publishOn(customScheduler).
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
container.createItem(family)
.publishOn(customScheduler) // Switches the thread.
.subscribe(
// ...
);
Dengan menggunakan publishOn(customScheduler), Anda merilis utas IO Netty dan beralih ke utas kustom Anda sendiri yang disediakan oleh penjadwal kustom. Modifikasi ini memecahkan masalah. Anda tidak akan mengalami io.netty.handler.timeout.ReadTimeoutException kegagalan lagi.
Rentang permintaan terlalu besar
Kegagalan ini adalah kegagalan sisi server. Ini menunjukkan bahwa Anda menggunakan throughput yang dialokasikan. Coba lagi nanti. Jika Anda sering mendapatkan kegagalan ini, pertimbangkan untuk meningkatkan throughput pengumpulan.
Menerapkan backoff pada interval yang ditentukan oleh getRetryAfterInMilliseconds
Selama pengujian performa, Anda harus meningkatkan beban hingga sejumlah kecil permintaan dibatasi lajunya. Jika dibatasi, aplikasi klien harus menunda sesuai dengan interval pengulangan yang ditentukan oleh server. Menghormati konsep "backoff" memastikan bahwa Anda menghabiskan waktu seminimal mungkin menunggu di antara percobaan ulang.
Penanganan kesalahan dari Java SDK Reactive Chain
Penanganan kesalahan dari Azure Cosmos DB Java SDK penting dalam hal logika aplikasi klien. Ada mekanisme penanganan kesalahan yang berbeda yang disediakan oleh kerangka kerja reaktor-core yang dapat digunakan dalam skenario yang berbeda. Kami menyarankan pelanggan untuk memahami operator penanganan kesalahan ini secara rinci dan menggunakan yang paling sesuai dengan skenario logika coba lagi mereka.
Important
Kami tidak merekomendasikan penggunaan onErrorContinue() operator, karena tidak didukung dalam semua skenario.
Perhatikan bahwa onErrorContinue() adalah operator spesialis yang dapat membuat perilaku rantai reaktif Anda tidak jelas. Ini beroperasi pada operator hulu, bukan hilir, memerlukan dukungan operator tertentu untuk bekerja, dan cakupan dapat dengan mudah menyebar ke hulu ke dalam kode pustaka yang tidak mengantisipasinya (menghasilkan perilaku yang tidak diinginkan). Silakan merujuk ke dokumentasionErrorContinue() untuk detail lebih lanjut tentang operator khusus ini.
Kegagalan menyambungkan ke Emulator Azure Cosmos DB
Sertifikat HTTPS Emulator Azure Cosmos DB ditandatangani sendiri. Agar SDK berfungsi dengan emulator, impor sertifikat emulator ke Java TrustStore. Untuk informasi selengkapnya, lihat Mengekspor sertifikat Emulator Azure Cosmos DB.
Masalah Konflik Dependensi
Azure Cosmos DB Java SDK menarik banyak dependensi; secara umum, jika pohon dependensi proyek Anda menyertakan versi artefak lama yang bergantung pada Azure Cosmos DB Java SDK, ini dapat mengakibatkan kesalahan tak terduga yang dihasilkan saat Anda menjalankan aplikasi Anda. Jika Anda melakukan debug untuk mengetahui mengapa aplikasi Anda dengan tak terduga melempar pengecualian, ada baiknya untuk memeriksa kembali bahwa pohon dependensi Anda tidak secara tidak sengaja memasukkan versi lama dari satu atau beberapa dependensi Azure Cosmos DB Java SDK.
Solusi untuk masalah tersebut adalah mengidentifikasi dependensi proyek mana yang membawa versi lama dan mengecualikan dependensi transitif pada versi lama tersebut, dan memungkinkan Azure Cosmos DB Java SDK membawa versi yang lebih baru.
Untuk mengidentifikasi dependensi proyek mana yang membawa versi lama dari sesuatu yang bergantung pada Azure Cosmos DB Java SDK, jalankan perintah berikut terhadap file pom.xml proyek Anda:
mvn dependency:tree
Untuk informasi selengkapnya, lihat panduan pohon dependensi maven.
Setelah Anda mengetahui dependensi proyek mana yang bergantung pada versi yang lebih lama, Anda dapat memodifikasi dependensi pada lib tersebut dalam file pom Anda dan mengecualikan dependensi transitif, mengikuti contoh di bawah ini (yang mengasumsikan bahwa reactor-core adalah dependensi yang kedaluarsa):
<dependency>
<groupId>${groupid-of-lib-which-brings-in-reactor}</groupId>
<artifactId>${artifactId-of-lib-which-brings-in-reactor}</artifactId>
<version>${version-of-lib-which-brings-in-reactor}</version>
<exclusions>
<exclusion>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</exclusion>
</exclusions>
</dependency>
Untuk informasi selengkapnya, lihat panduan pengecualian dependensi transitif.
Mengaktifkan pengelogan SDK klien
Azure Cosmos DB Java SDK v4 menggunakan SLF4j sebagai fasad pengelogan yang mendukung pengelogan ke kerangka kerja pengelogan populer seperti log4j dan logback.
Misalnya, jika Anda ingin menggunakan log4j sebagai kerangka kerja pengelogan, tambahkan libs berikut di classpath Java Anda.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
Tambahkan juga konfigurasi log4j.
# this is a sample log4j configuration
# Set root logger level to INFO and its only appender to A1.
log4j.rootLogger=INFO, A1
log4j.category.com.azure.cosmos=INFO
#log4j.category.io.netty=OFF
#log4j.category.io.projectreactor=OFF
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %5X{pid} [%t] %-5p %c - %m%n
Untuk informasi selengkapnya, lihat manual pengelogan sfl4j.
Statistik jaringan OS
Jalankan perintah netstat untuk merasakan berapa banyak koneksi dalam status seperti ESTABLISHED dan CLOSE_WAIT.
Di Linux, Anda dapat menjalankan perintah berikut.
netstat -nap
Di Windows, Anda dapat menjalankan perintah yang sama dengan bendera argumen yang berbeda:
netstat -abn
Filter hasil untuk hanya koneksi ke endpoint Azure Cosmos DB.
Jumlah koneksi ke titik akhir Azure Cosmos DB dalam ESTABLISHED status tidak boleh lebih besar dari ukuran kumpulan koneksi yang dikonfigurasi.
Banyak koneksi ke titik akhir Azure Cosmos DB mungkin dalam status CLOSE_WAIT . Mungkin ada lebih dari 1.000. Angka yang tinggi menunjukkan bahwa koneksi dibuat dan dicabut dengan cepat. Situasi ini berpotensi menyebabkan masalah. Untuk informasi selengkapnya, lihat bagian Masalah umum dan solusi.
Masalah kueri umum
Metrik kueri membantu menentukan di mana kueri menghabiskan sebagian besar waktu. Dari metrik kueri, Anda dapat melihat berapa banyak yang dihabiskan untuk back-end vs klien. Pelajari selengkapnya di panduan performa kueri.
Langkah berikutnya
- Pelajari tentang Panduan performa untuk Java SDK v4
- Pelajari tentang praktik terbaik untuk Java SDK v4