إشعار
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
مهم
هذا ليس أحدث Java SDK لـ Azure Cosmos DB! يجب عليك ترقية مشروعك إلى Azure Cosmos DB Java SDK v4 ثم قراءة دليل استكشاف أخطاء Azure Cosmos DB Java SDK v4. اتبع التعليمات في دليل Migration to Azure Cosmos DB Java SDK v4 ودليل Reactor vs RxJava للترقية.
تغطي هذه المقالة استكشاف الأخطاء في Azure Cosmos DB Async Java SDK v2 فقط. راجع Azure Cosmos DB Async Java SDK v2 Release Notes, Maven repository and performance Notes لمزيد من المعلومات.
مهم
في 31 أغسطس 2024، سيتم إيقاف Azure Cosmos DB Async Java SDK v2.x؛ ستستمر مجموعة تطوير التطوير وجميع التطبيقات التي تستخدم الحزمة في العمل؛ سيتوقف Azure Cosmos DB ببساطة عن توفير المزيد من الصيانة والدعم لهذه الحزمة SDK. نوصي باتباع الإرشادات المذكورة أعلاه للترحيل إلى Azure Cosmos DB Java SDK v4.
تغطي هذه المقالة القضايا الشائعة، والحلول البديلة، وخطوات التشخيص، والأدوات عند استخدام حزمة تطوير تطوير Java Async مع قاعدة بيانات Azure Cosmos لحسابات NoSQL. يوفر SDK جافا غير المتزامنة تمثيلا منطقيا على جانب العميل للوصول إلى قاعدة بيانات Azure Cosmos لنظام NoSQL. توضح هذه المقالة الأدوات والأساليب التي تساعدك في حالة مواجهة أي مشكلات.
ابدأ بهذه القائمة:
- ألق نظرة على قسم المشكلات الشائعة والحلول في هذه المقالة.
- انظر إلى مجموعة تطوير البرمجيات (SDK)، وهي متاحة مفتوحة المصدر على GitHub. يحتوي على قسم للمشاكل يتم مراقبته بنشاط. تحقق لمعرفة ما إذا تم بالفعل تقديم أي مشكلة مماثلة مع حل بديل.
- راجع نصائح الأداء، واتبع الممارسات المقترحة.
- اقرأ بقية هذا المقال، إذا لم تجد حلا. ثم قدم مشكلة على GitHub.
المشكلات الشائعة والحلول
مشاكل في الشبكة، فشل مهلة قراءة نيتي، انخفاض معدل الإنتاجية، تأخير عالي
اقتراحات عامة
- تأكد من أن التطبيق يعمل على نفس المنطقة التي يعمل بها حساب Azure Cosmos DB الخاص بك.
- تحقق من استخدام المعالج المركزي على المضيف الذي يعمل فيه التطبيق. إذا كان استخدام المعالج 90 بالمئة أو أكثر، شغل تطبيقك على مضيف بتكوين أعلى. أو يمكنك توزيع الحمل على أجهزة أكثر.
تقليل الربط
يمكن أن يحدث تقييد الاتصال إما بسبب حد الاتصال على جهاز المضيف أو بسبب نفاد منافذ Azure SNAT (PAT).
حد الاتصال على جهاز مضيف
بعض أنظمة لينكس، مثل ريد هات، لديها حد أعلى لعدد الملفات المفتوحة الكلي. يتم تنفيذ المقابس في لينكس كملفات، لذا هذا العدد يحد أيضا من إجمالي عدد الاتصالات. قم بتشغيل الأمر التالي.
ulimit -a
الحد الأقصى لعدد الملفات المفتوحة المسموح بها، والتي تعرف بأنها "بدون ملف"، يجب أن يكون على الأقل ضعف حجم مجموعة الاتصال الخاصة بك. لمزيد من المعلومات، راجع نصائح الأداء.
Azure SNAT (PAT) port exhaustion
إذا كان تطبيقك ينشر على أجهزة Azure الافتراضية بدون عنوان IP عام، فإن منافذ Azure SNAT تقيم اتصالات مع أي نقطة نهاية خارج جهازك الافتراضي. عدد الاتصالات المسموح بها من الجهاز الظاهري لنقطة نهاية Azure Cosmos DB محدود بواسطة تكوين Azure SNAT.
تستخدم منافذ Azure SNAT فقط عندما يكون لدى جهازك الافتراضي عنوان IP خاص وتحاول عملية من الجهاز الافتراضي الاتصال بعنوان IP عام. هناك حالتان لتجنب قيود Azure SNAT:
أضف نقطة نهاية خدمة Azure Cosmos DB إلى الشبكة الفرعية لشبكة Azure Virtual Machines الخاصة بك. لمزيد من المعلومات، راجع نقاط نهاية خدمة الشبكة الظاهرية Azure.
عند تمكين نقطة نهاية الخدمة، لن يتم إرسال الطلبات من عنوان IP عام إلى Azure Cosmos DB. بدلاً من ذلك، يتم إرسال هوية الشبكة الافتراضية والشبكة الفرعية. قد يؤدي هذا التغيير إلى سقوط جدار الحماية إذا تم السماح بعناوين IP العامة فقط. إذا كنت تستخدم جدار حماية، فعند تمكين نقطة نهاية الخدمة، أضف شبكة فرعية إلى جدار الحماية باستخدام Virtual Network ACLs.
قم بتعيين عنوان IP عام لجهاز Azure الافتراضي الخاص بك.
لا يمكن الوصول إلى الخدمة - جدار الحماية
ConnectTimeoutException تشير إلى أن مجموعة تطوير البرمجيات لا يمكنها الوصول إلى الخدمة.
قد تظهر لك عطل مشابه للما يلي عند استخدام الوضع المباشر:
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]
إذا كان لديك جدار حماية يعمل على جهاز التطبيق، افتح نطاق المنافذ من 10,000 إلى 20,000 والتي تستخدمها الوضع المباشر. اتبع أيضا حد الاتصال على جهاز مضيف.
وكيل HTTP
إذا كنت تستخدم وكيل HTTP، فتأكد من أنه يمكنه دعم عدد الاتصالات التي تم تكوينها في SDK ConnectionPolicy.
خلاف ذلك، ستواجه مشكلات في الاتصال.
نمط ترميز غير صحيح: حجب خيط Netty IO
تستخدم مجموعة تطوير البرمجيات مكتبة Netty IO للتواصل مع قاعدة بيانات Azure Cosmos. تحتوي مجموعة تطوير البرمجيات على واجهات برمجة تطبيقات غير متزامنة وتستخدم واجهات برمجة تطبيقات إخراجية غير حاصرة في نيتي. يتم تنفيذ عمل الإخراج الداخلي في مجموعة تطوير البرمجيات على خيوط Netty الخاصة بالإخراج الداخلي. عدد خيوط الإدخال الداخلي (NTY) مهيأ ليكون مساويا لعدد أنوية المعالج في جهاز التطبيقات.
خيوط Netty IO مخصصة فقط للعمل غير الحاجب في Netty IO. تعيد مجموعة تطوير البرمجيات نتيجة استدعاء واجهة برمجة التطبيقات على أحد خيوط Netty IO إلى كود التطبيق. إذا أجرى التطبيق عملية طويلة الأمد بعد استلام النتائج على خيط Netty، فقد لا يكون لدى SDK عدد كاف من خيوط الإخراج التقديمي لأداء عمل الإخراج الداخلي. قد يؤدي مثل هذا الترميز إلى انخفاض معدل الإنتاجية، وزيادة التأخير، والإخفاقات io.netty.handler.timeout.ReadTimeoutException . الحل البديل هو تبديل الخيط عندما تعلم أن العملية تستغرق وقتا.
على سبيل المثال، ألق نظرة على مقتطف الكود التالي. قد تقوم بعمل طويل الأمد يستغرق أكثر من بضع أجزاء من الثانية في موضوع Netty. إذا كان الأمر كذلك، قد تصل في النهاية إلى حالة لا يوجد فيها خيط Netty IO لمعالجة أعمال الإدخال. نتيجة لذلك، تحصل على فشل في ReadTimeoutException.
Async Java SDK V2 (Maven com.microsoft.azure::azure-cosmosdb)
@Test
public void badCodeWithReadTimeoutException() throws Exception {
int requestTimeoutInSeconds = 10;
ConnectionPolicy policy = new ConnectionPolicy();
policy.setRequestTimeoutInMillis(requestTimeoutInSeconds * 1000);
AsyncDocumentClient testClient = new AsyncDocumentClient.Builder()
.withServiceEndpoint(TestConfigurations.HOST)
.withMasterKeyOrResourceToken(TestConfigurations.MASTER_KEY)
.withConnectionPolicy(policy)
.build();
int numberOfCpuCores = Runtime.getRuntime().availableProcessors();
int numberOfConcurrentWork = numberOfCpuCores + 1;
CountDownLatch latch = new CountDownLatch(numberOfConcurrentWork);
AtomicInteger failureCount = new AtomicInteger();
for (int i = 0; i < numberOfConcurrentWork; i++) {
Document docDefinition = getDocumentDefinition();
Observable<ResourceResponse<Document>> createObservable = testClient
.createDocument(getCollectionLink(), docDefinition, null, false);
createObservable.subscribe(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) {
}
},
exception -> {
//It will be io.netty.handler.timeout.ReadTimeoutException.
exception.printStackTrace();
failureCount.incrementAndGet();
latch.countDown();
},
() -> {
latch.countDown();
});
}
latch.await();
assertThat(failureCount.get()).isGreaterThan(0);
}
الحل البديل هو تغيير الخيط الذي تقوم فيه بالعمل الذي يستغرق وقتا. حدد نسخة واحدة من المجدول لتطبيقك.
Async Java SDK V2 (Maven com.microsoft.azure::azure-cosmosdb)
// Have a singleton instance of an executor and a scheduler.
ExecutorService ex = Executors.newFixedThreadPool(30);
Scheduler customScheduler = rx.schedulers.Schedulers.from(ex);
قد تحتاج إلى عمل يستغرق وقتا، مثل العمل الحسابي الثقيل أو حجب الإخراج. في هذه الحالة، قم بتحويل الخيط إلى عامل مقدم من قبل ال customScheduler.observeOn(customScheduler) API.
Async Java SDK V2 (Maven com.microsoft.azure::azure-cosmosdb)
Observable<ResourceResponse<Document>> createObservable = client
.createDocument(getCollectionLink(), docDefinition, null, false);
createObservable
.observeOn(customScheduler) // Switches the thread.
.subscribe(
// ...
);
باستخدام observeOn(customScheduler)، تقوم بتحرير خيط Netty IO وتنتقل إلى خيط مخصص مقدم من المجدول المخصص.
هذا التعديل يحل المشكلة. لن تحصل على io.netty.handler.timeout.ReadTimeoutException فشل بعد الآن.
مشكلة نفد مخزون الاتصال
PoolExhaustedException هو فشل من جهة العميل. يشير هذا الفشل إلى أن عبء العمل في تطبيقك أعلى مما يمكن أن يخدمه تجمع اتصال SDK. زد حجم مجموعة الاتصالات أو وزع الحمل على عدة تطبيقات.
معدل الطلب كبير جداً
هذا الفشل هو فشل على جانب الخادم. يشير إلى أنك استهلكت معدل النقل الذي تم توفيره. أعد المحاولة لاحقًا. إذا كنت تواجه هذا الفشل كثيرا، فكر في زيادة معدل الإنتاجية.
فشل في الاتصال بمحاكي Azure Cosmos DB
شهادة Azure Cosmos DB Emulator HTTPS موقعة ذاتيا. لكي يعمل SDK مع المحاكي، استورد شهادة المحاكي إلى متجر جافا تراست. لمزيد من المعلومات، راجع تصدير شهادات Azure Cosmos DB Emulator.
قضايا صراع الاعتماد
Exception in thread "main" java.lang.NoSuchMethodError: rx.Observable.toSingle()Lrx/Single;
الاستثناء أعلاه يشير إلى أن لديك اعتمادا على نسخة أقدم من مكتبة RxJava (مثل 1.2.2). تعتمد SDK الخاصة بنا على RxJava 1.3.8 التي تحتوي على واجهات برمجة تطبيقات لم تكن متوفرة في الإصدارات السابقة من RxJava.
الحل المتبادل لهذه المشكلات هو تحديد أي تبعيات أخرى تجلب RxJava-1.2.2 واستبعاد الاعتماد الانتقالي على RxJava-1.2.2، والسماح ل CosmosDB SDK بتقديم النسخة الأحدث.
لتحديد أي مكتبة تجلب RxJava-1.2.2، قم بتشغيل الأمر التالي بجانب ملف مشروعك pom.xml:
mvn dependency:tree
لمزيد من المعلومات، راجع دليل شجرة الاعتماد على المافن.
بمجرد تحديد RxJava-1.2.2 كاعتماد انتقالي لأي تبعية أخرى لمشروعك، يمكنك تعديل الاعتماد على تلك المكتبة في ملف pom واستبعاد الاعتماد الانتقالي في RxJava له:
<dependency>
<groupId>${groupid-of-lib-which-brings-in-rxjava1.2.2}</groupId>
<artifactId>${artifactId-of-lib-which-brings-in-rxjava1.2.2}</artifactId>
<version>${version-of-lib-which-brings-in-rxjava1.2.2}</version>
<exclusions>
<exclusion>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
</exclusion>
</exclusions>
</dependency>
لمزيد من المعلومات، راجع دليل استبعاد الاعتماد الانتقالي.
تمكين تسجيل SDK للعميل
تستخدم مجموعة تطوير جافا غير المتزامنة SLF4j كواجهة تسجيل تدعم تسجيل الدخول إلى أطر التسجيل الشائعة مثل log4j وlogback.
على سبيل المثال، إذا أردت استخدام log4j كإطار عمل للتسجيل، أضف المكتبات التالية في مسار الصف الخاص بك في جافا.
<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>
أضف أيضا إعداد log4j.
# this is a sample log4j configuration
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=INFO, A1
log4j.category.com.microsoft.azure.cosmosdb=DEBUG
#log4j.category.io.netty=INFO
#log4j.category.io.reactivex=INFO
# 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
لمزيد من المعلومات، راجع دليل تسجيل sfl4j.
إحصائيات شبكات نظام التشغيل
شغل أمر netstat للحصول على فكرة عن عدد الاتصالات في حالات مثل ESTABLISHED و CLOSE_WAIT.
على لينكس، يمكنك تشغيل الأمر التالي.
netstat -nap
تصفية النتيجة لتكون فقط الاتصالات إلى نقطة نهاية Azure Cosmos DB.
عدد الاتصالات إلى نقطة نهاية قاعدة بيانات Azure Cosmos في ESTABLISHED الحالة لا يمكن أن يكون أكبر من حجم مجموعة الاتصالات المكونة لديك.
قد تكون العديد من الاتصالات مع نقطة نهاية Azure Cosmos DB في حالة تالف CLOSE_WAIT . قد يكون هناك أكثر من 1000. هذا الرقم المرتفع يشير إلى أن العلاقات تنشأ وتهدم بسرعة. هذا الوضع قد يسبب مشاكل. لمزيد من المعلومات، راجع قسم المشاكل الشائعة والحلول البديلة .