Serverloze gebeurtenisverwerking

Azure Cosmos DB
Azure Functions
Azure Monitor
Azure Pipelines
Azure Storage

Deze referentiearchitectuur toont een serverloze, gebeurtenisgestuurde architectuur die een gegevensstroom opneemt, de gegevens verwerkt en de resultaten naar een back-enddatabase schrijft.

Architectuur

Diagram met een referentiearchitectuur voor serverloze gebeurtenisverwerking met behulp van Azure Functions.

Workflow

  • Gebeurtenissen komen aan bij Azure Event Hubs.
  • Een functie-app wordt geactiveerd om de gebeurtenis af te handelen.
  • De gebeurtenis wordt opgeslagen in een Azure Cosmos DB-database.
  • Als de functie-app de gebeurtenis niet kan opslaan, wordt de gebeurtenis opgeslagen in een opslagwachtrij die later moet worden verwerkt.

Onderdelen

  • Event Hubs neemt de gegevensstroom op. Event Hubs is ontworpen voor scenario's voor gegevensstreaming met hoge doorvoer.

    Notitie

    Voor IoT-scenario's (Internet of Things) raden we Azure IoT Hub aan. IoT Hub heeft een ingebouwd eindpunt dat compatibel is met de Azure Event Hubs-API, zodat u beide services in deze architectuur kunt gebruiken zonder grote wijzigingen in de back-endverwerking. Zie voor meer informatie Verbinding maken ioT-apparaten naar Azure: IoT Hub en Event Hubs.

  • Functie-app. Azure Functions is een serverloze rekenoptie. Het maakt gebruik van een gebeurtenisgestuurd model, waarbij een stukje code (een functie) wordt aangeroepen door een trigger. Wanneer gebeurtenissen in deze architectuur binnenkomen bij Event Hubs, activeren ze een functie die de gebeurtenissen verwerkt en de resultaten naar de opslag schrijft.

    Functie-apps zijn geschikt voor het verwerken van afzonderlijke records van Event Hubs. Voor complexere scenario's voor stroomverwerking kunt u Apache Spark overwegen met behulp van Azure Databricks of Azure Stream Analytics.

  • Azure Cosmos DB. Azure Cosmos DB is een databaseservice met meerdere modellen die beschikbaar is in een serverloze, op verbruik gebaseerde modus. Voor dit scenario slaat de functie voor gebeurtenisverwerking JSON-records op met behulp van Azure Cosmos DB voor NoSQL.

  • Queue Storage. Queue Storage wordt gebruikt voor berichten met onbestelbare berichten. Als er een fout optreedt tijdens het verwerken van een gebeurtenis, slaat de functie de gebeurtenisgegevens op in een wachtrij met dode letters voor latere verwerking. Zie de sectie Tolerantie verderop in dit artikel voor meer informatie.

  • Azure Monitor. Monitor verzamelt metrische prestatiegegevens over de Azure-services die in de oplossing zijn geïmplementeerd. Door deze in een dashboard te visualiseren, kunt u inzicht krijgen in de status van de oplossing.

  • Azure Pipelines. Pijplijnen is een ci-service (continue integratie) en cd-service (continue levering) waarmee de toepassing wordt gebouwd, getest en geïmplementeerd.

Overwegingen

Met deze overwegingen worden de pijlers van het Azure Well-Architected Framework geïmplementeerd. Dit is een set richtlijnen die kunnen worden gebruikt om de kwaliteit van een workload te verbeteren. Zie Microsoft Azure Well-Architected Framework voor meer informatie.

Beschikbaarheid

De implementatie die hier wordt weergegeven, bevindt zich in één Azure-regio. Voor een tolerantere benadering van herstel na noodgevallen kunt u gebruikmaken van functies voor geodistributie in de verschillende services:

  • Event Hubs. Maak twee Event Hubs-naamruimten, een primaire (actieve) naamruimte en een secundaire (passieve) naamruimte. Berichten worden automatisch doorgestuurd naar de actieve naamruimte, tenzij u een failover naar de secundaire naamruimte uitvoert. Zie Azure Event Hubs Geo-disaster recovery voor meer informatie.
  • Functie-app. Implementeer een tweede functie-app die wacht om te lezen uit de secundaire Event Hubs-naamruimte. Deze functie schrijft naar een secundair opslagaccount voor een wachtrij met dode letters.
  • Azure Cosmos DB. Azure Cosmos DB ondersteunt meerdere schrijfregio's, waarmee schrijfbewerkingen worden uitgevoerd naar elke regio die u toevoegt aan uw Azure Cosmos DB-account. Als u meerdere schrijfbewerkingen niet inschakelt, kunt u nog steeds een failover uitvoeren voor de primaire schrijfregio. De Azure Cosmos DB-client-SDK's en de Azure Function-bindingen verwerken de failover automatisch, zodat u geen configuratie-instellingen voor toepassingen hoeft bij te werken.
  • Azure Storage. Gebruik RA-GRS-opslag voor de wachtrij met dode letters. Hiermee maakt u een alleen-lezen replica in een andere regio. Als de primaire regio niet meer beschikbaar is, kunt u de items lezen die zich momenteel in de wachtrij bevinden. Richt bovendien een ander opslagaccount in de secundaire regio in waarnaar de functie kan schrijven na een failover.

Schaalbaarheid

Event Hubs

De doorvoercapaciteit van Event Hubs wordt gemeten in doorvoereenheden. U kunt een Event Hub automatisch schalen door automatisch vergroten in te schakelen , waardoor de doorvoereenheden automatisch worden geschaald op basis van verkeer, tot een geconfigureerd maximum.

De Event Hubs-trigger in de functie-app wordt geschaald op basis van het aantal partities in de Event Hub. Aan elke partitie wordt één functie-exemplaar tegelijk toegewezen. Als u de doorvoer wilt maximaliseren, ontvangt u de gebeurtenissen in een batch in plaats van één voor één.

Azure Cosmos DB

Azure Cosmos DB is beschikbaar in twee verschillende capaciteitsmodi:

  • Serverloos, voor workloads met onregelmatig of onvoorspelbaar verkeer en lage gemiddelde tot piekverkeersverhouding.
  • Ingerichte doorvoer voor workloads met duurzaam verkeer dat voorspelbare prestaties vereist.

Om ervoor te zorgen dat uw workload schaalbaar is, is het belangrijk om een geschikte partitiesleutel te kiezen wanneer u uw Azure Cosmos DB-containers maakt. Hier volgen enkele kenmerken van een goede partitiesleutel:

  • De sleutelwaarderuimte is groot.
  • Er is een gelijkmatige verdeling van lees-/schrijfbewerkingen per sleutelwaarde, waardoor sneltoetsen worden vermeden.
  • De maximale gegevens die zijn opgeslagen voor een enkele sleutelwaarde, overschrijden niet de maximale fysieke partitiegrootte (20 GB).
  • De partitiesleutel voor een document wordt niet gewijzigd. U kunt de partitiesleutel niet bijwerken in een bestaand document.

In het scenario voor deze referentiearchitectuur slaat de functie precies één document per apparaat op dat gegevens verzendt. De functie werkt de documenten voortdurend bij met de meest recente apparaatstatus met behulp van een upsert-bewerking. Apparaat-id is een goede partitiesleutel voor dit scenario, omdat schrijfbewerkingen gelijkmatig over de sleutels worden verdeeld en de grootte van elke partitie strikt gebonden is omdat er één document is voor elke sleutelwaarde. Zie Partitie en schaal in Azure Cosmos DB voor meer informatie over partitiesleutels.

Tolerantie

Wanneer u de Event Hubs-trigger met Functions gebruikt, worden uitzonderingen binnen uw verwerkingslus onderscheppen. Als er een niet-verwerkte uitzondering optreedt, worden de berichten niet opnieuw geprobeerd door de Functions-runtime. Als een bericht niet kan worden verwerkt, plaatst u het bericht in een wachtrij voor onbestelbare berichten. Gebruik een out-of-band-proces om de berichten te onderzoeken en corrigerende actie te bepalen.

De volgende code laat zien hoe de opnamefunctie uitzonderingen onderschept en niet-verwerkte berichten in een wachtrij met dode letters plaatst.

 [Function(nameof(RawTelemetryFunction))]
 public async Task RunAsync([EventHubTrigger("%EventHubName%", Connection = "EventHubConnection")] EventData[] messages,
     FunctionContext context)
 {
     _telemetryClient.GetMetric("EventHubMessageBatchSize").TrackValue(messages.Length);
     DeviceState? deviceState = null;
     // Create a new CosmosClient
     var cosmosClient = new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTION_STRING"));

     // Get a reference to the database and the container
     var database = cosmosClient.GetDatabase(Environment.GetEnvironmentVariable("COSMOSDB_DATABASE_NAME"));
     var container = database.GetContainer(Environment.GetEnvironmentVariable("COSMOSDB_DATABASE_COL"));

     // Create a new QueueClient
     var queueClient = new QueueClient(Environment.GetEnvironmentVariable("DeadLetterStorage"), "deadletterqueue");
     await queueClient.CreateIfNotExistsAsync();

     foreach (var message in messages)
     {
         try
         {
             deviceState = _telemetryProcessor.Deserialize(message.Body.ToArray(), _logger);
             try
             {
                 // Add the device state to Cosmos DB
                 await container.UpsertItemAsync(deviceState, new PartitionKey(deviceState.DeviceId));
             }
             catch (Exception ex)
             {
                  _logger.LogError(ex, "Error saving on database", message.PartitionKey, message.SequenceNumber);
                 var deadLetterMessage = new DeadLetterMessage { Issue = ex.Message, MessageBody = message.Body.ToArray(), DeviceState = deviceState };
                 // Convert the dead letter message to a string
                 var deadLetterMessageString = JsonConvert.SerializeObject(deadLetterMessage);

                 // Send the message to the queue
                 await queueClient.SendMessageAsync(deadLetterMessageString);
             }

         }
         catch (Exception ex)
         {
             _logger.LogError(ex, "Error deserializing message", message.PartitionKey, message.SequenceNumber);
             var deadLetterMessage = new DeadLetterMessage { Issue = ex.Message, MessageBody = message.Body.ToArray(), DeviceState = deviceState };
             // Convert the dead letter message to a string
             var deadLetterMessageString = JsonConvert.SerializeObject(deadLetterMessage);

             // Send the message to the queue
             await queueClient.SendMessageAsync(deadLetterMessageString);
         }
     }
 }

De weergegeven code registreert ook uitzonderingen op Application Insights. U kunt de partitiesleutel en het volgnummer gebruiken om berichten met dode letters te correleren met de uitzonderingen in de logboeken.

Berichten in de wachtrij voor onbestelbare berichten moeten voldoende informatie hebben, zodat u de context van de fout kunt begrijpen. In dit voorbeeld bevat de DeadLetterMessage klasse het uitzonderingsbericht, de oorspronkelijke gebeurtenistekstgegevens en het gedeserialiseerde gebeurtenisbericht (indien beschikbaar).

    public class DeadLetterMessage
    {
        public string? Issue { get; set; }
        public byte[]? MessageBody { get; set; }
        public DeviceState? DeviceState { get; set; }
    }

Gebruik Azure Monitor om de Event Hub te bewaken. Als u ziet dat er invoer is maar geen uitvoer, betekent dit dat berichten niet worden verwerkt. In dat geval gaat u naar Log Analytics en zoekt u naar uitzonderingen of andere fouten.

DevOps

Gebruik infrastructuur als code (IaC) indien mogelijk. IaC beheert de infrastructuur, toepassing en opslagresources met een declaratieve benadering zoals Azure Resource Manager. Dit helpt bij het automatiseren van de implementatie met Behulp van DevOps als een oplossing voor continue integratie en continue levering (CI/CD). Sjablonen moeten worden geversied en opgenomen als onderdeel van de release-pijplijn.

Wanneer u sjablonen maakt, groepeert u resources als een manier om ze per workload te organiseren en te isoleren. Een veelvoorkomende manier om na te denken over workload is één serverloze toepassing of een virtueel netwerk. Het doel van workloadisolatie is om de resources aan een team te koppelen, zodat het DevOps-team onafhankelijk alle aspecten van deze resources kan beheren en CI/CD kan uitvoeren.

Wanneer u uw services implementeert, moet u ze bewaken. Overweeg om Application Insights te gebruiken om de ontwikkelaars in staat te stellen de prestaties te bewaken en problemen te detecteren.

Zie de DevOps-controlelijst voor meer informatie.

Herstel na noodgeval

De implementatie die hier wordt weergegeven, bevindt zich in één Azure-regio. Voor een tolerantere benadering van herstel na noodgevallen kunt u gebruikmaken van functies voor geodistributie in de verschillende services:

  • Event Hubs. Maak twee Event Hubs-naamruimten, een primaire (actieve) naamruimte en een secundaire (passieve) naamruimte. Berichten worden automatisch doorgestuurd naar de actieve naamruimte, tenzij u een failover naar de secundaire naamruimte uitvoert. Zie Azure Event Hubs Geo-disaster recovery voor meer informatie.

  • Functie-app. Implementeer een tweede functie-app die wacht om te lezen uit de secundaire Event Hubs-naamruimte. Deze functie schrijft naar een secundair opslagaccount voor wachtrij met dode letters.

  • Azure Cosmos DB. Azure Cosmos DB ondersteunt meerdere schrijfregio's, waarmee schrijfbewerkingen worden uitgevoerd naar elke regio die u toevoegt aan uw Azure Cosmos DB-account. Als u meerdere schrijfbewerkingen niet inschakelt, kunt u nog steeds een failover uitvoeren voor de primaire schrijfregio. De Azure Cosmos DB-client-SDK's en de Azure Function-bindingen verwerken de failover automatisch, zodat u geen configuratie-instellingen voor toepassingen hoeft bij te werken.

  • Azure Storage. Gebruik RA-GRS-opslag voor de wachtrij met dode letters. Hiermee maakt u een alleen-lezen replica in een andere regio. Als de primaire regio niet meer beschikbaar is, kunt u de items lezen die zich momenteel in de wachtrij bevinden. Richt bovendien een ander opslagaccount in de secundaire regio in waarnaar de functie kan schrijven na een failover.

Kostenoptimalisatie

Kostenoptimalisatie gaat over manieren om onnodige uitgaven te verminderen en operationele efficiëntie te verbeteren. Zie Overzicht van de pijler kostenoptimalisatie voor meer informatie.

Gebruik de Azure-prijscalculator om de kosten te schatten. Hier volgen enkele andere overwegingen voor Azure Functions en Azure Cosmos DB.

Azure Functions

Azure Functions ondersteunt twee hostingmodellen:

  • Verbruiksabonnement. Rekenkracht wordt automatisch toegewezen wanneer uw code wordt uitgevoerd.
  • App Service-plan. Er wordt een set virtuele machines (VM's) toegewezen voor uw code. Het App Service-plan definieert het aantal VM's en de VM-grootte.

In deze architectuur activeert elke gebeurtenis die op Event Hubs aankomt een functie die die gebeurtenis verwerkt. Vanuit kostenperspectief is het raadzaam om het verbruiksabonnement te gebruiken, omdat u alleen betaalt voor de rekenresources die u gebruikt.

Azure Cosmos DB

Met Azure Cosmos DB betaalt u voor de bewerkingen die u op uw database uitvoert en voor de opslag die door uw gegevens wordt gebruikt.

  • Databasebewerkingen. De manier waarop er kosten in rekening worden gebracht voor uw databasebewerkingen, is afhankelijk van het type Azure Cosmos DB-account dat u gebruikt.
    • In de serverloze modus hoeft u geen doorvoer in te richten bij het maken van resources in uw Azure Cosmos DB-account. Aan het einde van de factureringsperiode wordt u gefactureerd voor het aantal aanvraageenheden dat wordt verbruikt door uw databasebewerkingen.
    • In de ingerichte doorvoermodus geeft u de doorvoer op die u nodig hebt in aanvraageenheden per seconde (RU/s) en wordt u per uur gefactureerd voor de maximale ingerichte doorvoer voor een bepaald uur. Opmerking: omdat het ingerichte doorvoermodel resources aan uw container of database toedraagt, worden er kosten in rekening gebracht voor de doorvoer die u hebt ingericht, zelfs als u geen workloads uitvoert.
  • Opslag. U wordt een vast tarief gefactureerd voor de totale hoeveelheid opslagruimte (in GB's) die gedurende een bepaald uur door uw gegevens en indexen wordt verbruikt.

In deze referentiearchitectuur slaat de functie precies één document op per apparaat dat gegevens verzendt. De functie werkt de documenten voortdurend bij met de meest recente apparaatstatus, met behulp van een upsert-bewerking, wat rendabel is in termen van verbruikte opslag. Zie het prijsmodel van Azure Cosmos DB voor meer informatie.

Gebruik de Azure Cosmos DB-capaciteitscalculator om een snelle schatting te krijgen van de workloadkosten.

Dit scenario implementeren

GitHub-logo Een referentie-implementatie voor deze architectuur is beschikbaar op GitHub.

Volgende stappen