معالجة الأحداث بلا خادم

Azure Cosmos DB
Azure Functions
Azure Monitor
Azure Pipelines
Azure Storage

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

بناء الأنظمة

رسم تخطيطي يوضح بنية مرجعية لمعالجة الأحداث بدون خادم باستخدام Azure Functions.

‏‏سير العمل‬

  • تصل الأحداث إلى مراكز الأحداث.
  • يتم تشغيل Function App للتعامل مع الحدث.
  • يتم تخزين الحدث في قاعدة بيانات Azure Cosmos DB.
  • إذا فشل تطبيق الوظيفة في تخزين الحدث بنجاح، فسيتم حفظ الحدث في قائمة انتظار التخزين لتتم معالجته لاحقاً.

المكونات

  • ُEvent Hubs تستوعب دفق البيانات. تم تصميم مراكز الأحداث لسيناريوهات تدفق البيانات ذات معدل النقل العالي.

    إشعار

    بالنسبة إلى سيناريوهات إنترنت الأشياء (IoT)، نوصي باستخدام Azure IoT Hub. يحتوي IoT Hub على نقطة نهاية مدمجة ومتوافقة مع واجهة برمجة تطبيقات Azure Event Hubs، بحيث يمكنك استخدام أي الخدمتين في هذه البنية دون تغييرات كبيرة في المعالجة الخلفية. لمزيد من المعلومات، راجع توصيل أجهزة إنترنت الأشياء بـ Azure: IoT Hub ومراكز الأحداث .

  • Function App. Azure Functions هي خيار حساب بلا خادم. يستخدم نموذجاً يحركه الحدث، حيث يتم استدعاء جزء من التعليمة البرمجية (وظيفة) بواسطة مشغل. في هذه البنية، عندما تصل الأحداث إلى مراكز الأحداث، فإنها تشغل وظيفة تعالج الأحداث وتكتب النتائج في التخزين.

    تعد Function Apps مناسبة لمعالجة السجلات الفردية من مراكز الأحداث. للحصول على سيناريوهات معالجة التدفق الأكثر تعقيداً، ضع في اعتبارك Apache Spark باستخدام Azure Databricks، أو Azure Stream Analytics.

  • قاعدة بيانات Azure Cosmos. Azure Cosmos DB هي خدمة قاعدة بيانات متعددة النماذج متاحة في وضع بلا خادم قائم على الاستهلاك. بالنسبة لهذا السيناريو، تخزن وظيفة معالجة الأحداث سجلات JSON، باستخدام Azure Cosmos DB ل NoSQL.

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

  • Azure Monitor. تجمع المراقبة قياسات الأداء حول خدمات Azure المنتشرة في الحل. من خلال تصورها في لوحة القيادة، يمكنك الحصول على رؤية لصحة الحل.

  • Azure Pipelines. التدفقات هي خدمة تكامل مستمر (CI) وتسليم مستمر (CD) تقوم بإنشاء التطبيق واختباره وتوزيعه.

الاعتبارات

تنفذ هذه الاعتبارات ركائز Azure Well-Architected Framework، وهو عبارة عن مجموعة من المبادئ التوجيهية التي يمكن استخدامها لتحسين جودة حمل العمل. لمزيد من المعلومات، يرجى مراجعةMicrosoft Azure Well-Architected Framework.

التوافر

يقع التوزيع الموضح هنا في منطقة Azure واحدة. للحصول على نهج أكثر مرونة للتعافي من الكوارث، استفد من ميزات التوزيع الجغرافي في الخدمات المختلفة:

  • مراكز الأحداث. أنشئ اثنتين من مساحات أسماء مراكز الأحداث، ومساحة اسم أساسية (نشطة) ومساحة اسم ثانوية (خاملة). يتم توجيه الرسائل تلقائياً إلى مساحة الاسم النشطة إلا إذا فشلت في مساحة الاسم الثانوية. لمزيد من المعلومات، راجع Azure Event Hubs استرداد البيانات من الكوارث الجغرافية.
  • Function App. وزع تطبيق وظيفة ثانٍ ينتظر القراءة من مساحة اسم مراكز الأحداث الثانوية. تكتب هذه الوظيفة إلى حساب تخزين ثانوي لقائمة انتظار الرسائل المهملة.
  • قاعدة بيانات Azure Cosmos. يدعم Azure Cosmos DB مناطق كتابة متعددة، ما يتيح عمليات الكتابة إلى أي منطقة تضيفها إلى حساب Azure Cosmos DB الخاص بك. إذا لم تقم بتمكين الكتابة المتعددة، فلا يزال بإمكانك الفشل في منطقة الكتابة الأساسية. تتعامل SDKs لعميل Azure Cosmos DB وروابط Azure Function تلقائيا مع تجاوز الفشل، لذلك لا تحتاج إلى تحديث أي إعدادات تكوين تطبيق.
  • Azure Storage. استخدم تخزين RA-GRS لقائمة انتظار الرسائل المهملة. يؤدي هذا إلى إنشاء نسخة متماثلة للقراءة فقط في منطقة أخرى. إذا أصبحت المنطقة الأساسية غير متوفرة، يمكنك قراءة العناصر الموجودة حالياً في قائمة الانتظار. بالإضافة إلى ذلك، قم بتوفير حساب تخزين آخر في المنطقة الثانوية التي يمكن للوظيفة الكتابة إليها بعد الفشل.

قابلية التوسع

مراكز الأحداث

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

يتدرج مشغل مراكز الأحداث في تطبيق الوظائف وفقا لعدد الأقسام في مركز الأحداث. يتم تعيين مثيل وظيفي واحد لكل قسم في كل مرة. لزيادة معدل النقل إلى أقصى حد، استقبل الأحداث دفعة واحدة، بدلاً من استقبال حدث واحد في كل مرة.

Azure Cosmos DB

يتوفر Azure Cosmos DB في وضعي سعة مختلفين:

  • بلا خادم، لأحمال العمل ذات نسبة استخدام شبكة متقطعة أو غير متوقعة وانخفاض نسبة استخدام الشبكة إلى الذروة.
  • معدل النقل المقدم، لأحمال العمل ذات نسبة استخدام شبكة مستمرة التي تتطلب أداءً يمكن التنبؤ به.

للتأكد من أن حمل العمل الخاص بك قابل للتطوير، من المهم اختيار مفتاح قسم مناسب عند إنشاء حاويات Azure Cosmos DB. فيما يلي بعض خصائص مفتاح القسم الجيد:

  • مساحة القيمة الرئيسية كبيرة.
  • سيكون هناك توزيع متساوٍ لعمليات القراءة/الكتابة لكل قيمة مفتاح، مع تجنب مفاتيح التشغيل السريع.
  • لن يتجاوز الحد الأقصى للبيانات المخزنة لأي قيمة مفتاح واحد الحد الأقصى لحجم القسم الفعلي (20 غيغابايت).
  • لن يتغير مفتاح القسم للمستند. لا يمكنك تحديث مفتاح القسم في مستند موجود.

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

مرونة

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

توضح التعليمة البرمجية التالية كيف تلتقط وظيفة الاستيعاب الاستثناءات وتضع الرسائل غير المعالجة في قائمة انتظار الرسائل المهملة.

 [Function(nameof(RawTelemetryFunction))]
 public async Task RunAsync([EventHubTrigger("%EventHubName%", Connection = "EventHubConnection")] EventData[] messages,
     FunctionContext context)
 {
     _telemetryClient.GetMetric("EventHubMessageBatchSize").TrackValue(messages.Length);
     DeviceState? deviceState = null;
     // Create a new CosmosClient
     var cosmosClient = new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTION_STRING"));

     // Get a reference to the database and the container
     var database = cosmosClient.GetDatabase(Environment.GetEnvironmentVariable("COSMOSDB_DATABASE_NAME"));
     var container = database.GetContainer(Environment.GetEnvironmentVariable("COSMOSDB_DATABASE_COL"));

     // Create a new QueueClient
     var queueClient = new QueueClient(Environment.GetEnvironmentVariable("DeadLetterStorage"), "deadletterqueue");
     await queueClient.CreateIfNotExistsAsync();

     foreach (var message in messages)
     {
         try
         {
             deviceState = _telemetryProcessor.Deserialize(message.Body.ToArray(), _logger);
             try
             {
                 // Add the device state to Cosmos DB
                 await container.UpsertItemAsync(deviceState, new PartitionKey(deviceState.DeviceId));
             }
             catch (Exception ex)
             {
                  _logger.LogError(ex, "Error saving on database", message.PartitionKey, message.SequenceNumber);
                 var deadLetterMessage = new DeadLetterMessage { Issue = ex.Message, MessageBody = message.Body.ToArray(), DeviceState = deviceState };
                 // Convert the dead letter message to a string
                 var deadLetterMessageString = JsonConvert.SerializeObject(deadLetterMessage);

                 // Send the message to the queue
                 await queueClient.SendMessageAsync(deadLetterMessageString);
             }

         }
         catch (Exception ex)
         {
             _logger.LogError(ex, "Error deserializing message", message.PartitionKey, message.SequenceNumber);
             var deadLetterMessage = new DeadLetterMessage { Issue = ex.Message, MessageBody = message.Body.ToArray(), DeviceState = deviceState };
             // Convert the dead letter message to a string
             var deadLetterMessageString = JsonConvert.SerializeObject(deadLetterMessage);

             // Send the message to the queue
             await queueClient.SendMessageAsync(deadLetterMessageString);
         }
     }
 }

تسجل التعليمة البرمجية المعروضة أيضاً الاستثناءات لـ Application Insights. يمكنك استخدام مفتاح القسم ورقم التسلسل لربط الرسائل المهملة بالاستثناءات الموجودة في السجلات.

يجب أن تحتوي الرسائل الموجودة في قائمة انتظار الرسائل المهملة على معلومات كافية حتى تتمكن من فهم سياق الخطأ. في هذا المثال، DeadLetterMessage تحتوي الفئة على رسالة الاستثناء وبيانات نص الحدث الأصلي ورسالة الحدث التي تم إلغاء تسلسلها (إذا كانت متوفرة).

    public class DeadLetterMessage
    {
        public string? Issue { get; set; }
        public byte[]? MessageBody { get; set; }
        public DeviceState? DeviceState { get; set; }
    }

استخدم Azure Monitor لمراقبة مركز الأحداث. إذا رأيت أن هناك إدخالاً ولكن لا يوجد إخراج، فهذا يعني أن الرسائل لا تتم معالجتها. في هذه الحالة، انتقل إلى Log Analytics وابحث عن استثناءات أو أخطاء أخرى.

DevOps

استخدم البنية الأساسية كتعليمة برمجية (IaC) عندما يكون ذلك ممكناً. تدير IaC البنية الأساسية والتطبيق وموارد التخزين بأسلوب تعريفي مثل Azure Resource Manager. سيساعد ذلك في التنفيذ التلقائي للتوزيع باستخدام DevOps كحل للتكامل المستمر والتسليم المستمر (CI/CD). يجب إصدار القوالب وتضمينها كجزء من تدفق الإصدار.

عند إنشاء القوالب، جمِّع الموارد كطريقة لتنظيمها وعزلها لكل حمل عمل. من الطرق الشائعة للتفكير في حمل العمل تطبيق أحادي بلا خادم أو شبكة ظاهرية. الهدف من عزل حمل العمل هو ربط الموارد بفريق، حتى يتمكن فريق DevOps من إدارة جميع جوانب هذه الموارد بشكل مستقل وتنفيذ CI/CD.

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

التعافي من الكوارث

يقع التوزيع الموضح هنا في منطقة Azure واحدة. للحصول على نهج أكثر مرونة للتعافي من الكوارث، استفد من ميزات التوزيع الجغرافي في الخدمات المختلفة:

  • مراكز الأحداث. أنشئ اثنتين من مساحات أسماء مراكز الأحداث، ومساحة اسم أساسية (نشطة) ومساحة اسم ثانوية (خاملة). يتم توجيه الرسائل تلقائياً إلى مساحة الاسم النشطة إلا إذا فشلت في مساحة الاسم الثانوية. لمزيد من المعلومات، راجع Azure Event Hubs استرداد البيانات من الكوارث الجغرافية.

  • Function App. وزع تطبيق وظيفة ثانٍ ينتظر القراءة من مساحة اسم مراكز الأحداث الثانوية. تكتب هذه الوظيفة إلى حساب تخزين ثانوي لقائمة انتظار الرسائل المهملة.

  • قاعدة بيانات Azure Cosmos. يدعم Azure Cosmos DB مناطق كتابة متعددة، ما يتيح عمليات الكتابة إلى أي منطقة تضيفها إلى حساب Azure Cosmos DB الخاص بك. إذا لم تقم بتمكين الكتابة المتعددة، فلا يزال بإمكانك الفشل في منطقة الكتابة الأساسية. تتعامل SDKs لعميل Azure Cosmos DB وروابط Azure Function تلقائيا مع تجاوز الفشل، لذلك لا تحتاج إلى تحديث أي إعدادات تكوين تطبيق.

  • Azure Storage. استخدم تخزين RA-GRS لقائمة انتظار الرسائل المهملة. يؤدي هذا إلى إنشاء نسخة متماثلة للقراءة فقط في منطقة أخرى. إذا أصبحت المنطقة الأساسية غير متوفرة، يمكنك قراءة العناصر الموجودة حالياً في قائمة الانتظار. بالإضافة إلى ذلك، قم بتوفير حساب تخزين آخر في المنطقة الثانوية التي يمكن للوظيفة الكتابة إليها بعد الفشل.

تحسين التكلفة

يركز تحسين التكلفة على البحث عن طرق للحد من النفقات غير الضرورية وتحسين الكفاءة التشغيلية. لمزيد من المعلومات، راجع نظرة عامة على ركيزة تحسين التكلفة.

استخدم حاسبة Azure Pricing لتقدير التكاليف. فيما يلي بعض الاعتبارات الأخرى ل Azure Functions وAzure Cosmos DB.

دالات Azure

تدعم Azure Functions نموذجين للاستضافة:

  • خطة الاستهلاك. يتم تخصيص قوة الحساب تلقائياً عند تشغيل التعليمة البرمجية الخاصة بك.
  • خطة خدمة التطبيق. تم تخصيص مجموعة من الأجهزة الظاهرية (VMs) للتعليمة البرمجية الخاصة بك. تحدد خطة App Service عدد الأجهزة الظاهرية وحجم الجهاز الظاهري.

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

Azure Cosmos DB

باستخدام Azure Cosmos DB، تدفع مقابل العمليات التي تجريها قاعدة البيانات والتخزين الذي تستهلكه بياناتك.

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

في هذه البنية المرجعية، تخزن الوظيفة مستنداً واحداً بالضبط لكل جهاز يرسل البيانات. تعمل الوظيفة باستمرار على تحديث المستندات بأحدث حالة للجهاز، باستخدام عملية upsert، والتي تعد فعالة من حيث التكلفة لمساحة التخزين المستهلكة. لمزيد من المعلومات، راجع نموذج تسعير Azure Cosmos DB.

استخدم حاسبة سعة Azure Cosmos DB للحصول على تقدير سريع لتكلفة حمل العمل.

نشر هذا السيناريو

شعار GitHub يتوفر تنفيذ مرجعي لهذه البنية على GitHub.

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