Share via


Aanbevolen procedures voor grootschalige IoT-apparaatimplementaties

Het kan lastig zijn om een IoT-oplossing te schalen naar miljoenen apparaten. Grootschalige oplossingen moeten vaak worden ontworpen in overeenstemming met service- en abonnementslimieten. Wanneer klanten Azure IoT Device Provisioning Service gebruiken, gebruiken ze deze in combinatie met andere Azure IoT-platformservices en -onderdelen, zoals IoT Hub en Azure IoT-apparaat-SDK's. In dit artikel worden aanbevolen procedures, patronen en voorbeeldcode beschreven die u in uw ontwerp kunt opnemen om te profiteren van deze services en uw implementaties uit te schalen. Door deze patronen en procedures te volgen vanaf de ontwerpfase van het project, kunt u de prestaties van uw IoT-apparaten maximaliseren.

Nieuwe apparaten inrichten

Eerste keer inrichten is het proces van onboarding van een apparaat voor de eerste keer als onderdeel van een IoT-oplossing. Wanneer u met grootschalige implementaties werkt, is het belangrijk om het inrichtingsproces te plannen om overbelastingssituaties te voorkomen die worden veroorzaakt door alle apparaten die tegelijkertijd verbinding proberen te maken.

Een gefaseerd inrichtingsschema gebruiken

Voor de implementatie van apparaten op de schaal van miljoenen kan het registreren van alle apparaten in één keer ertoe leiden dat het DPS-exemplaar wordt overspoeld vanwege beperking (HTTP-antwoordcode 429, Too Many Requests) en een fout bij het registreren van uw apparaten. Als u dergelijke beperking wilt voorkomen, gebruikt u een verspringend registratieschema voor de apparaten. Configureer de batchgrootten voor apparaatregistratie in overeenstemming met DPS-quota en -limieten. Als de registratiesnelheid bijvoorbeeld 200 apparaten per minuut is, is de batchgrootte voor onboarding 200 apparaten per batch.

Bewerkingen voor opnieuw proberen

Als tijdelijke fouten optreden omdat een service bezet is, kunnen apparaten met nieuwe logica verbinding maken met de IoT-cloud. Een groot aantal nieuwe pogingen kan echter een drukke service die dicht bij of bij de capaciteit wordt uitgevoerd, verder verminderen. Net als bij elke Azure-service moet u een intelligent mechanisme voor opnieuw proberen implementeren met exponentieel uitstel. Meer informatie over verschillende patronen voor opnieuw proberen vindt u in het ontwerppatroon voor opnieuw proberen en tijdelijke foutafhandeling.

In plaats van een implementatie onmiddellijk opnieuw uit te voeren wanneer deze wordt beperkt, wacht u tot de tijd die is opgegeven in de retry-after header. Als er geen header voor opnieuw proberen beschikbaar is vanuit de service, kan dit algoritme helpen een soepelere onboarding-ervaring voor apparaten te realiseren:

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

Met deze logica vertragen apparaten opnieuw verbinding maken voor een willekeurige hoeveelheid tijd, tussen min_retry_delay_msec en max_retry_delay_msec. De maximale vertraging voor opnieuw proberen wordt berekend met de volgende variabelen:

  • <load> is een configureerbare factor met waarden > 0, wat aangeeft dat de belasting wordt uitgevoerd met een gemiddelde laadtijd vermenigvuldigd met het aantal verbindingen per seconde
  • <T> is de absolute minimale tijd voor het koud opstarten van de apparaten (berekend als T = N / cps waar N het totale aantal apparaten is en cps is de servicelimiet voor het aantal verbindingen per seconde).

Zie Timing voor opnieuw proberen voor meer informatie over de timing van bewerkingen voor opnieuw proberen.

Apparaten opnieuw inrichten

Opnieuw inrichten is het proces waarbij een apparaat moet worden ingericht voor een IoT Hub nadat het eerder is verbonden. Er kunnen veel redenen zijn waardoor een apparaat opnieuw verbinding moet maken met een IoT Hub, zoals:

  • Een apparaat kan opnieuw worden opgestart vanwege stroomstoringen, verlies van netwerkconnectiviteit, geo-herlocatie, firmware-updates, fabrieksinstellingen terugzetten of rotatie van certificaatsleutels.
  • Het IoT Hub-exemplaar is mogelijk niet beschikbaar vanwege een niet-geplande IoT Hub-storing.

U hoeft het inrichtingsproces niet telkens te doorlopen wanneer een apparaat opnieuw wordt opgestart. De meeste apparaten die opnieuw worden geprovisioneerd, worden verbonden met dezelfde IoT-hub. In plaats daarvan moet een apparaat proberen rechtstreeks verbinding te maken met de IoT-hub met behulp van de informatie die is opgeslagen in de cache van een eerdere geslaagde verbinding.

Apparaten die een verbindingsreeks kunnen opslaan

Apparaten met de mogelijkheid om hun verbindingsreeks op te slaan na de eerste inrichting, moeten dit doen en proberen om na het opnieuw opstarten rechtstreeks verbinding te maken met IoT Hub. Dit patroon vermindert de latentie bij het maken van verbinding met de juiste IoT Hub. Er zijn hier twee mogelijke gevallen:

  • De IoT Hub om verbinding te maken bij het opnieuw opstarten van het apparaat is hetzelfde als de eerder verbonden IoT Hub.

    Het verbindingsreeks dat uit de cache is opgehaald, werkt prima en het apparaat kan opnieuw verbinding maken met hetzelfde eindpunt. U hoeft geen nieuwe start te maken voor het inrichtingsproces.

  • De IoT Hub om verbinding te maken bij het opnieuw opstarten van het apparaat verschilt van de eerder verbonden IoT Hub.

    De verbindingsreeks die in het geheugen zijn opgeslagen, is onjuist. Als u verbinding probeert te maken met hetzelfde eindpunt, lukt dit niet en wordt het mechanisme voor opnieuw proberen voor de IoT Hub-verbinding geactiveerd. Zodra de drempelwaarde voor de IoT Hub-verbindingsfout is bereikt, activeert het mechanisme voor opnieuw proberen automatisch een nieuwe start naar het inrichtingsproces.

Apparaten die geen verbindingsreeks kunnen opslaan

Sommige apparaten hebben niet een grote footprint of geheugen voor het opslaan van de verbindingsreeks vanaf een geslaagde IoT Hub-verbinding. Deze apparaten moeten na het opnieuw opstarten opnieuw inrichten via DPS. Gebruik de DPS-registratie-API om u opnieuw te registreren. Houd er rekening mee dat het aantal nieuwe registraties per minuut beperkt is op basis van de limiet voor dps-apparaatregistratie.

Voorbeeld van opnieuw inrichten

In de codevoorbeelden in deze sectie ziet u een klasse voor het lezen naar en schrijven vanuit de apparaatcache, gevolgd door code die probeert een apparaat opnieuw te verbinden met de IoT Hub als er een verbindingsreeks wordt gevonden en opnieuw wordt geïmplementeerd via DPS als dat niet zo is.

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

U kunt code gebruiken die vergelijkbaar is met de volgende code om te bepalen hoe u doorgaat met het opnieuw verbinden van een apparaat nadat u hebt vastgesteld of er verbindingsgegevens in de cache zijn:

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

Overwegingen voor IoT Hub-connectiviteit

Eén IoT-hub is beperkt tot 1 miljoen apparaten plus modules. Als u van plan bent meer dan een miljoen apparaten te hebben, kunt u het aantal apparaten beperken tot 1 miljoen per hub en waar nodig hubs toevoegen wanneer u de schaal van uw implementatie verhoogt. Zie IoT Hub-quota voor meer informatie. Als u plannen hebt voor meer dan een miljoen apparaten en u deze moet ondersteunen in een specifieke regio (zoals in een EU-regio voor vereisten voor gegevenslocatie), kunt u contact met ons opnemen om ervoor te zorgen dat de regio waarin u implementeert de capaciteit heeft om uw huidige en toekomstige schaal te ondersteunen.

Wanneer u via DPS verbinding maakt met IoT Hub, moeten apparaten de volgende logica gebruiken als reactie op foutcodes bij het verbinden:

  • Wanneer u een van de 500-reeks serverfoutreacties ontvangt, probeert u de verbinding opnieuw met behulp van referenties in de cache of de resultaten van een API-aanroep voor apparaatregistratiestatus.
  • Wanneer u een volledige registratie ontvangt 401, Unauthorized of 404, Not Found403, Forbidden uitvoert, voert u een volledige registratie uit door de DPS-registratie-API aan te roepen.

Apparaten moeten op elk gewenst moment kunnen reageren op een door de gebruiker geïnitieerde opdracht voor opnieuw inrichten.

Als apparaten worden losgekoppeld van IoT Hub, moeten apparaten gedurende 15-30 minuten opnieuw verbinding maken met dezelfde IoT Hub voordat ze teruggaan naar DPS.

Andere IoT Hub-scenario's bij het gebruik van DPS:

  • IoT Hub-failover: apparaten moeten blijven werken omdat verbindingsinformatie niet mag worden gewijzigd en logica aanwezig is om de verbinding opnieuw uit te voeren zodra de hub weer beschikbaar is.
  • Wijziging van IoT Hub: het toewijzen van apparaten aan een andere IoT Hub moet worden uitgevoerd met behulp van een aangepast toewijzingsbeleid.
  • IoT Hub-verbinding opnieuw proberen: gebruik geen agressieve strategie voor opnieuw proberen. Laat in plaats daarvan minstens een minuut voordat u het opnieuw probeert.
  • IoT Hub-partities: Als uw apparaatstrategie sterk leunt op telemetrie, moet het aantal apparaat-naar-cloud-partities worden verhoogd.

Apparaten bewaken

Een belangrijk onderdeel van de algehele implementatie is het bewaken van de end-to-end oplossing om ervoor te zorgen dat het systeem op de juiste wijze presteert. Er zijn verschillende manieren om de status van een service te bewaken voor grootschalige implementatie van IoT-apparaten. De volgende patronen hebben bewezen effectief te zijn bij het bewaken van de service:

  • Maak een toepassing om een query uit te voeren op elke inschrijvingsgroep op een DPS-exemplaar, het totale aantal apparaten op te halen dat is geregistreerd bij die groep en vervolgens de getallen uit verschillende inschrijvingsgroepen samen te voegen. Dit aantal biedt een exacte telling van de apparaten die momenteel zijn geregistreerd via DPS en kan worden gebruikt om de status van de service te bewaken.
  • Apparaatregistraties gedurende een specifieke periode bewaken. Bewaak bijvoorbeeld de registratietarieven voor een DPS-exemplaar gedurende de afgelopen vijf dagen. Houd er rekening mee dat deze benadering alleen een geschatte figuur biedt en ook wordt beperkt tot een periode.

Volgende stappen