Pipeline zur Datenstromverarbeitung mit Azure DatabricksStream processing pipeline with Azure Databricks

Diese Referenzarchitektur zeigt eine End-to-End-Pipeline zur Datenstromverarbeitung.This reference architecture shows an end-to-end stream processing pipeline. Dieser Pipelinetyp hat vier Phasen: Erfassung, Verarbeitung, Speicherung und Analyse/Berichterstellung.This type of pipeline has four stages: ingest, process, store, and analysis and reporting. In dieser Referenzarchitektur erfasst die Pipeline Daten aus zwei Quellen, verknüpft verwandte Datensätze aus den einzelnen Datenströmen, reichert das Ergebnis an und berechnet einen Durchschnitt in Echtzeit.For this reference architecture, the pipeline ingests data from two sources, performs a join on related records from each stream, enriches the result, and calculates an average in real time. Die Ergebnisse werden zur weiteren Analyse gespeichert.The results are stored for further analysis.

GitHub-Logo Eine Referenzimplementierung dieser Architektur ist auf GitHub verfügbar.GitHub logo A reference implementation for this architecture is available on GitHub.

Referenzarchitektur für Datenstromverarbeitung mit Azure Databricks

Szenario: Ein Taxiunternehmen erfasst Daten zu jeder Taxifahrt.Scenario: A taxi company collects data about each taxi trip. In diesem Szenario gehen wir davon aus, dass zwei separate Geräte Daten senden.For this scenario, we assume there are two separate devices sending data. Das Taxi verfügt ein Messgerät, das Informationen zu jeder Fahrt sendet – die Dauer, die Strecke sowie die Abhol- und Zielorte.The taxi has a meter that sends information about each ride — the duration, distance, and pickup and dropoff locations. Ein separates Gerät akzeptiert Zahlungen von Kunden und sendet Daten zu den Fahrpreisen.A separate device accepts payments from customers and sends data about fares. Das Taxiunternehmen möchte Fahrgasttrends ermitteln und dazu für jedes Stadtviertel in Echtzeit das durchschnittliche Trinkgeld pro gefahrener Meile berechnen.To spot ridership trends, the taxi company wants to calculate the average tip per mile driven, in real time, for each neighborhood.

ArchitectureArchitecture

Die Architektur umfasst die folgenden Komponenten.The architecture consists of the following components.

Datenquellen:Data sources. In dieser Architektur gibt es zwei Datenquellen, die Datenströme in Echtzeit generieren.In this architecture, there are two data sources that generate data streams in real time. Der erste Datenstrom enthält Informationen zur Fahrt und der zweite Informationen zum Fahrpreis.The first stream contains ride information, and the second contains fare information. Die Referenzarchitektur umfasst einen simulierten Datengenerator, der aus einem Satz von statischen Dateien liest und die Daten an Event Hubs pusht.The reference architecture includes a simulated data generator that reads from a set of static files and pushes the data to Event Hubs. Bei einer echten Anwendung stammen die Daten von Geräten, die in den Taxis installiert sind.The data sources in a real application would be devices installed in the taxi cabs.

Azure Event Hubs:Azure Event Hubs. Event Hubs ist ein Ereigniserfassungsdienst.Event Hubs is an event ingestion service. Die hier gezeigte Architektur verwendet zwei Event Hub-Instanzen, eine für jede Datenquelle.This architecture uses two event hub instances, one for each data source. Jede Datenquelle sendet einen Datenstrom an den zugehörigen Event Hub.Each data source sends a stream of data to the associated event hub.

Azure Databricks:Azure Databricks. Databricks ist eine Apache Spark-basierte Analyseplattform, die für die Microsoft Azure-Clouddienstplattform optimiert ist.Databricks is an Apache Spark-based analytics platform optimized for the Microsoft Azure cloud services platform. Sie wird verwendet, um die Taxifahrtdaten und die Fahrpreisdaten zu korrelieren und die korrelierten Daten mit den gespeicherten Stadtvierteldaten aus dem Databricks-Dateisystem anzureichern.Databricks is used to correlate of the taxi ride and fare data, and also to enrich the correlated data with neighborhood data stored in the Databricks file system.

Cosmos DB:Cosmos DB. Der Azure Databricks-Auftrag gibt eine Reihe von Datensätzen aus, die unter Verwendung der Cassandra-API in Cosmos DB geschrieben werden.The output from Azure Databricks job is a series of records, which are written to Cosmos DB using the Cassandra API. Die Cassandra-API wird verwendet, da sie Modelle mit Zeitreihendaten unterstützt.The Cassandra API is used because it supports time series data modeling.

Azure Log Analytics:Azure Log Analytics. Die von Azure Monitor erfassten Anwendungsprotokolldaten werden in einem Log Analytics-Arbeitsbereich gespeichert.Application log data collected by Azure Monitor is stored in a Log Analytics workspace. Mithilfe von Log Analytics-Abfragen können Metriken analysiert und visualisiert sowie Protokollmeldungen auf Probleme innerhalb der Anwendung untersucht werden.Log Analytics queries can be used to analyze and visualize metrics and inspect log messages to identify issues within the application.

DatenerfassungData ingestion

Um eine Datenquelle zu simulieren, verwendet die Referenzarchitektur das Dataset New York City Taxi Data[1].To simulate a data source, this reference architecture uses the New York City Taxi Data dataset[1]. Dieses Dataset enthält Daten zu Taxifahrten in New York City für einen Zeitraum von vier Jahren (2010–2013).This dataset contains data about taxi trips in New York City over a four-year period (2010 – 2013). Es umfasst zwei Datensatztypen: Fahrtdaten und Fahrpreisdaten.It contains two types of record: Ride data and fare data. Die Fahrtdaten enthalten die Fahrtdauer, die Fahrtstrecke sowie die Abhol- und Zielorte.Ride data includes trip duration, trip distance, and pickup and dropoff location. Die Fahrpreisdaten enthalten die Beträge von Fahrpreis, Steuern und Trinkgeld.Fare data includes fare, tax, and tip amounts. Gemeinsame Felder in beiden Datensatztypen sind die Taxinummer (Medallion), die Taxilizenz (Hack license) und die Anbieter-ID (Vendor ID).Common fields in both record types include medallion number, hack license, and vendor ID. Anhand dieser drei Felder werden ein Taxi und ein Fahrer eindeutig identifiziert.Together these three fields uniquely identify a taxi plus a driver. Die Daten werden im CSV-Format gespeichert.The data is stored in CSV format.

[1] Donovan, Brian; Work, Dan (2016): New York City Taxi Trip Data (2010 – 2013).[1] Donovan, Brian; Work, Dan (2016): New York City Taxi Trip Data (2010-2013). Universität Illinois in Urbana-Champaign.University of Illinois at Urbana-Champaign. https://doi.org/10.13012/J8PN93H8

Der Datengenerator ist eine .NET Core-Anwendung, die Datensätze liest und an Azure Event Hubs sendet.The data generator is a .NET Core application that reads the records and sends them to Azure Event Hubs. Der Generator sendet Fahrtdaten im JSON-Format und Fahrpreisdaten im CSV-Format.The generator sends ride data in JSON format and fare data in CSV format.

Event Hubs verwendet Partitionen zum Segmentieren der Daten.Event Hubs uses partitions to segment the data. Partitionen ermöglichen es einem Consumer, die einzelnen Partitionen gleichzeitig zu lesen.Partitions allow a consumer to read each partition in parallel. Wenn Sie Daten an Event Hubs senden, können Sie den Partitionsschlüssel explizit angeben.When you send data to Event Hubs, you can specify the partition key explicitly. Andernfalls werden Datensätze nach einem Roundrobinverfahren Partitionen zugewiesen.Otherwise, records are assigned to partitions in round-robin fashion.

In diesem Szenario sollen Fahrtdaten und Fahrpreisdaten für ein bestimmtes Taxi die gleiche Partitions-ID erhalten.In this scenario, ride data and fare data should end up with the same partition ID for a given taxi cab. Dies ermöglicht Databricks eine gewisse Parallelität beim Korrelieren der beiden Datenströme.This enables Databricks to apply a degree of parallelism when it correlates the two streams. Ein Datensatz in der Partition n der Fahrtdaten entspricht einem Datensatz in der Partition n der Fahrpreisdaten.A record in partition n of the ride data will match a record in partition n of the fare data.

Diagramm der Datenstromverarbeitung mit Azure Databricks und Event Hubs

Im Datengenerator enthält das gemeinsame Datenmodell für beide Datensatztypen eine PartitionKey-Eigenschaft, bei der es sich um die Verkettung von Medallion, HackLicense und VendorId handelt.In the data generator, the common data model for both record types has a PartitionKey property that is the concatenation of Medallion, HackLicense, and VendorId.

public abstract class TaxiData
{
    public TaxiData()
    {
    }

    [JsonProperty]
    public long Medallion { get; set; }

    [JsonProperty]
    public long HackLicense { get; set; }

    [JsonProperty]
    public string VendorId { get; set; }

    [JsonProperty]
    public DateTimeOffset PickupTime { get; set; }

    [JsonIgnore]
    public string PartitionKey
    {
        get => $"{Medallion}_{HackLicense}_{VendorId}";
    }

Diese Eigenschaft wird verwendet, um beim Senden der Daten an Event Hubs einen expliziten Partitionsschlüssel bereitzustellen:This property is used to provide an explicit partition key when sending to Event Hubs:

using (var client = pool.GetObject())
{
    return client.Value.SendAsync(new EventData(Encoding.UTF8.GetBytes(
        t.GetData(dataFormat))), t.PartitionKey);
}

Event HubsEvent Hubs

Die Durchsatzkapazität von Event Hubs wird in Durchsatzeinheiten gemessen.The throughput capacity of Event Hubs is measured in throughput units. Sie können einen Event Hub automatisch skalieren, indem Sie die Funktion für automatische Vergrößerung aktivieren. Dadurch werden die Durchsatzeinheiten basierend auf dem Datenverkehr automatisch bis zu einem konfigurierten Höchstwert hochskaliert.You can autoscale an event hub by enabling auto-inflate, which automatically scales the throughput units based on traffic, up to a configured maximum.

DatenstromverarbeitungStream processing

Die Datenverarbeitung in Azure Databricks erfolgt durch einen Auftrag.In Azure Databricks, data processing is performed by a job. Der Auftrag wird einem Cluster zugewiesen und darin ausgeführt.The job is assigned to and runs on a cluster. Bei dem Auftrag kann es sich um benutzerdefinierten Java-Code oder um ein Spark-Notebook handeln.The job can either be custom code written in Java, or a Spark notebook.

In dieser Referenzarchitektur ist der Auftrag ein Java-Archiv mit Klassen (geschrieben in Java und Scala).In this reference architecture, the job is a Java archive with classes written in both Java and Scala. Bei Angabe des Java-Archivs für einen Databricks-Auftrag wird die Klasse für die Ausführung durch den Databricks-Cluster angegeben.When specifying the Java archive for a Databricks job, the class is specified for execution by the Databricks cluster. Hier enthält die main-Methode der Klasse com.microsoft.pnp.TaxiCabReader die Datenverarbeitungslogik.Here, the main method of the com.microsoft.pnp.TaxiCabReader class contains the data processing logic.

Lesen des Datenstroms aus den beiden Event Hub-InstanzenReading the stream from the two event hub instances

Die Datenverarbeitungslogik verwendet strukturiertes Spark-Streaming, um Daten aus den beiden Azure Event Hub-Instanzen zu lesen:The data processing logic uses Spark structured streaming to read from the two Azure event hub instances:

val rideEventHubOptions = EventHubsConf(rideEventHubConnectionString)
      .setConsumerGroup(conf.taxiRideConsumerGroup())
      .setStartingPosition(EventPosition.fromStartOfStream)
    val rideEvents = spark.readStream
      .format("eventhubs")
      .options(rideEventHubOptions.toMap)
      .load

    val fareEventHubOptions = EventHubsConf(fareEventHubConnectionString)
      .setConsumerGroup(conf.taxiFareConsumerGroup())
      .setStartingPosition(EventPosition.fromStartOfStream)
    val fareEvents = spark.readStream
      .format("eventhubs")
      .options(fareEventHubOptions.toMap)
      .load

Anreichern der Daten mit StadtviertelinformationenEnriching the data with the neighborhood information

Die Fahrtdaten enthalten die Koordinaten (Längen- und Breitengrad) des Start- und Zielorts.The ride data includes the latitude and longitude coordinates of the pick up and drop off locations. Diese Koordinaten sind zwar hilfreich, eignen sich aber nicht besonders für die Analyse.While these coordinates are useful, they are not easily consumed for analysis. Daher werden die Daten mit Stadtvierteldaten aus einer Shape-Datei angereichert.Therefore, this data is enriched with neighborhood data that is read from a shapefile.

Das Shape-Dateiformat ist binär und lässt sich nicht so einfach analysieren. Die Bibliothek GeoTools bietet jedoch Tools für Geodaten, die das Shape-Dateiformat verwenden.The shapefile format is binary and not easily parsed, but the GeoTools library provides tools for geospatial data that use the shapefile format. Diese Bibliothek wird in der Klasse com.microsoft.pnp.GeoFinder verwendet, um auf der Grundlage der Koordinaten des Start- und Zielorts den Namen des Stadtviertels zu bestimmen.This library is used in the com.microsoft.pnp.GeoFinder class to determine the neighborhood name based on the pick up and drop off coordinates.

val neighborhoodFinder = (lon: Double, lat: Double) => {
      NeighborhoodFinder.getNeighborhood(lon, lat).get()
    }

Verknüpfen von Fahrt- und FahrpreisdatenJoining the ride and fare data

Zunächst werden die Fahrt- und Fahrpreisdaten transformiert:First the ride and fare data is transformed:

    val rides = transformedRides
      .filter(r => {
        if (r.isNullAt(r.fieldIndex("errorMessage"))) {
          true
        }
        else {
          malformedRides.add(1)
          false
        }
      })
      .select(
        $"ride.*",
        to_neighborhood($"ride.pickupLon", $"ride.pickupLat")
          .as("pickupNeighborhood"),
        to_neighborhood($"ride.dropoffLon", $"ride.dropoffLat")
          .as("dropoffNeighborhood")
      )
      .withWatermark("pickupTime", conf.taxiRideWatermarkInterval())

    val fares = transformedFares
      .filter(r => {
        if (r.isNullAt(r.fieldIndex("errorMessage"))) {
          true
        }
        else {
          malformedFares.add(1)
          false
        }
      })
      .select(
        $"fare.*",
        $"pickupTime"
      )
      .withWatermark("pickupTime", conf.taxiFareWatermarkInterval())

Anschließend werden die Fahrtdaten mit den Fahrpreisdaten verknüpft:And then the ride data is joined with the fare data:

val mergedTaxiTrip = rides.join(fares, Seq("medallion", "hackLicense", "vendorId", "pickupTime"))

Verarbeiten der Daten und Einfügen in Cosmos DBProcessing the data and inserting into Cosmos DB

Der durchschnittliche Fahrpreis für jedes Stadtviertel wird für ein bestimmtes Zeitintervall berechnet:The average fare amount for each neighborhood is calculated for a given time interval:

val maxAvgFarePerNeighborhood = mergedTaxiTrip.selectExpr("medallion", "hackLicense", "vendorId", "pickupTime", "rateCode", "storeAndForwardFlag", "dropoffTime", "passengerCount", "tripTimeInSeconds", "tripDistanceInMiles", "pickupLon", "pickupLat", "dropoffLon", "dropoffLat", "paymentType", "fareAmount", "surcharge", "mtaTax", "tipAmount", "tollsAmount", "totalAmount", "pickupNeighborhood", "dropoffNeighborhood")
      .groupBy(window($"pickupTime", conf.windowInterval()), $"pickupNeighborhood")
      .agg(
        count("*").as("rideCount"),
        sum($"fareAmount").as("totalFareAmount"),
        sum($"tipAmount").as("totalTipAmount")
      )
      .select($"window.start", $"window.end", $"pickupNeighborhood", $"rideCount", $"totalFareAmount", $"totalTipAmount")

Das Ergebnis wird schließlich in Cosmos DB eingefügt:Which is then inserted into Cosmos DB:

maxAvgFarePerNeighborhood
      .writeStream
      .queryName("maxAvgFarePerNeighborhood_cassandra_insert")
      .outputMode(OutputMode.Append())
      .foreach(new CassandraSinkForeach(connector))
      .start()
      .awaitTermination()

SicherheitshinweiseSecurity considerations

Der Zugriff auf den Arbeitsbereich der Azure-Datenbank wird über die Administratorkonsole gesteuert.Access to the Azure Database workspace is controlled using the administrator console. Über die Administratorkonsole können Benutzer hinzugefügt, Benutzerberechtigungen verwaltet und einmaliges Anmelden eingerichtet werden.The administrator console includes functionality to add users, manage user permissions, and set up single sign-on. Die Zugriffssteuerung für Arbeitsbereiche, Cluster, Aufträge und Tabellen kann ebenfalls über die Administratorkonsole festgelegt werden.Access control for workspaces, clusters, jobs, and tables can also be set through the administrator console.

Verwaltung geheimer SchlüsselManaging secrets

Azure Databricks enthält einen Geheimnisspeicher zum Speichern von Geheimnissen (beispielsweise Verbindungszeichenfolgen, Zugriffsschlüssel, Benutzernamen und Kennwörter).Azure Databricks includes a secret store that is used to store secrets, including connection strings, access keys, user names, and passwords. Geheimnisse werden im Azure Databricks-Geheimnisspeicher nach Bereichen partitioniert:Secrets within the Azure Databricks secret store are partitioned by scopes:

databricks secrets create-scope --scope "azure-databricks-job"

Geheimnisse werden auf der Bereichsebene hinzugefügt:Secrets are added at the scope level:

databricks secrets put --scope "azure-databricks-job" --key "taxi-ride"

Hinweis

Anstelle des nativen Azure Databricks-Bereichs kann auch ein Azure Key Vault-basierter Bereich verwendet werden.An Azure Key Vault-backed scope can be used instead of the native Azure Databricks scope. Weitere Informationen finden Sie unter Azure Key Vault-backed scopes (Azure Key Vault-basierte Bereiche).To learn more, see Azure Key Vault-backed scopes.

Im Code erfolgt der Zugriff auf Geheimnisse über die secrets-Hilfsprogramme von Azure Databricks.In code, secrets are accessed via the Azure Databricks secrets utilities.

Aspekte der ÜberwachungMonitoring considerations

Azure Databricks basiert auf Apache Spark. Beide Lösungen verwenden log4j als Standardbibliothek für die Protokollierung.Azure Databricks is based on Apache Spark, and both use log4j as the standard library for logging. Zusätzlich zur von Apache Spark bereitgestellten Standardprotokollierung sendet diese Referenzarchitektur auch Protokolle und Metriken an Azure Log Analytics.In addition to the default logging provided by Apache Spark, this reference architecture sends logs and metrics to Azure Log Analytics.

Die Klasse com.microsoft.pnp.TaxiCabReader konfiguriert das Apache Spark-Protokollierungssystem so, dass dessen Protokolle an Azure Log Analytics gesendet werden. Hierbei werden die Werte aus der Datei log4j.properties verwendet.The com.microsoft.pnp.TaxiCabReader class configures the Apache Spark logging system to send its logs to Azure Log Analytics using the values in the log4j.properties file. Die Meldungen der Apache Spark-Protokollierung liegen als Zeichenfolgen vor. Für Azure Log Analytics werden jedoch Protokollmeldungen im JSON-Format benötigt.While the Apache Spark logger messages are strings, Azure Log Analytics requires log messages to be formatted as JSON. Die Klasse com.microsoft.pnp.log4j.LogAnalyticsAppender transformiert die Meldungen in das JSON-Format:The com.microsoft.pnp.log4j.LogAnalyticsAppender class transforms these messages to JSON:


    @Override
    protected void append(LoggingEvent loggingEvent) {
        if (this.layout == null) {
            this.setLayout(new JSONLayout());
        }

        String json = this.getLayout().format(loggingEvent);
        try {
            this.client.send(json, this.logType);
        } catch(IOException ioe) {
            LogLog.warn("Error sending LoggingEvent to Log Analytics", ioe);
        }
    }

Bei der Verarbeitung von Fahrt- und Fahrpreismeldungen durch die Klasse com.microsoft.pnp.TaxiCabReader kann es zu Problemen mit der Formatierung und somit zu ungültigen Meldungen kommen.As the com.microsoft.pnp.TaxiCabReader class processes ride and fare messages, it's possible that either one may be malformed and therefore not valid. In einer Produktionsumgebung müssen diese falsch formatierten Meldungen unbedingt analysiert werden, um ein Problem mit den Datenquellen zu erkennen und schnell zu beheben, damit keine Daten verloren gehen.In a production environment, it's important to analyze these malformed messages to identify a problem with the data sources so it can be fixed quickly to prevent data loss. Die Klasse com.microsoft.pnp.TaxiCabReader registriert einen Apache Spark-Akkumulator zur Nachverfolgung der Anzahl falsch formatierter Fahrpreis- und Fahrtdatensätze:The com.microsoft.pnp.TaxiCabReader class registers an Apache Spark Accumulator that keeps track of the number of malformed fare and ride records:

    @transient val appMetrics = new AppMetrics(spark.sparkContext)
    appMetrics.registerGauge("metrics.malformedrides", AppAccumulators.getRideInstance(spark.sparkContext))
    appMetrics.registerGauge("metrics.malformedfares", AppAccumulators.getFareInstance(spark.sparkContext))
    SparkEnv.get.metricsSystem.registerSource(appMetrics)

Apache Spark verwendet die Dropwizard-Bibliothek, um Metriken zu senden. Einige der nativen Dropwizard-Metrikfelder sind jedoch nicht mit Azure Log Analytics kompatibel.Apache Spark uses the Dropwizard library to send metrics, and some of the native Dropwizard metrics fields are incompatible with Azure Log Analytics. Daher enthält diese Referenzarchitektur eine benutzerdefinierte Dropwizard-Senke und einen entsprechenden Reporter.Therefore, this reference architecture includes a custom Dropwizard sink and reporter. Die Metriken werden so formatiert, wie es von Azure Log Analytics erwartet wird.It formats the metrics in the format expected by Azure Log Analytics. Wenn Apache Spark Metriken meldet, werden auch die benutzerdefinierten Metriken für die falsch formatierten Fahrt- und Fahrpreisdaten gesendet.When Apache Spark reports metrics, the custom metrics for the malformed ride and fare data are also sent.

Als letzte Metrik wird im Azure Log Analytics-Arbeitsbereich der kumulative Fortschritt des strukturierten Spark-Streamingauftrags protokolliert.The last metric to be logged to the Azure Log Analytics workspace is the cumulative progress of the Spark Structured Streaming job progress. Hierzu wird in der Klasse com.microsoft.pnp.StreamingMetricsListener ein benutzerdefinierter StreamingQuery-Listener implementiert.This is done using a custom StreamingQuery listener implemented in the com.microsoft.pnp.StreamingMetricsListener class. Diese Klasse wird beim Ausführen des Auftrags bei der Apache Spark-Sitzung registriert:This class is registered to the Apache Spark Session when the job runs:

spark.streams.addListener(new StreamingMetricsListener())

Die Methoden in „StreamingMetricsListener“ werden von der Apache Spark-Runtime aufgerufen, wenn ein strukturiertes Streamingereignis auftritt. Dabei werden Protokollmeldungen und Metriken an den Azure Log Analytics-Arbeitsbereich gesendet.The methods in the StreamingMetricsListener are called by the Apache Spark runtime whenever a structured steaming event occurs, sending log messages and metrics to the Azure Log Analytics workspace. Zur Überwachung der Anwendung können Sie in Ihrem Arbeitsbereich die folgenden Abfragen verwenden:You can use the following queries in your workspace to monitor the application:

Wartezeit und Durchsatz für StreamingabfragenLatency and throughput for streaming queries

taxijob_CL
| where TimeGenerated > startofday(datetime(<date>)) and TimeGenerated < endofday(datetime(<date>))
| project  mdc_inputRowsPerSecond_d, mdc_durationms_triggerExecution_d
| render timechart

Ausnahmen, die während der Ausführung von Datenstromabfragen protokolliert wurdenExceptions logged during stream query execution

taxijob_CL
| where TimeGenerated > startofday(datetime(<date>)) and TimeGenerated < endofday(datetime(<date>))
| where Level contains "Error"

Kumulation falsch formatierter Fahrpreis- und FahrtdatenAccumulation of malformed fare and ride data

SparkMetric_CL
| where TimeGenerated > startofday(datetime(<date>)) and TimeGenerated < endofday(datetime(<date>))
| render timechart
| where name_s contains "metrics.malformedrides"

SparkMetric_CL
| where TimeGenerated > startofday(datetime(<date>)) and TimeGenerated < endofday(datetime(<date>))
| render timechart
| where name_s contains "metrics.malformedfares"

Auftragsausführung zur Nachverfolgung der ResilienzJob execution to trace resiliency

SparkMetric_CL
| where TimeGenerated > startofday(datetime(<date>)) and TimeGenerated < endofday(datetime(<date>))
| render timechart
| where name_s contains "driver.DAGScheduler.job.allJobs"

Weitere Informationen finden Sie unter Überwachung von Azure Databricks.For more information, see Monitoring Azure Databricks.

Bereitstellen der LösungDeploy the solution

Führen Sie zum Bereitstellen und Ausführen der Referenzimplementierung die Schritte aus der GitHub-Infodatei aus.To the deploy and run the reference implementation, follow the steps in the GitHub readme.