نصائح حول أداء Azure Cosmos DB والإصدار 2 من .NET SDK

ينطبق على: NoSQL

Azure Cosmos DB هي قاعدة بيانات موزعة سريعة ومرنة تتوسع بسلاسة مع زمن انتقال ومعدل انتقال مضمونين. لا يتعين عليك إجراء تغييرات هيكلية كبيرة أو كتابة تعليمات برمجية معقدة لتوسيع نطاق قاعدة البيانات باستخدام Azure Cosmos DB. يُعد توسيع النطاق وتقليصه أمراً سهلاً مثل استدعاء واجهة برمجة التطبيقات للنظام. لمعرفة مزيد، راجع كيفية توفير معدل نقل الحاوية أو كيفية توفير معدل نقل قاعدة البيانات. لكن نظراً لإمكانية الوصول إلى Azure Cosmos DB عبر استدعاءات الشبكة، يمكن إجراء تحسينات من جانب العميل لتحقيق أعلى أداء عند استخدام SQL .NET SDK.

لذلك، إذا كنت تحاول تحسين أداء قاعدة البيانات، ففكر في الخيارات التالية:

الترقية إلى .NET SDK الإصدار 3

تم إصدار .NET SDK الإصدار 3. إذا كنت تستخدم الإصدار 3 من .NET SDK، فراجع دليل أداء الإصدار 3 من .NET SDK للحصول على المعلومات التالية:

  • الإعدادات الافتراضية لوضع TCP المباشر
  • تندفق دعم واجهة برمجة التطبيقات
  • دعم المتسلسل المخصص للسماح باستخدام System.Text.JSON
  • دعم الدفعات والمجموعات المتكامل

توصيات الاستضافة

تشغيل خدمة تجميع البيانات المهملة من جانب الخادم (GC)

يمكن أن يساعد تقليل وتيرة تجميع البيانات المهملة في بعض الحالات. في .NET، عيِّن gcServer على true.

توسيع نطاق أعباء عمل العميل

إذا كنت تختبر بمستويات معدل نقل عالية (أكثر من 50000 وحدة طلب/ثانية)، فقد يصبح تطبيق العميل مزدحماً؛ نظراً لأن الجهاز يحد من استخدام وحدة المعالجة المركزية أو الشبكة. إذا وصلت إلى هذه النقطة، يمكنك الاستمرار في دفع حساب Azure Cosmos DB بشكل أكبر عن طريق توسيع نطاق تطبيقات العميل عبر خوادم متعددة.

إشعار

يمكن أن يؤدي الاستخدام العالي لوحدة المعالجة المركزية إلى زيادة زمن الانتقال وطلب استثناءات للمهلة.

عمليات بيانات التعريف

لا تتحقق من وجود قاعدة بيانات و/أو مجموعة عن طريق استدعاء Create...IfNotExistsAsync و/أو Read...Async في المسار السريع و/أو قبل إجراء عملية عنصر. يجب أن يتم التحقق فقط عند بدء تشغيل التطبيق عندما يكون ذلك ضرورياً، إذا كنت تتوقع حذفها (وإلا فلن تكون هناك حاجة). ستؤدي عمليات بيانات التعريف هذه إلى إنشاء زمن انتقال إضافي من طرف إلى طرف، وليس له اتفاقية مستوى خدمة (SLA)، وقيوده المنفصلة التي لا تتناسب مع عمليات البيانات.

التسجيل والتتبع.

تحتوي بعض البيئات على .NET DefaultTraceListener ممكن. يطرح DefaultTraceListener مشكلات الأداء على بيئات التشغيل ما يسبب ازدحامات عالية في CPU والإدخال/إخراج. تحقق من تعطيل DefaultTraceListener في تطبيقك وتأكد من ذلك عن طريق إزالته من TraceListeners على بيئات التشغيل.

تزيله أحدث إصدارات SDK (أكبر من 2.16.2) تلقائياً عند اكتشافه، أمّا في الإصدارات القديمة، يمكنك إزالته عن طريق:

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
}

الشبكات

نهج الاتصال: استخدم وضع الاتصال المباشر

وضع الاتصال الافتراضي للإصدار 2 من .NET SDK عبر البوابة. يمكنك تكوين وضع الاتصال في أثناء إنشاء مثيل DocumentClient باستخدام المعلمة ConnectionPolicy. إذا كنت تستخدم الوضع المباشر، فأنت بحاجة أيضاً إلى تعيين Protocolباستخدام المعلمة ConnectionPolicy. لمعرفة مزيد حول خيارات الاتصال المختلفة، راجع مقالة أوضاع الاتصال.

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
});

استنفاد المنفذ المؤقت

في حالة ملاحظة ارتفاع حجم اتصال أو استخدام منفذ في مثيلاتك، تأكد أولاً من أن مثيلات عميلك هي قاعدة بيانات أحادية. بمعنى آخر، يجب أن تكون مثيلات العميل فريدة طوال مدة بقاء التطبيق.

عند التشغيل على بروتوكول TCP، يحسِّن العميل زمن الانتقال باستخدام الاتصالات طويلة الأمد، بدلاً من بروتوكول HTTPS، الذي يُنهي الاتصالات بعد دقيقتَيْن من عدم النشاط.

في السيناريوهات التي تتضمن إمكانية وصول ضئيلة، وإذا لاحظت ارتفاع عدد الاتصالات مقارنة بالوصول إلى وضع البوابة، يمكنك:

  • كوِّن الخاصية ConnectionPolicy.PortReuseMode إلى PrivatePortPool (فعّال مع إصدار إطار العمل>= 4.6.1 والإصدار الأساسي لـ .NET >‏= 2.0): تسمح هذه الخاصية لـ SDK باستخدام تجمع صغير من المنافذ المؤقتة لمجموعة مختلفة من نقاط نهاية وجهة Azure Cosmos DB.
  • يجب أن يكون تكوين خاصية ConnectionPolicy.IdleConnectionTimeout أكبر من 10 دقائق أو مساوياً لها. تتراوح القيم الموصى بها بين 20 دقيقة و24 ساعة.

استدعِ OpenAsync لتجنب وجود زمن انتقال بدء التشغيل عند الطلب الأول

يكون زمن انتقال الطلب الأول أعلى افتراضياً؛ لأنه يحتاج إلى جلب جدول توجيه العنوان. عند استخدام الإصدار 2 من SDK، استدعِ OpenAsync() مرة واحدة في أثناء التكوين لتجنب وجود زمن انتقال بدء التشغيل في الطلب الأول. يشبه الاستدعاء ما يلي: await client.OpenAsync();

إشعار

سيُنشئ OpenAsync طلبات للحصول على جدول توجيه العناوين لجميع الحاويات في الحساب. بالنسبة للحسابات التي تحتوي على كثير من الحاويات، ولكن تطبيقها يصل إلى مجموعة فرعية منها، فإن OpenAsync سينشئ مقداراً غير ضروري من نسبة استخدام الشبكة، وهو ما يجعل عملية التهيئة بطيئة. لذلك قد لا يكون استخدام OpenAsync مفيداً في هذا السيناريو؛ لأنه يبطئ بدء تشغيل التطبيق.

للحصول على أداء مميز، رتِّب العملاء في منطقة Azure نفسها

ضع أي تطبيقات تستدعي Azure Cosmos DB في المنطقة نفسها الموجودة بها قاعدة بيانات Azure Cosmos DB إن أمكن. فيما يلي مقارنة تقريبية: تكتمل استدعاءات Azure Cosmos DB في داخل المنطقة نفسها في غضون مدة من 1 مللي ثانية إلى 2 مللي ثانية، لكن زمن الانتقال بين الساحل الغربي والشرقي للولايات المتحدة يزيد على 50 مللي ثانية. يمكن أن يختلف وقت الاستجابة هذا من طلب إلى آخر، اعتماداً على المسار الذي يسلكه الطلب أثناء انتقاله من العميل إلى حد مركز بيانات Azure. يمكنك الحصول على أقل زمن انتقال ممكن عن طريق التأكد من وجود تطبيق الاستدعاء في داخل منطقة Azure نفسها التي توجد فيها نقطة نهاية Azure Cosmos DB المتوفرة. للحصول على قائمة بالمناطق المتوفرة، راجع مناطق Azure.

نهج اتصال Azure Cosmos DB

زيادة عدد مؤشرات الترابط/المهام

نظراً لإجراء استدعاءات Azure Cosmos DB عبر الشبكة، فقد تحتاج إلى تغيير درجة التوازي لطلباتك، بحيث ينتظر تطبيق العميل بين الطلبات أدنى مدة ممكنة. على سبيل المثال، إذا كنت تستخدم .NET Task Parallel Library، فأنشئ مئات المهام التي تُقرأ من Azure Cosmos DB أو تُكتب فيه.

تمكين تسريع الشبكات

لتقليل زمن الانتقال وتوتر وحدة المعالجة المركزية، نوصي بتمكين تسريع الشبكة على الأجهزة الظاهرية للعميل. راجع إنشاء جهاز ظاهري يعمل بنظام التشغيل Windows باستخدام تسارع الشبكة أو إنشاء جهاز ظاهري يعمل بنظام Linux باستخدام تسارع الشبكة.

استخدام SDK

تثبيت أحدث إصدار من SDK

يتم تحسين حزم Azure Cosmos DB SDK باستمرار لتوفير أفضل أداء. راجع صفحات أداة SDK لـ Azure Cosmos DB لتحديد أحدث إصدار من SDK ومراجعة التحسينات.

استخدم عميل قاعدة بيانات أحادية Azure Cosmos DB طوال عمر تطبيقك

كل مثيل DocumentClient هو مؤشر ترابط آمن ويجري إدارة فعالة للاتصال وتخزيناً مؤقتاً للعنوان عند التشغيل في الوضع المباشر. للسماح بإدارة اتصال فعّالة وأداء أفضل لعميل SDK، نوصي باستخدام مثيل واحد لكل AppDomain طوال مدة بقاء التطبيق.

تجنب الاستدعاءات المحظورة

يجب تصميم Azure Cosmos DB SDK لمعالجة العديد من الطلبات في وقت واحد. تسمح واجهات برمجة التطبيقات غير المتزامنة للتجمع الصغير لمؤشرات الترابط بمعالجة آلاف الطلبات المتزامنة من خلال عدم الانتظار في الاستدعاءات المحظورة. بدلاً من الانتظار لإكمال مهمة متزامنة طويلة الأمد، يمكن أن يعمل مؤشر الترابط على طلب آخر.

هناك مشكلة شائعة في الأداء في التطبيقات التي تستخدم Azure Cosmos DB SDK وهي حظر المكالمات التي قد تكون غير متزامنة. تؤدي كثير من الاستدعاءات المحظورة المتزامن إلى نقص تجمع مؤشرات الترابط وانخفاض وقت الاستجابة.

لا تنفِّذ ما يلي:

  • منع التنفيذ غير المتزامن من خلال استدعاء Task.Wait أو Task.Result.
  • استخدام Task.Run لمنع تزامن واجهة برمجة التطبيقات المتزامنة.
  • احصل على تأمين في مسارات التعليمات البرمجية الشائعة. Azure Cosmos DB .NET SDK هو الأكثر أداء عند تصميمه لتشغيل التعليمات البرمجية بالتوازي.
  • استدعِ Task.Run وانتظرها على الفور. يقوم ASP.NET Core بالفعل بتشغيل تعليمات برمجية للتطبيق على مؤشرات ترابط تجمع مؤشرات الترابط العادية، لذا فإن استدعاء Task.Run يؤدي فقط إلى جدولة Thread Pool إضافية غير ضرورية. حتى إذا كانت التعليمات البرمجية المجدولة تحظر أي مؤشر ترابط، فإن Task.Run لا يمنع ذلك.
  • استخدم ToList() DocumentClient.CreateDocumentQuery(...) الذي يستخدم استدعاءات الحظر لاستنزاف الاستعلام بشكل متزامن. استخدم AsDocumentQuery () لاستنزاف الاستعلام بشكل غير متزامن.

من المستحسن القيام بما يلي:

  • استدعاء واجهات برمجة تطبيقات Azure Cosmos DB .NET بشكل غير متزامن.
  • مكدس الاستدعاءات بأكمله غير متزامن للاستفادة من أنماط غير متزامن/الانتظار.

يمكن استخدام محلل ملفات التعريف، مثل PerfView، للعثور على مؤشرات الترابط التي تُضاف بشكل متكرر إلى تجمع مؤشرات الترابط. يشير الحدث Microsoft-Windows-DotNETRuntime/ThreadPoolWorkerThread/Start إلى مؤشر ترابط مُضاف إلى تجمع مؤشرات الترابط.

زيادة System.Net MaxConnections لكل مضيف عند استخدام وضع البوابة

تُجرى طلبات Azure Cosmos DB عبر HTTPS/REST عند استخدام وضع البوابة. تلتزم بحد الاتصال الافتراضي لكل اسم مضيف، أو عنوان IP. قد تحتاج إلى تعيين MaxConnections على قيمة أعلى (من 100 إلى 1000) حتى تتمكن مكتبة العميل من استخدام اتصالات متزامنة متعددة مع Azure Cosmos DB. في الإصدار 1.8.0 من .NET SDK والإصدارات الأحدث، تكون القيمة الافتراضية لـ ServicePointManager.DefaultConnectionLimit‏ 50. لتغيير القيمة، يمكنك تعيين Documents.Client.ConnectionPolicy.MaxConnectionLimit إلى قيمة أعلى.

تنفيذ التراجع على فترات RetryAfter

في أثناء اختبار الأداء، يجب زيادة الحمل إلى أن يتم تقييد معدل قليل من الطلبات. في حالة تقييد الطلبات، يجب أن يتراجع تطبيق العميل عند التقييد لمدة الفترة الزمنية المقدرة لإعادة المحاولة المحدد من قِبَل الخادم. يضمن الالتزام بعملية التراجع الانتظار بين عمليات إعادة المحاولة لأقل وقت ممكن.

أُدرِج دعم سياسة إعادة المحاولة في أدوات SDK هذه:

لمزيد من المعلومات، راجع RetryAfter.

في الإصدار 1.19 والإصدارات الأحدث من .NET SDK، توجد آلية لتسجيل المعلومات التشخيصية الإضافية واستكشاف مشكلات زمن الانتقال وإصلاحها كما هو موضح في النموذج التالي. يمكنك تسجيل سلسلة التشخيص للطلبات ذات زمن انتقال أعلى للقراءة. ستساعدك سلسلة التشخيص المُوفَرة في معرفة عدد المرات التي تلقيت فيها خطأ 429 لطلب معيَّن.

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

التخزين المؤقت لعناوين URI للمستندات لزمن انتقال أقل للقراءة

خزِّن عناوين URL للمستندات مؤقتاً إن أمكن للحصول على أفضل أداء للقراءة. تحتاج إلى تعريف المنطق للتخزين المؤقت لمعرف المورد عند إنشاء مورد. تكون عمليات البحث المستندة إلى معرِّفات الموارد أسرع من عمليات البحث المستندة إلى الاسم؛ لذا فإن التخزين المؤقت لهذه القيم يحسن الأداء.

زيادة عدد مؤشرات الترابط/المهام

راجع زيادة عدد مؤشرات الترابط/المهام في قسم الشبكات في هذه المقالة.

عمليات الاستعلام

لعمليات الاستعلام، راجع نصائح أداء الاستعلامات.

سياسة الفهرسة

استبعاد المسارات غير المستخدمة من الفهرسة لعمليات كتابة أسرع

يسمح لك نهج الفهرسة Azure Cosmos DB أيضاً بتحديد مسارات المستندات المراد تضمينها أو استبعادها من الفهرسة باستخدام مسارات الفهرسة (IndexingPolicy.IncludedPaths and IndexingPolicy.ExcludedPaths). يمكن أن تحسِّن مسارات الفهرسة أداء الكتابة وتقلِّل تخزين الفهرس للسيناريوهات التي تُعرف فيها أنماط الاستعلام سابقاً. وذلك لأن تكاليف الفهرسة ترتبط مباشرة بعدد المسارات الفريدة المفهرسة. على سبيل المثال، يوضح هذا الرمز كيفية استبعاد قسم كامل من المستندات (شجرة فرعية) من الفهرسة باستخدام حرف البدل "*":

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);

للحصول على مزيد من المعلومات، راجع خدمة Azure Cosmos DB: نهج الفهرسة.

الإنتاجية

القياس والضبط لأقل وحدات طلب/الثانية

تقدم Azure Cosmos DB مجموعة كبيرة من عمليات قاعدة البيانات. تتضمن هذه العمليات استعلامات بشأن العلاقات والتسلسلات الهرمية مع ملفات تنسيق القرص العالمي والإجراءات المخزنة والمشغلات، وجميعها يعمل على المستندات داخل مجموعة قاعدة بيانات. تختلف التكلفة المرتبطة بكل من هذه العمليات اعتماداً على CPU وIO والذاكرة المطلوبة لإكمال العملية. بدلاً من التفكير في موارد الأجهزة وإدارتها، يمكنك التفكير في وحدة الطلب (RU) كمقياس واحد للموارد المطلوبة لتنفيذ عمليات قاعدة بيانات متنوعة وخدمة طلب تطبيق.

يتوفر معدل النقل بناءً على عدد وحدات الطلب المُعيَنة في كل حاوية. يُقيَم استهلاك وحدة الطلب كمعدل لكل الثانية. التطبيقات التي تتجاوز معدل وحدة الطلب المخصص لحاوياتها محدودة حتى ينخفض ​​المعدل إلى ما دون المستوى المخصص للحاوية. إذا كان تطبيقك يتطلب مستوى أعلى من الإنتاجية، فيمكنك زيادة الإنتاجية من خلال توفير وحدات طلب إضافية.

يؤثر تعقيد الاستعلام في عدد وحدات الطلب المستهلكة لعملية ما. يؤثر عدد دالات التقييم وطبيعتها وعدد UDF وحجم مجموعة البيانات المصدر في تكلفة عمليات الاستعلام.

لقياس النفقات العامة لأي عملية (إنشاء أو تحديث أو حذف)، افحص العنوان x-ms-request-charge (أو خاصية RequestCharge المكافئة في ResourceResponse\<T> أو FeedResponse\<T> في NET SDK) لقياس عدد وحدات الطلب التي تستهلكها العمليات:

// 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);
    }

إن رسوم الطلب التي تم إرجاعها في هذا العنوان جزء صغير من معدل النقل المخصص (أي 2000 وحدة طلب/ثانية). على سبيل المثال، إذا أنتج الاستعلام السابق 1000 مستند بحجم 1 كيلوبايت، فإن تكلفة العملية هي 1،000. لذلك، في غضون ثانية واحدة، ينفِّذ الخادم طلبَيْن فقط من هذا القبيل قبل أن يحدد معدل الطلبات اللاحقة. لمزيد من المعلومات، راجع وحدات الطلب وحاسبة وحدات الطلب.

تقييد معدل المعالجة/معدل الطلب كبير جدًّا

عندما يحاول أحد العملاء تجاوز معدل النقل المحجوز لحساب ما، لا يحدث انخفاض في الأداء على الخادم، ولا تُستخدَم سعة معدل نقل تتجاوز المستوى المحجوز. سينهي الخادم الطلب بشكل استباقي باستخدام RequestRateTooLarge (رمز حالة HTTP ‏429). سيعيد العنوان x-ms-retry-after-ms الذي يشير إلى مقدار الوقت بالملّي ثانية الذي يجب على المستخدم انتظاره قبل محاولة تنفيذ الطلب مرة أخرى.

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

تلتقط جميع حزم SDK هذه الاستجابة ضمنياً، وتحترم عنواناً بعد إعادة المحاولة المحدد من الخادم، ثم تعيد محاولة الطلب. ما لم يتم الوصول إلى حسابك بشكل متزامن من قبل عدة عملاء، فستنجح المحاولة التالية.

في حالة تجاوز أكثر من عميل واحد معدل الطلب على نحو تراكمي ومتسق، فقد لا يكفي عدد مرات إعادة المحاولة الافتراضي المعين حالياً على 9 داخلياً بواسطة العميل. في هذه الحالة، يدخل العميل DocumentClientException مع رمز الحالة 429 في التطبيق.

يمكنك تغيير عدد مرات إعادة المحاولة الافتراضي عن طريق تعيين RetryOptions على مثيل ConnectionPolicy. بشكل ظاهري يتم إرجاع DocumentClientException برمز الحالة 429 بعد وقت انتظار تراكمي قدره 30 ثانية، إذا استمر الطلب في العمل فوق معدل الطلب. ينتج هذا الخطأ حتى عندما يكون عدد عمليات إعادة المحاولة الحالية أقل من الحد الأقصى لعدد مرات إعادة المحاولة، سواء كانت القيمة الحالية هي القيمة الافتراضية المقدرة بـ 9 أو قيمة يحددها المستخدم.

تساعد طريقة عمل إعادة المحاولة التلقائية في تحسين مرونة معظم التطبيقات وسهولة استخدامها. ولكن قد لا يكون هذا هو السلوك الأفضل عند إجراء معايير الأداء، خاصةً عند قياس زمن الوصول. سوف يرتفع وقت الانتقال الذي يَلْحَظه العميل إذا وصلت التجربة إلى تقييد الخادم وتسببت في إعادة محاولة SDK للعميل بصمت. لتجنب ارتفاع وقت الانتقال أثناء تجارب الأداء، قم بقياس الرسوم التي يتم إرجاعها بواسطة كل عملية وتأكد من أن الطلبات تعمل بأقل من معدل الطلب المحجوز. لمزيد من المعلومات، راجع وحدات الطلب.

لمعدل نقل أعلى، صمم مستندات أصغر حجماً

ترتبط رسوم الطلب (أي تكلفة معالجة الطلب) لعملية معينة مباشرةً بحجم المستند. تكلِّف عمليات معالجة المستندات الكبيرة رسوماً أكثر من عمليات معالجة المستندات الصغيرة.

الخطوات التالية

للحصول على نموذج تطبيق يُستخدم لتقييم Azure Cosmos DB للسيناريوهات عالية الأداء على عدد قليل من أجهزة العميل، راجع اختبار الأداء والقياس باستخدام Azure Cosmos DB.

لمعرفة مزيد حول تصميم تطبيقك بحيث يتناسب مع الحجم والأداء العالي، راجع التقسيم والقياس في Azure Cosmos DB.