أفضل الممارسات لعمليات توزيع أجهزة إنترنت الأشياء على نطاق واسع

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

توفير أجهزة جديدة

التزويد لأول مرة هو عملية إلحاق جهاز لأول مرة كجزء من حل IoT. عند العمل مع عمليات النشر واسعة النطاق، من المهم جدولة عملية التزويد لتجنب حالات التحميل الزائد التي تسببها جميع الأجهزة التي تحاول الاتصال في نفس الوقت.

استخدام جدول توفير متدرج

لنشر الأجهزة على نطاق الملايين، قد يؤدي تسجيل جميع الأجهزة في وقت واحد إلى إرباك مثيل DPS بسبب التقييد (رمز 429, Too Many Requestsاستجابة HTTP) والفشل في تسجيل أجهزتك. لمنع مثل هذا التقييد، استخدم جدول تسجيل مرحلي للأجهزة. قم بتكوين أحجام دفعات تسجيل الجهاز وفقا لحصص وحدود DPS. على سبيل المثال، إذا كان معدل التسجيل 200 جهاز في الدقيقة، فسيكون حجم الدفعة للإلحاق 200 جهاز لكل دفعة.

عمليات إعادة المحاولة

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

بدلا من إعادة محاولة التوزيع على الفور عند تقييده، انتظر حتى الوقت المحدد في retry-after العنوان. إذا لم يكن هناك عنوان إعادة محاولة متوفر من الخدمة، يمكن أن تساعد هذه الخوارزمية في تحقيق تجربة إلحاق جهاز أكثر سلاسة:

min_retry_delay_msec = 1000
max_retry_delay_msec = (1.0 / <load>) * <T> * 1000
max_random_jitter_msec = max_retry_delay_msec

مع هذا المنطق، تؤخر الأجهزة إعادة الاتصال لفترة عشوائية من الوقت، بين min_retry_delay_msec و max_retry_delay_msec. يتم حساب الحد الأقصى لتأخير إعادة المحاولة بالمتغيرات التالية:

  • <load> هو عامل قابل للتكوين بقيم > 0، مما يشير إلى أن التحميل سيتم تنفيذه في متوسط وقت التحميل مضروبا في عدد الاتصالات في الثانية
  • <T> هو الحد الأدنى المطلق للوقت للتمهيد البارد للأجهزة (يتم حسابه حيث T = N / cps N يكون العدد الإجمالي للأجهزة وهو cps حد الخدمة لعدد الاتصالات في الثانية).

لمزيد من المعلومات حول توقيت عمليات إعادة المحاولة، راجع توقيت إعادة المحاولة.

إعادة توفير الأجهزة

إعادة التوفير هي العملية التي يحتاج فيها الجهاز إلى توفيره إلى IoT Hub بعد الاتصال بنجاح مسبقا. يمكن أن يكون هناك العديد من الأسباب التي تؤدي إلى الحاجة إلى جهاز لإعادة الاتصال بمركز IoT، مثل:

  • يمكن إعادة تشغيل الجهاز بسبب انقطاع التيار الكهربائي أو فقدان الاتصال بالشبكة أو النقل الجغرافي أو تحديثات البرامج الثابتة أو إعادة تعيين المصنع أو تدوير مفتاح الشهادة.
  • قد يكون مثيل IoT Hub غير متوفر بسبب انقطاع IoT Hub غير المخطط له.

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

الأجهزة التي يمكنها تخزين سلسلة الاتصال

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

  • مركز IoT للاتصال عند إعادة تشغيل الجهاز هو نفسه IoT Hub المتصل سابقا.

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

  • يختلف IoT Hub للاتصال عند إعادة تشغيل الجهاز عن IoT Hub المتصل مسبقا.

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

الأجهزة التي لا يمكنها تخزين سلسلة الاتصال

لا تحتوي بعض الأجهزة على بصمة أو ذاكرة كبيرة بما يكفي لاستيعاب التخزين المؤقت سلسلة الاتصال من اتصال IoT Hub ناجح سابق. تحتاج هذه الأجهزة إلى إعادة التزويد من خلال DPS بعد إعادة التشغيل. استخدم واجهة برمجة تطبيقات تسجيل DPS لإعادة التسجيل. ضع في اعتبارك أن عدد عمليات إعادة التسجيل في الدقيقة محدودة استنادا إلى حد تسجيل جهاز DPS.

عينة إعادة التزويد

تظهر أمثلة التعليمات البرمجية في هذا القسم فئة للقراءة والكتابة من ذاكرة التخزين المؤقت للجهاز، متبوعة بالتعليمات البرمجية التي تحاول إعادة توصيل جهاز بمركز IoT إذا تم العثور على سلسلة الاتصال وإعادة توفيره من خلال DPS إذا لم يكن كذلك.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ProvisioningCache
{
  public class ProvisioningDetailsFileStorage : IProvisioningDetailCache
  {
    private string dataDirectory = null;

    public ProvisioningDetailsFileStorage()
    {
      dataDirectory = Environment.GetEnvironmentVariable("ProvisioningDetailsDataDirectory");
    }

    public ProvisioningResponse GetProvisioningDetailResponseFromCache(string registrationId)
    {
      try
        {
          var provisioningResponseFile = File.ReadAllText(Path.Combine(dataDirectory, registrationId));

          ProvisioningResponse response = JsonConvert.DeserializeObject<ProvisioningResponse>(provisioningResponseFile);

          return response;
        }
      catch (Exception ex)
      {
        return null;
      }
    }

    public void SetProvisioningDetailResponse(string registrationId, ProvisioningResponse provisioningDetails)
    {
      var provisioningDetailsJson = JsonConvert.SerializeObject(provisioningDetails);

      File.WriteAllText(Path.Combine(dataDirectory, registrationId), provisioningDetailsJson);
    }
  }
}

يمكنك استخدام تعليمات برمجية مشابهة للآتي لتحديد كيفية متابعة إعادة توصيل جهاز بعد تحديد ما إذا كانت هناك معلومات اتصال في ذاكرة التخزين المؤقت:

IProvisioningDetailCache provisioningDetailCache = new ProvisioningDetailsFileStorage();

var provisioningDetails = provisioningDetailCache.GetProvisioningDetailResponseFromCache(registrationId);

// If no info is available in cache, go through DPS for provisioning
if(provisioningDetails == null)
{
  logger.LogInformation($"Initializing the device provisioning client...");
  using var transport = new ProvisioningTransportHandlerAmqp();
  ProvisioningDeviceClient provClient = ProvisioningDeviceClient.Create(dpsEndpoint, dpsScopeId, security, transport);
  logger.LogInformation($"Initialized for registration Id {security.GetRegistrationID()}.");
  logger.LogInformation("Registering with the device provisioning service... ");

  // This method will attempt to retry in case of a transient fault
  DeviceRegistrationResult result = await registerDevice(provClient);
  provisioningDetails = new ProvisioningResponse() { iotHubHostName = result.AssignedHub, deviceId = result.DeviceId };
  provisioningDetailCache.SetProvisioningDetailResponse(registrationId, provisioningDetails);
}

// If there was IoT Hub info from previous provisioning in the cache, try connecting to the IoT Hub directly
// If trying to connect to the IoT Hub returns status 429, make sure to retry operation honoring
//   the retry-after header
// If trying to connect to the IoT Hub returns a 500-series server error, have an exponential backoff with
//   at least 5 seconds of wait-time
// For all response codes 429 and 5xx, reprovision through DPS
// Ideally, you should also support a method to manually trigger provisioning on demand
if (provisioningDetails != null)
{
  logger.LogInformation($"Device {provisioningDetails.deviceId} registered to {provisioningDetails.iotHubHostName}.");
  logger.LogInformation("Creating TPM authentication for IoT Hub...");
  IAuthenticationMethod auth = new DeviceAuthenticationWithTpm(provisioningDetails.deviceId, security);
  logger.LogInformation($"Testing the provisioned device with IoT Hub...");
  DeviceClient iotClient = DeviceClient.Create(provisioningDetails.iotHubHostName, auth, TransportType.Amqp);
  logger.LogInformation($"Registering the Method Call back for Reprovisioning...");
  await iotClient.SetMethodHandlerAsync("Reprovision",reprovisionDirectMethodCallback, iotClient);

  // Now you should start a thread into this method and do your business while the DeviceClient is still connected
  await startBackgroundWork(iotClient);
  logger.LogInformation("Wait until closed...");

  // Wait until the app unloads or is cancelled
  var cts = new CancellationTokenSource();
  AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel();
  Console.CancelKeyPress += (sender, cpe) => cts.Cancel();

  await WhenCancelled(cts.Token);
  await iotClient.CloseAsync();
  Console.WriteLine("Finished.");
}

اعتبارات اتصال IoT Hub

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

عند الاتصال ب IoT Hub عبر DPS، يجب أن تستخدم الأجهزة المنطق التالي استجابة برموز الخطأ عند الاتصال:

  • عند تلقي أي من استجابات أخطاء الخادم المكونة من 500 سلسلة، أعد محاولة الاتصال باستخدام بيانات الاعتماد المخزنة مؤقتا أو نتائج استدعاء واجهة برمجة تطبيقات البحث عن حالة تسجيل الجهاز.
  • عند الاستلام 401, Unauthorized أو 403, Forbidden 404, Not Found، قم بإجراء إعادة تسجيل كاملة عن طريق استدعاء واجهة برمجة تطبيقات تسجيل DPS.

في أي وقت، يجب أن تكون الأجهزة قادرة على الاستجابة لأمر إعادة توفير بدأه المستخدم.

إذا تم قطع اتصال الأجهزة ب IoT Hub، يجب أن تحاول الأجهزة إعادة الاتصال مباشرة بنفس IoT Hub لمدة 15-30 دقيقة قبل محاولة العودة إلى DPS.

سيناريوهات مركز IoT الأخرى عند استخدام DPS:

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

مراقبة الأجهزة

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

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

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