Regelverk för storskaliga IoT-enhetsdistributioner
Det kan vara svårt att skala en IoT-lösning till miljontals enheter. Storskaliga lösningar måste ofta utformas i enlighet med tjänst- och prenumerationsgränser. När kunder använder Azure IoT Device Provisioning Service använder de den i kombination med andra Azure IoT-plattformstjänster och -komponenter, till exempel IoT Hub och Azure IoT-enhets-SDK:er. Den här artikeln beskriver metodtips, mönster och exempelkod som du kan använda i din design för att dra nytta av dessa tjänster och göra det möjligt för dina distributioner att skala ut. Genom att följa dessa mönster och metoder från designfasen i projektet kan du maximera prestanda för dina IoT-enheter.
Etablera nya enheter
Första gången etablering är processen att registrera en enhet för första gången som en del av en IoT-lösning. När du arbetar med storskaliga distributioner är det viktigt att schemalägga etableringsprocessen för att undvika överbelastningssituationer som orsakas av alla enheter som försöker ansluta samtidigt.
Använda ett förskjutet etableringsschema
För distribution av enheter i miljoners skala kan registrering av alla enheter samtidigt leda till att DPS-instansen överbelastas på grund av begränsning (HTTP-svarskod 429, Too Many Requests
) och ett misslyckande med att registrera dina enheter. Om du vill förhindra sådana begränsningar använder du ett stegvis registreringsschema för enheterna. Konfigurera batchstorlekarna för enhetsregistrering i enlighet med DPS-kvoter och -gränser. Om registreringsfrekvensen till exempel är 200 enheter per minut är batchstorleken för registrering 200 enheter per batch.
Försök igen
Om tillfälliga fel inträffar på grund av att en tjänst är upptagen kan enheter ansluta till IoT-molnet med hjälp av omprövningslogik. Ett stort antal återförsök kan dock ytterligare försämra en upptagen tjänst som körs nära eller på dess kapacitet. Precis som med alla Azure-tjänster bör du implementera en intelligent återförsöksmekanism med exponentiell backoff. Mer information om olika återförsöksmönster finns i designmönstret för återförsök och övergående felhantering.
I stället för att omedelbart försöka utföra en distribution igen när den begränsas väntar du tills den tid som anges i retry-after
rubriken. Om det inte finns någon återförsöksrubrik tillgänglig från tjänsten kan den här algoritmen hjälpa dig att få en smidigare enhetsregistreringsupplevelse:
min_retry_delay_msec = 1000
max_retry_delay_msec = (1.0 / <load>) * <T> * 1000
max_random_jitter_msec = max_retry_delay_msec
Med den här logiken fördröjer enheterna återanslutningen under en slumpmässig tid, mellan min_retry_delay_msec
och max_retry_delay_msec
. Den maximala fördröjningen för återförsök beräknas med följande variabler:
<load>
är en konfigurerbar faktor med värden > 0, vilket indikerar att belastningen utförs vid en genomsnittlig belastningstid multiplicerat med antalet anslutningar per sekund<T>
är den absoluta minsta tiden för att kallstarta enheterna (beräknas somT = N / cps
varN
är det totala antalet enheter ochcps
är tjänstgränsen för antalet anslutningar per sekund).
Mer information om tidpunkten för återförsök finns i Tid för återförsök.
Etablera om enheter
Ometablering är den process där en enhet måste etableras till en IoT Hub efter att ha anslutits tidigare. Det kan finnas många orsaker till att en enhet behöver återansluta till en IoT Hub, till exempel:
- En enhet kan startas om på grund av strömavbrott, förlust av nätverksanslutning, geo-flytt, uppdateringar av inbyggd programvara, fabriksåterställning eller rotation av certifikatnyckel.
- IoT Hub-instansen kan vara otillgänglig på grund av ett oplanerat IoT Hub-avbrott.
Du bör inte behöva gå igenom etableringsprocessen varje gång en enhet startas om. De flesta enheter som återskapas ansluts till samma IoT-hubb. I stället bör en enhet försöka ansluta till sin IoT-hubb direkt med hjälp av den information som cachelagrades från en tidigare lyckad anslutning.
Enheter som kan lagra en anslutningssträng
Enheter som har möjlighet att lagra sina anslutningssträng efter den första etableringen bör göra det och försöka återansluta direkt till IoT Hub efter omstart. Det här mönstret minskar svarstiden vid anslutning till lämplig IoT Hub. Det finns två möjliga fall här:
IoT Hub för att ansluta vid omstart av enheten är samma som den tidigare anslutna IoT Hub.
Den anslutningssträng som hämtas från cacheminnet bör fungera bra och enheten kan återansluta till samma slutpunkt. Inget behov av en nystart för etableringsprocessen.
IoT Hub för att ansluta vid omstart av enheten skiljer sig från den tidigare anslutna IoT Hub.
Den anslutningssträng som lagras i minnet är felaktig. Det går inte att ansluta till samma slutpunkt, så återförsöksmekanismen för IoT Hub-anslutningen utlöses. När tröskelvärdet för IoT Hub-anslutningsfelet har nåtts utlöser återförsöksmekanismen automatiskt en ny start på etableringsprocessen.
Enheter som inte kan lagra en anslutningssträng
Vissa enheter har inte tillräckligt stort fotavtryck eller minne för cachelagring av anslutningssträng från en tidigare lyckad IoT Hub-anslutning. Dessa enheter måste återskapas via DPS efter omstart. Använd DPS-registrerings-API:et för att registrera igen. Tänk på att antalet omregistreringar per minut är begränsat baserat på gränsen för DPS-enhetsregistrering.
Exempel på ometablering
Kodexemplen i det här avsnittet visar en klass för att läsa till och skriva från enhetens cache, följt av kod som försöker återansluta en enhet till IoT Hub om en anslutningssträng hittas och återskapas via DPS om det inte är det.
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);
}
}
}
Du kan använda kod som liknar följande för att avgöra hur du fortsätter med att återansluta en enhet när du har fastställt om det finns anslutningsinformation i cacheminnet:
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.");
}
Anslutningsöverväganden för IoT Hub
En enskild IoT-hubb är begränsad till 1 miljon enheter plus moduler. Om du planerar att ha fler än en miljon enheter kan du begränsa antalet enheter till 1 miljon per hubb och lägga till hubbar efter behov när du ökar distributionens skala. Mer information finns i IoT Hub-kvoter. Om du har planer för mer än en miljon enheter och du behöver stöd för dem i en viss region (till exempel i en EU-region för datahemvistkrav) kan du kontakta oss för att se till att den region som du distribuerar för har kapacitet att stödja din nuvarande och framtida skala.
När du ansluter till IoT Hub via DPS bör enheterna använda följande logik som svar på felkoder vid anslutning:
- När du tar emot något av serverfelsvaren i 500-serien försöker du igen med cachelagrade autentiseringsuppgifter eller resultatet av ett API-anrop för sökning efter enhetsregistreringsstatus.
- När du tar emot
401, Unauthorized
eller403, Forbidden
,404, Not Found
utför du en fullständig omregistrering genom att anropa DPS-registrerings-API:et.
När som helst bör enheterna kunna svara på ett användarinitierat återetableringskommando.
Om enheter kopplas från från IoT Hub bör enheterna försöka återansluta direkt till samma IoT Hub i 15–30 minuter innan de försöker gå tillbaka till DPS.
Andra IoT Hub-scenarier när du använder DPS:
- Redundansväxling i IoT Hub: Enheter bör fortsätta att fungera eftersom anslutningsinformationen inte bör ändras och logiken finns för att försöka ansluta igen när hubben är tillgänglig igen.
- Ändring av IoT Hub: Tilldela enheter till en annan IoT Hub bör göras med hjälp av en anpassad allokeringsprincip.
- Försök igen IoT Hub-anslutning: Du bör inte använda en aggressiv strategi för återförsök. Tillåt i stället ett mellanrum på minst en minut innan ett nytt försök.
- IoT Hub-partitioner: Om din enhetsstrategi lutar sig kraftigt mot telemetri bör antalet partitioner från enhet till moln ökas.
Övervaka enheter
En viktig del av den övergripande distributionen är att övervaka lösningen från slutpunkt till slutpunkt för att säkerställa att systemet fungerar korrekt. Det finns flera sätt att övervaka hälsotillståndet för en tjänst för storskalig distribution av IoT-enheter. Följande mönster har visat sig vara effektiva när det gäller att övervaka tjänsten:
- Skapa ett program för att fråga varje registreringsgrupp på en DPS-instans, hämta det totala antalet enheter som registrerats i gruppen och aggregera sedan siffrorna från olika registreringsgrupper. Det här numret ger ett exakt antal enheter som för närvarande är registrerade via DPS och kan användas för att övervaka tjänstens tillstånd.
- Övervaka enhetsregistreringar under en viss period. Övervaka till exempel registreringshastigheter för en DPS-instans under de senaste fem dagarna. Observera att den här metoden endast ger en ungefärlig bild och även är begränsad till en tidsperiod.
Nästa steg
- Etablera enheter över IoT Hubs
- Tidsinställning för återförsök vid återförsök