Najlepsze rozwiązania dotyczące wdrażania urządzeń IoT na dużą skalę
Skalowanie rozwiązania IoT do milionów urządzeń może być trudne. Rozwiązania na dużą skalę często muszą być projektowane zgodnie z limitami usług i subskrypcji. Gdy klienci korzystają z usługi Azure IoT Device Provisioning Service, używają jej w połączeniu z innymi usługami i składnikami platformy Azure IoT, takimi jak zestawy SDK urządzeń IoT Hub i Azure IoT. W tym artykule opisano najlepsze rozwiązania, wzorce i przykładowy kod, który można uwzględnić w projekcie, aby korzystać z tych usług i umożliwić skalowanie wdrożeń w poziomie. Postępując zgodnie z tymi wzorcami i rozwiązaniami, począwszy od fazy projektowania projektu, można zmaksymalizować wydajność urządzeń IoT.
Aprowizuj nowe urządzenia
Aprowizacja po raz pierwszy to proces dołączania urządzenia po raz pierwszy w ramach rozwiązania IoT. Podczas pracy z wdrożeniami na dużą skalę ważne jest zaplanowanie procesu aprowizacji w celu uniknięcia sytuacji przeciążenia spowodowanych przez wszystkie urządzenia próbujące nawiązać połączenie w tym samym czasie.
Używanie rozłożonego harmonogramu aprowizacji
W przypadku wdrażania urządzeń w skali milionów zarejestrowanie wszystkich urządzeń jednocześnie może spowodować przeciążenie wystąpienia usługi DPS z powodu ograniczania przepustowości (kod 429, Too Many Requests
odpowiedzi HTTP) i niepowodzenia rejestracji urządzeń. Aby zapobiec takiemu ograniczaniu, użyj rozłożonego harmonogramu rejestracji dla urządzeń. Skonfiguruj rozmiary partii rejestracji urządzeń zgodnie z limitami przydziału i limitami usługi DPS. Na przykład jeśli współczynnik rejestracji wynosi 200 urządzeń na minutę, rozmiar partii dołączania będzie wynosić 200 urządzeń na partię.
Operacje ponawiania prób
Jeśli występują przejściowe błędy spowodowane zajętą usługą, logika ponawiania umożliwia urządzeniom pomyślne nawiązanie połączenia z chmurą IoT. Jednak duża liczba ponownych prób może jeszcze bardziej obniżyć wydajność zajętej usługi, która jest uruchomiona blisko lub w jego pojemności. Podobnie jak w przypadku dowolnej usługi platformy Azure, należy zaimplementować inteligentny mechanizm ponawiania prób z wycofywaniem wykładniczym. Więcej informacji na temat różnych wzorców ponawiania prób można znaleźć w temacie Wzorzec projektowania ponawiania prób i obsługa błędów przejściowych.
Zamiast natychmiast ponowić próbę wdrożenia w przypadku ograniczenia przepustowości, zaczekaj na czas określony w nagłówku retry-after
. Jeśli w usłudze nie jest dostępny nagłówek ponawiania prób, ten algorytm może pomóc w osiągnięciu bardziej płynnego środowiska dołączania urządzeń:
min_retry_delay_msec = 1000
max_retry_delay_msec = (1.0 / <load>) * <T> * 1000
max_random_jitter_msec = max_retry_delay_msec
Dzięki tej logice urządzenia opóźniają ponowne nawiązywanie połączenia przez losowy czas między min_retry_delay_msec
i max_retry_delay_msec
. Maksymalne opóźnienie ponawiania prób jest obliczane przy użyciu następujących zmiennych:
<load>
jest konfigurowalnym czynnikiem o wartościach > 0, co wskazuje, że obciążenie będzie działać średnio w czasie ładowania pomnożonym przez liczbę połączeń na sekundę<T>
to minimalny czas zimnego rozruchu urządzeń (obliczany jakoT = N / cps
całkowitaN
liczba urządzeń icps
jest limitem usługi dla liczby połączeń na sekundę).
Aby uzyskać więcej informacji na temat chronometrażu operacji ponawiania, zobacz Czas ponawiania prób.
Ponowne aprowizowanie urządzeń
Ponowne aprowizowanie to proces, w którym należy aprowizować urządzenie w usłudze IoT Hub po pomyślnym nawiązaniu połączenia. Istnieje wiele powodów, dla których konieczne jest ponowne nawiązanie połączenia urządzenia z usługą IoT Hub, na przykład:
- Urządzenie może zostać uruchomione ponownie z powodu awarii zasilania, utraty łączności sieciowej, relokacji geograficznej, aktualizacji oprogramowania układowego, resetowania do ustawień fabrycznych lub rotacji klucza certyfikatu.
- Wystąpienie usługi IoT Hub może być niedostępne z powodu nieplanowanej awarii usługi IoT Hub.
Nie należy przechodzić przez proces aprowizacji za każdym razem, gdy urządzenie zostanie ponownie uruchomione. Większość urządzeń, które są ponownie aprowidowane, kończy się połączeniem z tym samym centrum IoT. Zamiast tego urządzenie powinno podjąć próbę nawiązania połączenia z centrum IoT hub bezpośrednio przy użyciu informacji buforowanych z poprzedniego pomyślnego połączenia.
Urządzenia, które mogą przechowywać parametry połączenia
Urządzenia, które mają możliwość przechowywania ich parametry połączenia po początkowej aprowizacji, powinny to zrobić i spróbować ponownie nawiązać połączenie bezpośrednio z usługą IoT Hub po ponownym uruchomieniu. Ten wzorzec zmniejsza opóźnienie pomyślnego nawiązywania połączenia z odpowiednią usługą IoT Hub. Istnieją dwa możliwe przypadki:
Usługa IoT Hub do nawiązania połączenia po ponownym uruchomieniu urządzenia jest taka sama jak wcześniej połączona usługa IoT Hub.
Parametry połączenia pobrany z pamięci podręcznej powinien działać prawidłowo, a urządzenie może ponownie nawiązać połączenie z tym samym punktem końcowym. Nie ma potrzeby nowego rozpoczęcia procesu aprowizacji.
Połączenie z usługą IoT Hub po ponownym uruchomieniu urządzenia różni się od wcześniej połączonego centrum IoT Hub.
Parametry połączenia przechowywane w pamięci są niedokładne. Próba nawiązania połączenia z tym samym punktem końcowym nie powiedzie się i dlatego zostanie wyzwolony mechanizm ponawiania próby połączenia usługi IoT Hub. Po osiągnięciu progu niepowodzenia połączenia z usługą IoT Hub mechanizm ponawiania automatycznie wyzwala nowy początek procesu aprowizacji.
Urządzenia, które nie mogą przechowywać parametry połączenia
Niektóre urządzenia nie mają wystarczająco dużego rozmiaru ani pamięci, aby pomieścić buforowanie parametry połączenia z wcześniejszego pomyślnego połączenia usługi IoT Hub. Te urządzenia muszą ponownie aprowizacji za pośrednictwem usługi DPS po ponownym uruchomieniu. Użyj interfejsu API rejestracji usługi DPS, aby ponownie się zarejestrować. Należy pamiętać, że liczba ponownych rejestracji na minutę jest ograniczona na podstawie limitu rejestracji urządzeń usługi DPS.
Przykład ponownej aprowizacji
Przykłady kodu w tej sekcji pokazują klasę do odczytu i zapisu z pamięci podręcznej urządzenia, a następnie kod, który próbuje ponownie połączyć urządzenie z usługą IoT Hub, jeśli zostanie znaleziona parametry połączenia i ponownie aprowizowana za pośrednictwem usługi DPS, jeśli tak nie jest.
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);
}
}
}
Możesz użyć kodu podobnego do poniższego, aby określić, jak kontynuować ponowne łączenie urządzenia po określeniu, czy w pamięci podręcznej znajdują się informacje o połączeniu:
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.");
}
Zagadnienia dotyczące łączności z usługą IoT Hub
Każde pojedyncze centrum IoT jest ograniczone do 1 miliona urządzeń i modułów. Jeśli planujesz mieć ponad milion urządzeń, należy ograniczyć liczbę urządzeń do 1 miliona na koncentrator i dodać koncentratory zgodnie z potrzebami podczas zwiększania skali wdrożenia. Aby uzyskać więcej informacji, zobacz Limity przydziału usługi IoT Hub. Jeśli masz plany dotyczące ponad miliona urządzeń i potrzebujesz ich obsługi w określonym regionie (takim jak w regionie UE w celu uzyskania wymagań dotyczących rezydencji danych), możesz skontaktować się z nami , aby upewnić się, że region, w którym wdrażasz, ma możliwość obsługi bieżącej i przyszłej skali.
Podczas nawiązywania połączenia z usługą IoT Hub za pośrednictwem usługi DPS urządzenia powinny używać następującej logiki w odpowiedzi na kody błędów podczas nawiązywania połączenia:
- Podczas odbierania dowolnej z 500 serii odpowiedzi na błędy serwera spróbuj ponownie nawiązać połączenie przy użyciu poświadczeń buforowanych lub wyników wywołania interfejsu API wyszukiwania stanu rejestracji urządzenia.
- W przypadku odbierania
401, Unauthorized
lub lub403, Forbidden
404, Not Found
wykonaj pełną ponowną rejestrację, wywołując interfejs API rejestracji usługi DPS.
W dowolnym momencie urządzenia powinny mieć możliwość odpowiadania na polecenie ponownego aprowizowania zainicjowane przez użytkownika.
Jeśli urządzenia są odłączone od usługi IoT Hub, urządzenia powinny spróbować ponownie nawiązać połączenie bezpośrednio z tym samym centrum IoT Hub przez 15–30 minut przed podjęciem próby powrotu do usługi DPS.
Inne scenariusze usługi IoT Hub w przypadku korzystania z usługi DPS:
- Tryb failover w usłudze IoT Hub: urządzenia powinny nadal działać, ponieważ informacje o połączeniu nie powinny ulec zmianie, a logika ma miejsce, aby ponowić próbę nawiązania połączenia po ponownym udostępnieniu centrum.
- Zmiana usługi IoT Hub: przypisywanie urządzeń do innego centrum IoT Hub powinno odbywać się przy użyciu niestandardowych zasad alokacji.
- Ponów próbę połączenia usługi IoT Hub: nie należy używać agresywnej strategii ponawiania prób. Zamiast tego należy zezwolić na przerwę co najmniej minutę przed ponowną próbą.
- Partycje usługi IoT Hub: jeśli strategia urządzenia mocno zależy od danych telemetrycznych, należy zwiększyć liczbę partycji z urządzenia do chmury.
Monitorowanie urządzeń
Ważną częścią ogólnego wdrożenia jest monitorowanie kompleksowego rozwiązania, aby upewnić się, że system działa prawidłowo. Istnieje kilka sposobów monitorowania kondycji usługi na potrzeby wdrożenia urządzeń IoT na dużą skalę. Następujące wzorce okazały się skuteczne w monitorowaniu usługi:
- Utwórz aplikację, aby wykonać zapytanie dotyczące każdej grupy rejestracji w wystąpieniu usługi DPS, uzyskać łączną liczbę urządzeń zarejestrowanych w tej grupie, a następnie zagregować liczby z różnych grup rejestracji. Ta liczba zawiera dokładną liczbę urządzeń, które są obecnie zarejestrowane za pośrednictwem usługi DPS i mogą służyć do monitorowania stanu usługi.
- Monitorowanie rejestracji urządzeń w określonym okresie. Na przykład monitoruj współczynniki rejestracji dla wystąpienia usługi DPS w ciągu ostatnich pięciu dni. Należy pamiętać, że takie podejście zapewnia jedynie przybliżoną liczbę i jest również ograniczone do okresu czasu.