Bonnes pratiques pour les déploiements d’appareils IoT à grande échelle
La mise à l’échelle d’une solution IoT pour des millions d’appareils peut être un véritable défi. Les solutions à grande échelle doivent souvent être conçues dans le respect de limites de service et d’abonnement. Quand des clients utilisent le service IoT Hub Device Provisioning Azure, ils le font en combinaison avec d’autres services et composants de la plateforme Azure IoT, tels que les kits de développement logiciel d’appareils IoT Hub et Azure IoT. Cet article décrit les meilleures pratiques, les modèles et les exemples de code que vous pouvez incorporer dans votre conception pour tirer parti de ces services et permettre l'évolution de vos déploiements. En suivant ces modèles et pratiques dès la phase de conception du projet, vous pouvez maximiser les performances de vos appareils IoT.
Provisionner de nouveaux appareils
Le premier approvisionnement d’un appareil est le processus d’intégration de celui-ci pour la première fois dans une solution IoT. Lorsque vous travaillez avec des déploiements à grande échelle, il est important de planifier le processus d’approvisionnement afin d’éviter des situations de surcharge occasionnées par le fait que tous les appareils tentent de se connecter en même temps.
Utiliser un calendrier de provisionnement échelonné
Pour le déploiement de millions d’appareils, l’inscription de tous les appareils en une fois peut entraîner une saturation de l’instance du service DPS en raison d’une limitation (code de réponse HTTP 429, Too Many Requests
), et l’échec de l’inscription de vos appareils. Pour éviter une telle limitation, utilisez un calendrier d’enregistrement échelonné pour les appareils. Configurez la taille des lots d'enregistrement de votre appareil conformément aux quotas et limites DPS. Par exemple, si le taux d’inscription est de 200 appareils par minute, la taille de lot pour l’intégration sera de 200 appareils par lot.
Réessayer les opérations
Si des pannes transitoires se produisent en raison d’un service occupé, la logique de nouvelle tentative permet aux appareils de se connecter avec succès au cloud IoT. Cependant, un grand nombre de nouvelles tentatives pourrait dégrader davantage un service occupé s’exécutant à pleine capacité ou presque. Comme pour tout service Azure, vous devriez implémenter un mécanisme de nouvelle tentative intelligent avec backoff exponentiel. Plus d'informations sur les différents modèles de nouvelle tentative peuvent être trouvées dans le modèle de conception de nouvelle tentative et la gestion des erreurs transitoires.
Plutôt que de réessayer immédiatement un déploiement en cas de limitation, attendez l'heure spécifiée dans l'en-tête retry-after
. À défaut d’en-tête de nouvelle tentative disponible à partir du service, cet algorithme peut vous aider à bénéficier d’une expérience d’intégration d’appareil plus fluide :
min_retry_delay_msec = 1000
max_retry_delay_msec = (1.0 / <load>) * <T> * 1000
max_random_jitter_msec = max_retry_delay_msec
Avec cette logique, les appareils retardent la reconnexion pendant une durée aléatoire, comprise entre min_retry_delay_msec
et max_retry_delay_msec
. Le délai maximum de nouvelle tentative est calculé avec les variables suivantes :
<load>
est un facteur configurable avec les valeurs > 0, qui indique que la charge s'exécutera à un temps de chargement moyen multiplié par le nombre de connexions par seconde<T>
est le temps minimum absolu pour démarrer à froid les appareils (calculé commeT = N / cps
oùN
est le nombre total d'appareils etcps
est la limite de service pour le nombre de connexions par seconde).
Pour plus d’informations sur le minutage des opérations de nouvelle tentative, consultez Minutage de nouvelle tentative.
Réapprovisionner des appareils
Le reprovisionnement est le processus par lequel un appareil doit être provisionné sur un IoT Hub après avoir été connecté précédemment avec succès. De nombreuses raisons peuvent nécessiter qu'un appareil se reconnecte à un IoT Hub, telles que :
- Un appareil pourrait redémarrer en raison d’une coupure d’alimentation, d’une perte de connectivité réseau, d’une géo-relocalisation, de mises à jour de microprogramme, d’une réinitialisation aux paramètres d’usine ou d’une rotation de clé de certificat.
- L’instance IoT Hub pourrait être indisponible en raison d’une panne d’IoT Hub non planifiée.
Vous ne devriez pas avoir besoin de suivre le processus de provisionnement à chaque redémarrage d'un appareil. La plupart des appareils réapprovisionnés finissent par être connectés au même hub IoT. Au lieu de cela, un appareil doit tenter de se connecter directement à son hub IoT en utilisant les informations mises en cache lors d’une précédente connexion réussie.
Appareils pouvant stocker une chaîne de connexion
Les appareils qui ont la possibilité de stocker leur chaîne de connexion après le provisionnement initial doivent le faire et tenter de se reconnecter directement à IoT Hub après le redémarrage. Ce modèle réduit la latence lors de la connexion réussie au Azure hub IoT Hub approprié. Il existe ici deux cas possibles :
L’IoT Hub auquel se connecter lors du redémarrage de l’appareil est identique à l’IoT Hub précédemment connecté.
La chaîne de connexion récupérée du cache devrait fonctionner correctement et l'appareil peut se reconnecter au même point de terminaison. Vous n’avez pas besoin d’un démarrage à zéro pour le processus d’approvisionnement.
L’IoT Hub auquel se connecter lors du redémarrage de l’appareil est différent de l’IoT Hub précédemment connecté.
La chaîne de connexion stockée en mémoire est inexacte. Une tentative de connexion au même point de terminaison échouera, ce qui aura pour effet de déclencher le mécanisme de nouvelle tentative pour la connexion IoT Hub. Une fois le seuil d’échec de connexion à l’IoT Hub atteint, le mécanisme de nouvelle tentative déclenche automatiquement un démarrage à zéro du processus d’approvisionnement.
Appareils ne pouvant pas stocker de chaîne de connexion
Certains appareils ne disposent pas d’une empreinte ou d’une mémoire suffisamment grande pour permettre la mise en cache de la chaîne de connexion d’une précédente connexion IoT Hub réussie. Ces appareils doivent être réapprovisionnés via DPS après le redémarrage. Utilisez l'API d'enregistrement DPS pour vous réinscrire. Gardez à l'esprit que le nombre de réinscriptions par minute est limité en fonction de la limite d'enregistrement de l'appareil Microsoft System Center Data Protection Manager.
Exemple de réapprovisionnement
Les exemples de code de cette section montrent une classe permettant de lire et d'écrire à partir du cache de l'appareil, suivie d'un code qui tente de reconnecter un appareil à IoT Hub si une chaîne de connexion est trouvée et de la reprovisionner via Microsoft System Center Data Protection Manager si ce n'est pas le cas.
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);
}
}
}
Vous pourriez utiliser un code similaire au suivant pour déterminer comment procéder à la reconnexion d’un appareil après avoir déterminé si le cache contient des informations de connexion :
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.");
}
Considérations relatives à la connectivité IoT Hub
Tout hub IoT est limité à 1 million d’appareils plus des modules. Si vous envisagez d’avoir plus d’un million d’appareils, plafonnez le nombre d’appareils à 1 million par hub et ajoutez autant de hubs que nécessaire lors de l’augmentation de l’échelle de votre déploiement. Pour plus d’informations, consultez les Quotas IoT Hub. Si vous avez des plans pour plus d’un million d’appareils que vous devez prendre en charge dans une région spécifique (par exemple, dans une région de l’UE en réponse à des exigences de résidence des données), vous pouvez nous contacter pour vous assurer que la région dans laquelle vous comptez opérer le déploiement dispose de la capacité nécessaire pour prendre en charge votre échelle actuelle et future.
Lors de la connexion à IoT Hub via Microsoft System Center Data Protection Manager, les appareils doivent utiliser la logique suivante en réponse aux codes d'erreur lors de la connexion :
- Lors de la réception de l’une des réponses d’erreur de serveur de la série HTTP 500, réessayez d’établir la connexion à l’aide d’informations d’identification mises en cache ou des résultats d’un appel de l’API de recherche de l’état d’inscription de l’appareil.
- En cas de réception d’une erreur
401, Unauthorized
,403, Forbidden
ou404, Not Found
, effectuez une réinscription complète en appelant l’API d’inscription DPS.
À tout moment, les appareils devraient pouvoir répondre à une commande de réapprovisionnement émanant d’un utilisateur.
Si les appareils sont déconnectés d’IoT Hub, ils doivent essayer de se reconnecter directement au même IoT Hub pendant 15 à 30 minutes avant de tenter de revenir au Microsoft System Center Data Protection Manager.
Autres scénarios IoT Hub lors de l’utilisation du service DPS :
- Basculement d’IoT Hub : les appareils devraient continuer à fonctionner car les informations de connexion ne devraient pas changer, et la logique est en place pour réessayer la connexion une fois le hub à nouveau disponible.
- Changement d’IoT Hub : l’attribution d’appareils à un autre IoT Hub devrait être effectuée à l’aide d’une stratégie d’allocation personnalisée.
- Réessayer la connexion IoT Hub : vous ne devez pas utiliser une stratégie de nouvelle tentative agressive. Au lieu de cela, attendez un intervalle d’au moins une minute avant de réessayer.
- Partitions IoT Hub : si votre stratégie en matière d’appareils dépend fortement d’une télémétrie, le nombre de partitions appareil-à-cloud doit être augmenté.
Surveiller les périphériques
Une partie importante du déploiement global consiste à surveiller la solution de bout en bout pour s’assurer que le système fonctionne correctement. Il existe plusieurs façons de surveiller l’intégrité d’un service pour un déploiement à grande échelle d’appareils IoT. Les modèles suivants ont démontré leur efficacité dans la surveillance du service :
- Créez une application pour interroger chaque groupe d’inscription sur une instance DPS, obtenir le nombre total d’appareils inscrits dans ce groupe, puis agréger les nombres des différents groupes d’inscription. Ce nombre fournit un compte exact des appareils actuellement inscrits via DPS, et peut être utilisé pour surveiller l’état du service.
- Surveillez les inscriptions d’appareils sur une période spécifique. Par exemple, surveillez les taux d’inscription d’une instance DPS sur la période des cinq jours précédents. Notez que cette approche ne fournit qu’un chiffre approximatif et est également plafonnée pour une période.
Étapes suivantes
- Provisionner des appareils sur des hubs IoT
- Minutage de nouvelle tentative lors d’opérations de nouvelle tentative