عملية تشخيص واستكشاف أخطاء الطلبات البطيئة Azure Cosmos DB بواسطة SDK.NET وإصلاحها
ينطبق على: NoSQL
في قاعدة بيانات Azure Cosmos، قد تلاحظ الطلبات البطيئة. يمكن أن تكون طلبات قاعدة بيانات Azure Cosmos بطيئة لأسباب متعددة مثل تقييد الطلب أو نتيجة الطريقة نفسها التي صممت بها طلبك. تعرض هذه المقالة الأسباب الجذرية المختلفة لهذه المشكلة.
معدل الطلب كبير جداً
تقييد الطلب هو السبب الأكثر شيوعا للطلبات البطيئة. تقيد قاعدة بيانات Azure Cosmos منظم حمل العمل الطلبات إذا تجاوزت هذه الطلبات وحدات الطلب RUs المخصصة لقاعدة البيانات أو الحاوية. SDK لديه منطق مدمج لإعادة المحاولة مع هذه الطلبات. توضح مقالة استكشاف أخطاء معدل الطلب كبير جداً وإصلاحها طريقة التحقق في حالة كانت الطلبات مقيدة وطريقة تغير سعة حسابك لتجنب هذه المشكلات في المستقبل. تتناول المقالة أيضا كيفية تغير سعة حسابك لتجنب هذه المشكلات في المستقبل.
تصميم التطبيق
عند تصميم التطبيق الخاص بك، اتبع أفضل الممارسات .NET SDK للحصول على أفضل أداء. إذا كان تطبيقك لا يتبع أفضل ممارسات SDK ، فقد تحصل على طلبات بطيئة أو فاشلة.
عند تطوير تطبيقك، راعي التالي ذكره:
- احرص على أن يكون التطبيق في نفس منطقة حساب قاعدة البيانات Azure Cosmos .
- يجب أن تعكس ApplicationRegion أو ApplicationPreferredRegions تفضيلاتك الإقليمية وأن تشير إلى المنطقة التي تم توزيع التطبيق فيها.
- قد يكون هناك اختناق في واجهة الشبكة بسبب نسبة استخدام الشبكة العالية. إذا كان التطبيق يعمل على أجهزة Azure الظاهرية، فهناك حلول بديلة ممكنة:
- ضع في اعتبارك استخدام آلة افتراضية مع تمكين Accelerated Networking.
- قم بتمكين تسريع الاتصال بالشبكة على جهاز ظاهري موجود.
- ضع في اعتبارك استخدام جهاز ظاهري متطور.
- فضل وضع الاتصال المباشر.
- تجنب ارتفاع في المعالج CPU. تأكد من مراجعة الحد الأقصى الخاص بـ CPU وليس المتوسط وهو الحد الافتراضي لمعظم أنظمة تسجيل الدخول. في الأغلب أي شيء أكثر من 40٪ يمكن أن يؤثر على زيادة زمن الانتقال.
عمليات بيانات التعريف
في حالة كنت بحاجة إلى التحقق من وجود قاعدة بيانات أو حاوية، فلا تقم بذلك عن طريق الاتصال Create...IfNotExistsAsync
أو Read...Async
قبل إجراء عملية العنصر. يجب أن يتم التحقق من الصحة فقط عند بدء تشغيل التطبيق عند الضرورة، في حالة كنت تتوقع حذفها. تولد عمليات البيانات الوصفية هذه زمن انتقال إضافي وليست تملك اتفاقية على مستوى الخدمة (SLA)، ولها قيود منفصلة خاصة بها. فهي لا تغير السعة مثل عمليات البيانات.
الطلبات بطيئة في الوضع المجمع
الوضع المجمع هو معدل النقل محسن للإنتاجية مخصص لعمليات حجم البيانات العالية وليس وضعا محسنا لزمن الانتقال؛ الغرض منه هو تشبع معدل النقل المتاح. في حالة كنت تواجه طلبات بطيئة عند استخدام الوضع المجمع، فتأكد مما يلي:
- يتم تجميع التطبيق الخاص بك في التكوين الخاص بالإصدار.
- أنت لا تقيس زمن الوصول أثناء تصحيح الأخطاء الخاصة بالتطبيق (لا توجد مصححات مرفقة).
- حجم العمليات مرتفع، تجنب استخدام كميات كبيرة لأقل من 1000 عملية. يملي معدل النقل المتوفر لديك عدد العمليات في الثانية التي يمكنك معالجتها وسيكون هدفك بالجملة هو الاستفادة من أكبر قدر ممكن منها.
- راقب الحاوية بحثا عن سيناريوهات التقييد. إذا كانت الحاوية تتعرض للتقييد الشديد، فهذا يعني أن حجم البيانات أكبر من معدل النقل الذي تم توفيره، فأنت بحاجة إما إلى توسيع نطاق الحاوية أو تقليل حجم البيانات (ربما إنشاء دفعات أصغر من البيانات في وقت واحد).
- أنت تستخدم النمط
async/await
بشكل صحيح لمعالجة كافة المهام المتزامنة وتجنب حظر أي عملية غير متزامنة.
تسجيل التشخيص
تتضمن جميع الاستجابات في SDK على CosmosException
خاصية التشخيصDiagnostics
. تسجل هذه الخاصية كل المعلومات الخاصة بالطلب المفرد بما في ذلك إذا كانت هناك إعادة محاولة أو أي فشل مؤقت.
يتم إرجاع التشخيصات كسلسلة. تتغير السلسلة مع كل إصدار كما يتم العمل على تحسينها لاستكشاف أفضل سيناريوهات اكتشاف الأخطاء وإصلاحها. مع كل إصدار من SDK، يكون للسلسة تغيرات جذرية في التنسيق. تجنب توزيع السلسلة حتى تتجنب التغيرات الجذرية. توضح عينة التعليمات البرمجية التالية كيفية قراءة السجلات الخاصة بالتشخيص باستخدام SDK.NET:
try
{
ItemResponse<Book> response = await this.Container.CreateItemAsync<Book>(item: testItem);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan)
{
// Log the response.Diagnostics.ToString() and add any additional info necessary to correlate to other logs
}
}
catch (CosmosException cosmosException)
{
// Log the full exception including the stack trace with: cosmosException.ToString()
// The Diagnostics can be logged separately if required with: cosmosException.Diagnostics.ToString()
}
// When using Stream APIs
ResponseMessage response = await this.Container.CreateItemStreamAsync(partitionKey, stream);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan || !response.IsSuccessStatusCode)
{
// Log the diagnostics and add any additional info necessary to correlate to other logs with: response.Diagnostics.ToString()
}
التشخيص موجود في الإصدار 3.19 والإصدارت الأحدث
تحتوي بنية JSON على التغييرات الجذرية الصادرة مع كل إصدار من SDK. وهذا يجعل من غير الأمن توزيعها. تمثل JSON بنية شجرة الطلب التي تمر عبر SDK. تغطي الأقسام التالية بعض الأشياء الأساسية التي يجب النظر إليها.
سجل معالج CPU
استخدام CPU عالية هو السبب الأكثر شيوعا لمشكلة الطلبات البطيئة. للحصول على زمن انتقال مثالي، يجب أن يكون استخدام وحدة المعالجة المركزية حوالي 40 بالمائة. استخدم 10 ثوانٍ كفاصل زمني لمراقبة الحد الأقصى (وليس المتوسط) لاستخدام وحدة المعالجة المركزية. تعد الارتفاعات الحادة في CPU تكون أكثر شيوعاً مع استعلامات القسم المتقاطع؛ حيث يمكن أن تجري الطلبات اتصالات متعددة عن استعلام واحد.
تحتوي مهلات التشخيصات، التي تحتوي على ما يلي، على سبيل المثال:
"systemHistory": [
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
{
"dateUtc": "2021-11-17T23:38:38.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
...
]
- في حالة تجاوزت قيم
cpu
70٪، فمن المحتمل أن يكون سبب انتهاء المهلة هو استنفاد CPU. في هذه الحالة، يتمثل الحل في التحقق من مصدر الاستخدام العالي لوحدة المعالجة المركزية وتقليله، أو توسيع نطاق الجهاز إلى حجم مورد أكبر. - إذا كانت قيمة العقد
threadInfo/isThreadStarving
هيTrue
، يرجع السبب إلى نقص مؤشر ترابط. في هذه الحالة، يكون الحل هو التحقيق في مصدر / مصادر محادثة نصية (المحادثة النصية التي يحتمل أن تكون مقفلة)، أو تغير سعة مؤشر ترابط الجهاز / الأجهزة إلى حجم مورد أكبر. - إذا لم تصل المدة
dateUtc
بين القياسات إلى 10 ثوانٍ تقريباً، يشير ذلك أيضاً إلى وجود اختلاف في تجمع المحادثة النصية. يتم قياس وحدة المعالجة المركزية كمهمة مستقلة يتم أدراجها في قائمة الانتظار في تجمع مؤشرات محادثة نصية كل 10 ثوان. في حالة كان الوقت بين القياسات أطول، فهذا يشير إلى أن المهام غير المتزامنة غير قابلة للمعالجة في الوقت المناسب. السيناريو الأكثر شيوعا هو عندما يقوم تعليمة برمجية التطبيق بحظر المكالمات عبر التعليمات البرمجية غير المتزامنة.
حل
يجب توسيع نطاق تطبيق العميل الذي يستخدم SDK أو زيادة حجمه.
HttpResponseStats
HttpResponseStats
تعد الطلبات التي تذهب إلى البوابة. حتى في الوضع المباشر تحصل SDK على كل معلومات بيانات الخاصة بالتعريف من البوابة.
في حالة كان الطلب بطيئا، فتحقق أولا من عدم تحقيق أي من الاقتراحات السابقة النتائج المرجوة. في حالة كان الطلب لا يزال بطيئاً، أشارت الأنماط المختلفة إلى مشكلات مختلفة: يوفر الجدول التالي تفاصيل.
عدد الطلبات | السيناريو | الوصف |
---|---|---|
فردي للجميع | طلب المهلة أو HttpRequestExceptions |
يشير إلى استنزاف منفذ SNAT أو النقص في موارد الجهاز اللازمة لمعالجة الطلب في الوقت المناسب. |
النسبة المئوية أحادية أو صغيرة (لا تنتهك اتفاقية مستوى الخدمة) | الكل | من الممكن أن يكون سبب ظهور نسبة مئوية أحادية أو صغيرة من الطلبات البطيئة العديد من المشكلات المؤقتة المختلفة التي يجب توقعها. |
الكل | الكل | تشير إلى مشكلة في البنية الأساسية أو الشبكات. |
انتهاك الاتفاقية على مستوى الخدمة | لم يتم إسقاط أي تغييرات على التطبيق وعلى SLA | يشير إلى مشكلة في خدمة قاعدة بيانات Azure Cosmos. |
"HttpResponseStats": [
{
"StartTimeUTC": "2021-06-15T13:53:09.7961124Z",
"EndTimeUTC": "2021-06-15T13:53:09.7961127Z",
"RequestUri": "https://127.0.0.1:8081/dbs/347a8e44-a550-493e-88ee-29a19c070ecc/colls/4f72e752-fa91-455a-82c1-bf253a5a3c4e",
"ResourceType": "Collection",
"HttpMethod": "GET",
"ActivityId": "e16e98ec-f2e3-430c-b9e9-7d99e58a4f72",
"StatusCode": "OK"
}
]
StoreResult
StoreResult
يمثل StoreResult طلب واحد إلى قاعدة بيانات AzureCosmos باستخدام وضع الاتصال المباشر مع بروتوكول TCP.
في حالة كان الطلب لا يزال بطيئاً، أشارت الأنماط المختلفة إلى مشكلات مختلفة: يوفر الجدول التالي تفاصيل.
عدد الطلبات | السيناريو | الوصف |
---|---|---|
فردي للجميع | StoreResult المحتوياتTransportException |
يشير إلى استنزاف منفذ SNAT أو النقص في موارد الجهاز اللازمة لمعالجة الطلب في الوقت المناسب. |
النسبة المئوية أحادية أو صغيرة (لا تنتهك اتفاقية مستوى الخدمة) | الكل | من الممكن أن يكون سبب ظهور نسبة مئوية أحادية أو صغيرة من الطلبات البطيئة العديد من المشكلات المؤقتة المختلفة التي يجب توقعها. |
الكل | الكل | مشكلة في البنية الأساسية أو الشبكات. |
انتهاك الاتفاقية على مستوى الخدمة | تحتوي الطلبات على رموز خطأ فشل متعددة، مثل 410 |
يشير إلى مشكلة في خدمة Azure Cosmos DB أو جهاز العميل. |
انتهاك الاتفاقية على مستوى الخدمة | StorePhysicalAddress هو نفسه مع عدم وجود تعليمة برمجية حالة الفشل. |
من المحتمل أن تكون هناك مشكلة في قاعدة بيانات Azure Cosmos . |
انتهاك الاتفاقية على مستوى الخدمة | StorePhysicalAddress لها نفس معرف القسم مع اختلاف معرفات النسخ المتماثلة وعدم وجود أي تعليمة برمجية لحالة الفشل. |
من المحتمل أن تكون هناك مشكلة في قاعدة بيانات Azure Cosmos . |
انتهاك الاتفاقية على مستوى الخدمة | StorePhysicalAddress عشوائي، مع عدم وجود تعليمة برمجية حالة الفشل. |
تشير إلى مشكلة في الجهاز. |
للحصول على نتائج تخزين متعددة لطلب واحد، كن على علم بما يلي:
- الاتساق القوي والمحدود سيكون له دائماً نتيجتان على الأقل في نتائج التخزين.
- التحقق من تعليمة برمجية لحالة الكل
StoreResult
. تعيد SDK المحاولة تلقائياً على عدة إخفاقات مؤقتة . يستمر التحسين في SDK لتغطية المزيد من السيناريوهات.
سطر وقت الطلب
إظهار الوقت المستغرق للمراحل المختلفة لإرسال واستلام الطلب في طبقة النقل.
ChannelAcquisitionStarted
: الوقت للحصول على اتصال جديد أو إنشائه. يمكن إنشاء الاتصالات لأسباب عديدة مثل: تم إغلاق الاتصال السابق بسبب عدم النشاط باستخدام CosmosClientOptions.IdleTcpConnectionTimeout، أو تجاوز حجم الطلبات المتزامنة CosmosClientOptions.MaxRequestsPerTcpConnection، أو تم إغلاق الاتصال بسبب خطأ في الشبكة، أو أن التطبيق لا يتبع نمط Singleton ويتم إنشاء مثيلات جديدة باستمرار. بمجرد إنشاء اتصال، تتم إعادة استخدامه للطلبات اللاحقة، لذلك يجب ألا يؤثر هذا على زمن انتقال P99 ما لم تحدث المشكلات المذكورة سابقا.Pipelined
قد يكون الوقت كبيرا بسبب طلب كبير.Transit time
كبير، مما يؤدي إلى مشكلة في الشبكات. قارن هذا الرقم بـBELatencyInMs
. إذا كانتBELatencyInMs
BELatencyInMs صغيرة، يتم استهلاك الوقت على الشبكة بدلاً من استهلاكه على خدمة قاعدة البياناتAZURE Cosmos .Received
قد يكون الوقت كبيرا بسبب مشكلة تجويع مؤشر الترابط. إنه الوقت بين وجود الإستجابة وإرجاع النتيجة.
ServiceEndpointStatistics
معلومات حول خادم خلفي عين. يمكن لـ SDK فتح اتصالات متعددة إلى خادم خلفية واحد اعتمادًا على عدد الطلبات المعلقة وMaxConcurrentRequestsPerConnection.
inflightRequests
عدد الطلبات المعلقة إلى الخادم الخلفي (ربما من أقسام مختلفة). قد يؤدي العدد المرتفع إلى زيادة نسبة استخدام الشبكة وزمن انتقال أعلى.openConnections
هو إجمالي عدد الاتصالات المفتوحة لخادم خلفي واحد. يمكن أن يكون هذا مفيدًا لإظهار إخراج منفذ SNAT إذا كان هذا الرقم مرتفعًا جدًا.
ConnectionStatistics
معلومات حول الاتصال المعين (الجديد أو القديم) الذي يتم تعيين الطلب إليه.
waitforConnectionInit
: كان الطلب الحالي ينتظر اكتمال تهيئة الاتصال الجديدة. سيؤدي هذا إلى زمن انتقال أعلى.callsPendingReceive
: عدد الاستدعاءات التي كانت معلقة قبل إرسال هذا الاستدعاء. يمكن أن يظهر لنا عدد كبير أنه كان هناك الكثير من الاستدعاءات قبل هذا الاستدعاء وقد يؤدي ذلك إلى زمن انتقال أعلى. إذا كان هذا الرقم مرتفعًا، فإنه يشير إلى مشكلة حظر السطر الرئيسية ربما بسبب طلب آخر مثل الاستعلام أو عملية الموجز التي تستغرق وقتًا طويلا لمعالجتها. حاول خفض CosmosClientOptions.MaxRequestsPerTcpConnection لزيادة عدد القنوات.LastSentTime
: وقت آخر طلب تم إرساله إلى هذا الخادم. يمكن استخدام هذا جنبًا إلى جنب مع LastReceivedTime لعرض مشكلات الاتصال أو نقطة النهاية. على سبيل المثال، إذا كان هناك الكثير من مهلات الاستلام، فسيكون وقت الإرسال أكبر بكثير من وقت الاستلام.lastReceive
: وقت آخر طلب تم تلقيه من هذا الخادمlastSendAttempt
: وقت آخر محاولة إرسال
أحجام الطلب والاستجابة
requestSizeInBytes
: الحجم الإجمالي للطلب المرسل إلى Azure Cosmos DBresponseMetadataSizeInBytes
: حجم العناوين التي تم إرجاعها من Azure Cosmos DBresponseBodySizeInBytes
: حجم المحتوى الذي تم إرجاعه من Azure Cosmos DB
"StoreResult": {
"ActivityId": "bab6ade1-b8de-407f-b89d-fa2138a91284",
"StatusCode": "Ok",
"SubStatusCode": "Unknown",
"LSN": 453362,
"PartitionKeyRangeId": "1",
"GlobalCommittedLSN": 0,
"ItemLSN": 453358,
"UsingLocalLSN": true,
"QuorumAckedLSN": -1,
"SessionToken": "-1#453362",
"CurrentWriteQuorum": -1,
"CurrentReplicaSetSize": -1,
"NumberOfReadRegions": 0,
"IsValid": true,
"StorePhysicalAddress": "rntbd://127.0.0.1:10253/apps/DocDbApp/services/DocDbServer92/partitions/a4cb49a8-38c8-11e6-8106-8cdcd42c33be/replicas/1s/",
"RequestCharge": 1,
"RetryAfterInMs": null,
"BELatencyInMs": "0.304",
"transportRequestTimeline": {
"requestTimeline": [
{
"event": "Created",
"startTimeUtc": "2022-05-25T12:03:36.3081190Z",
"durationInMs": 0.0024
},
{
"event": "ChannelAcquisitionStarted",
"startTimeUtc": "2022-05-25T12:03:36.3081214Z",
"durationInMs": 0.0132
},
{
"event": "Pipelined",
"startTimeUtc": "2022-05-25T12:03:36.3081346Z",
"durationInMs": 0.0865
},
{
"event": "Transit Time",
"startTimeUtc": "2022-05-25T12:03:36.3082211Z",
"durationInMs": 1.3324
},
{
"event": "Received",
"startTimeUtc": "2022-05-25T12:03:36.3095535Z",
"durationInMs": 12.6128
},
{
"event": "Completed",
"startTimeUtc": "2022-05-25T12:03:36.8621663Z",
"durationInMs": 0
}
],
"serviceEndpointStats": {
"inflightRequests": 1,
"openConnections": 1
},
"connectionStats": {
"waitforConnectionInit": "False",
"callsPendingReceive": 0,
"lastSendAttempt": "2022-05-25T12:03:34.0222760Z",
"lastSend": "2022-05-25T12:03:34.0223280Z",
"lastReceive": "2022-05-25T12:03:34.0257728Z"
},
"requestSizeInBytes": 447,
"responseMetadataSizeInBytes": 438,
"responseBodySizeInBytes": 604
},
"TransportException": null
}
معدل الفشل ينتهك Azure Cosmos DB SLA
اتصل بالدعم Azure .
الخطوات التالية
- تشخيص واستكشاف مشاكل وإصلاحها عند استخدامك قاعدة بيانات Azure Cosmos .NET لعدة الخاصة بتطوير البرامج.
- تعرف على إرشادات الأداء الخاصة بـ .NET SDK.
- تعرف على أفضل الممارسات الخاصة بـ .NET SDK