Bewährte Methoden für umfangreiche IoT-Gerätebereitstellungen
Die Skalierung einer IoT-Lösung auf Millionen von Geräten kann schwierig sein. Große Lösungen müssen häufig gemäß Dienst- und Abonnementgrenzwerten entwickelt werden. Wenn Kunden den Azure IoT Device Provisioning Service nutzen, verwenden sie ihn in Kombination mit anderen Diensten und Komponenten der Azure IoT-Plattform, wie z. B. IoT Hub und Azure IoT-Geräte-SDKs. In diesem Artikel werden bewährte Methoden, Muster und Beispielcode beschrieben, die Sie in Ihr Design integrieren können, um diese Dienste zu nutzen und die Skalierung Ihrer Bereitstellungen zu ermöglichen. Indem Sie diese Muster und Methoden ab der Entwurfsphase des Projekts befolgen, können Sie die Leistung Ihrer IoT-Geräte maximieren.
Bereitstellen von neuen Geräten
Die erstmalige Bereitstellung ist der Prozess des erstmaligen Onboardings eines Geräts als Teil einer IoT-Lösung. Bei der Arbeit mit großen Bereitstellungen ist es wichtig, den Bereitstellungsprozess zu planen, um Überlastungssituationen zu vermeiden, die entstehen, weil alle Geräte verursachen, gleichzeitig eine Verbindung herzustellen.
Verwenden eines gestaffelten Bereitstellungszeitplans
Bei der Bereitstellung von Millionen von Geräten kann das gleichzeitige Registrieren aller Geräte dazu führen, dass die DPS-Instanz aufgrund von Drosselung (HTTP-Antwortcode 429, Too Many Requests
) überlastet ist und ein Fehler beim Registrieren Ihrer Geräte auftritt. Um eine solche Drosselung zu verhindern, verwenden Sie einen gestuften Registrierungsplan für die Geräte. Konfigurieren Sie die Batchgrößen für Ihre Geräteregistrierung gemäß DPS-Kontingenten und -Grenzwerten. Wenn die Registrierungsrate beispielsweise 200 Geräte pro Minute beträgt, würde die Batchgröße für das Onboarding 200 Geräte pro Batch betragen.
Operationen wiederholen
Wenn vorübergehende Fehler auftreten, da ein Dienst ausgelastet ist, ermöglicht eine Wiederholungslogik die erfolgreiche Verbindung mit der IoT-Cloud. Eine große Anzahl von Wiederholungsversuchen könnte jedoch einen stark ausgelasteten Dienst, der an seiner Kapazitätsgrenze angelangt ist, weiter beeinträchtigen. Wie bei jedem Azure-Dienst sollten Sie einen intelligenten Wiederholungsmechanismus mit exponentiellem Backoff implementieren. Weitere Informationen zu verschiedenen Wiederholungsmustern finden Sie unter Wiederholungsmuster und Behandeln vorübergehender Fehler.
Anstatt bei einer Drosselung eine Bereitstellung sofort erneut zu versuchen, warten Sie für die im retry-after
-Header angegebene Zeit. Wenn kein Wiederholungsheader vom Dienst verfügbar ist, kann dieser Algorithmus dazu beitragen, ein reibungsloseres Geräteonboarding zu erzielen:
min_retry_delay_msec = 1000
max_retry_delay_msec = (1.0 / <load>) * <T> * 1000
max_random_jitter_msec = max_retry_delay_msec
Mit dieser Logik verzögern Geräte eine erneute Verbindung für eine zufällige Zeit min_retry_delay_msec
zwischen und max_retry_delay_msec
. Die maximale Wiederholungsverzögerung wird mit den folgenden Variablen berechnet:
<load>
ist ein konfigurierbarer Faktor mit Werten > 0, was angibt, dass die Last mit einer durchschnittlichen Ladezeit multipliziert wird, die mit der Anzahl der Verbindungen pro Sekunde multipliziert wird.<T>
ist die absolute Mindestzeit für den Kaltstart der Geräte (berechnet alsT = N / cps
, wobeiN
die Gesamtzahl der Geräte ist undcps
die Dienstgrenze für die Anzahl der Verbindungen pro Sekunde).
Weitere Informationen zum Zeitpunkt der Wiederholungsvorgänge finden Sie unter Retry Timing (Wiederholungszeitpunkt).
Erneutes Bereitstellen von Geräten
Bei der erneuten Bereitstellung muss ein Gerät einem IoT-Hub bereitgestellt werden, nachdem es zuvor erfolgreich verbunden wurde. Viele Gründe können dazu führen, dass ein Gerät eine Verbindung mit einem IoT-Hub erneut herstellen muss, z. B. Folgendes:
- Ein Gerät könnte aufgrund von Stromausfall, Verlust der Netzwerkkonnektivität, Änderung des geografischen Standorts, Firmwareupdates, Zurücksetzung auf Werkseinstellungen oder Zertifikatschlüsseldrehung neu gestartet werden.
- Die IoT Hub-Instanz könnte aufgrund eines nicht geplanten IoT-Hub-Ausfalls nicht verfügbar sein.
Sie sollten nicht jedes Mal, wenn ein Gerät neu gestartet wird, den Bereitstellungsprozess durchlaufen müssen. Die meisten Geräte, die neu bereitgestellt werden, werden wieder mit demselben IoT-Hub verbunden. Stattdessen sollte ein Gerät versuchen, eine direkte Verbindung mit seinem IoT-Hub herzustellen, indem die Informationen verwendet werden, die von einer vorherigen erfolgreichen Verbindung zwischengespeichert wurden.
Geräte, die eine Verbindungszeichenfolge speichern können
Geräte, die die Möglichkeit haben, ihre Verbindungszeichenfolge nach der Erstbereitstellung zu speichern, sollten dies tun und versuchen, nach dem Neustart eine direkte Verbindung mit IoT Hub herzustellen. Dieses Muster reduziert die Latenz beim erfolgreichen Herstellen der Verbindung mit dem entsprechenden IoT-Hub. Es gibt zwei mögliche Ursachen:
Der IoT-Hub, mit dem beim Neustart des Geräts eine Verbindung hergestellt werden soll, entspricht dem zuvor verbundenen IoT-Hub.
Die aus dem Cache abgerufene Verbindungszeichenfolge sollte gut funktionieren, und das Gerät kann die Verbindung mit demselben Endpunkt erneut herstellen. Es ist kein neuer Start des Bereitstellungsprozesses erforderlich.
Der IoT-Hub, mit dem beim Neustart des Geräts eine Verbindung hergestellt werden soll, ist nicht der zuvor verbundene IoT-Hub.
Die im Arbeitsspeicher gespeicherte Verbindungszeichenfolge ist ungenau. Der Versuch, eine Verbindung mit demselben Endpunkt herzustellen, ist nicht erfolgreich, und daher wird der Wiederholungsmechanismus für die IoT Hub-Verbindung ausgelöst. Sobald der Schwellenwert für den IoT Hub-Verbindungsfehler erreicht ist, löst der Wiederholungsmechanismus automatisch einen neuen Start des Bereitstellungsprozesses aus.
Geräte, die keine Verbindungszeichenfolge speichern können
Einige Geräte verfügen nicht über genügend Kapazität, um die Zwischenspeicherung der Verbindungszeichenfolge aus einer früheren erfolgreichen IoT Hub-Verbindung aufzunehmen. Diese Geräte müssen nach dem Neustart über DPS neu bereitgestellt werden. Verwenden Sie die DPS-Registrierungs-API für die erneute Registrierung. Beachten Sie, dass die Anzahl der Neuregistrierungen pro Minute auf der Grundlage des DPS-Geräteregistrierungsgrenzwerts begrenzt ist.
Beispiel für die erneute Bereitstellung
Die Codebeispiele in diesem Szenario zeigen eine Klasse zum Lesen aus dem Gerätecache und Schreiben darauf an, gefolgt von Code, der versucht, erneut eine Verbindung eines Geräts mit dem IoT-Hub herzustellen, wenn eine Verbindungszeichenfolge gefunden wird, und eine erneute Bereitstellung über DPS durchführt, wenn nicht.
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);
}
}
}
Sie könnten einen Code ähnlich dem folgenden verwenden, um zu bestimmen, wie mit dem erneuten Verbinden eines Geräts verfahren werden soll, nachdem festgestellt wurde, ob sich Verbindungsinformationen im Cache befinden:
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.");
}
Überlegungen zur IoT Hub-Konnektivität
Jeder einzelne IoT-Hub ist auf 1 Million Geräte und Module beschränkt. Wenn Sie mehr als eine Million Geräte haben möchten, setzen Sie die Anzahl der Geräte auf 1 Million pro Hub fest, und fügen Sie Hubs nach Bedarf hinzu, wenn der Umfang Ihrer Bereitstellung zunimmt. Weitere Informationen finden Sie unter Referenz: IoT Hub-Kontingente und -Drosselung. Wenn Sie mehrere Millionen Geräte planen und diese in einer bestimmten Region unterstützen müssen (z. B. aufgrund von Datenresidenzanforderungen in einer EU-Region), können Sie sich mit uns in Verbindung setzen, um sicherzustellen, dass die Region, in der Sie die Bereitstellung vornehmen, über die Kapazitäten verfügt, um Ihren aktuellen und zukünftigen Umfang zu unterstützen.
Beim Herstellen einer Verbindung zu IoT Hub über DPS sollten Geräte beim Herstellen einer Verbindung die folgende Logik als Reaktion auf Fehlercodes verwenden:
- Wiederholen Sie bei Empfang einer der Serverfehlerantworten der 500-Serie den Verbindungsversuch entweder mit zwischengespeicherten Anmeldeinformationen oder den Ergebnissen eines Aufrufs der Geräteregistrierungsstatus-Lookup-API.
- Wenn Sie
401, Unauthorized
,403, Forbidden
oder404, Not Found
empfangen, führen Sie eine vollständige Neuregistrierung durch Aufrufen der DPS-Registrierungs-API aus.
Jederzeit sollten Geräte in der Lage sein, auf einen vom Benutzer initiierten Befehl zur erneuten Bereitstellung zu reagieren.
Wenn Geräte vom IoT Hub getrennt werden, sollten die Geräte 15-30 Minuten versuchen, eine direkte Verbindung mit demselben IoT Hub wiederherzustellen, bevor sie versuchen, zu DPS zurückzukehren.
Andere IoT Hub-Szenarien bei Verwendung von DPS:
- IoT Hub-Failover: Geräte sollten weiterhin funktionieren, da Verbindungsinformationen nicht geändert werden sollten und Logik vorhanden ist, um einen erneuten Verbindungsversuch durchzuführen, sobald der Hub wieder verfügbar ist.
- Wechsel des IoT-Hubs: Zuweisen von Geräten zu einem anderen IoT-Hub sollte mithilfe einer benutzerdefinierten Zuordnungsrichtlinie erfolgen.
- IoT Hub-Verbindung wiederholen: Sie sollten keine aggressive Wiederholungsstrategie verwenden. Lassen Sie stattdessen eine Zeitspanne von mindestens einer Minute vor einem Wiederholungsversuch zu.
- IoT-Hub-Partitionen: Wenn sich Ihre Gerätestrategie stark auf Telemetrie stützt, sollte die Anzahl der Geräte-to-Cloud-Partitionen erhöht werden.
Überwachen von Geräten
Ein wichtiger Bestandteil der gesamten Bereitstellung ist die End-to-End-Überwachung der Lösung, um sicherzustellen, dass das System entsprechend ausgeführt wird. Es gibt mehrere Möglichkeiten, die Integrität eines Diensts für die Bereitstellung von IoT-Geräten in großem Umfang zu überwachen. Die folgenden Muster haben sich bei der Überwachung des Diensts als wirksam erwiesen:
- Erstellen Sie eine Anwendung, um jede Registrierungsgruppe in einer DPS-Instanz abzufragen, rufen Sie die gesamten für diese Gruppe registrierten Geräte ab, und aggregieren Sie dann die Zahlen aus verschiedenen Registrierungsgruppen. Diese Zahl entspricht der genauen Anzahl der Geräte, die derzeit über DPS registriert sind und verwendet werden können, um den Status des Diensts zu überwachen.
- Überwachen Sie Geräteregistrierungen über einen bestimmten Zeitraum. Überwachen Sie beispielsweise die Registrierungsraten für eine DPS-Instanz in den vorherigen fünf Tagen. Beachten Sie, dass dieser Ansatz nur ein annäherndes Bild liefert und auch auf einen Zeitraum begrenzt ist.
Nächste Schritte
- Bereitstellen von Geräten für IoT-Hubs
- Retry Timing (Wiederholungszeitpunkt)