Azure BLOB Storage nutzen


Die meisten Applikationen benötigen einen Platz zum Speichern von Daten. Je nach Datentyp, Datenmenge, Zugriff und der damit verbundenen Methode zum Zugriff auf die Daten können verschiedenste Speichermodelle eingesetzt werden. Mit den Azure Services kommen neben den herkömmlichen Varianten weitere, neue Mechanismen hinzu, die genutzt werden können. Dieser Artikel befasst sich mit Zugriff auf Azure BLOB Storage.

Wofür BLOB?

BLOB steht für Binary Large OBject. Darunter versteht man große, binäre Objekte, wie etwa Dateien oder andere unstrukturierte Daten. BLOBs werden im Regelfall nicht in (klassischen) Datenbanken gespeichert und können nicht oder nur mit viel Aufwand strukturiert gespeichert werden.

Azure Storage Blobs eignet sich also vor allem zum Persistieren von etwa Dateien: (Viele) völlig unterschiedliche Daten, die sicher in der Cloud gespeichert werden sollen. Der Zugriff darauf kann mit Tools, wie etwa dem Azure Storage Explorer oder vielen weiteren Tools (siehe etwa auch Jürgens Tipp hier) erfolgen, oder natürlich mit eigenem Code in der eigenen App. Hier geht es darum, eigenen Code zu verwenden.

Dieses kleine Tutorial führt duch die Verwendung von Azure Storage Blob. Auch wenn wir hier bereits in einigen Artikeln über die Verwendung von BLOBs geschrieben haben, möchte ich hier ein Code-Update und eine aktuelle Zusammenfassung für die eigene Verwendung posten.

Das Konzept von BLOB Storage

BLOB Storage ist so organisiert, dass die Inhalte (Files) in einem Container liegen müssen, die wiederrum einem Storage Account zugeordnet sind (siehe hier).

image

Der Zugriff auf einen BLOB erfolgt über einen HTTP-Request in diesem Format:
http://<storage-account-name>.blob.core.windows.net/<container-name>/<blob-name>

also etwa:
http://sally.blob.core.windows.net/movies/MOV1.AVI

Für die Benennung von Containern gibt es einige Regeln, wie etwa “alles kleinschreiben”, keine Sonderzeichen, 3 bis 63 Zeichen nur mit Buchstaben, Nummern und dem Dash (-“) Zeichen. Auch für die Blob-Files gelten besondere Regeln, wie etwa “Blob names are case-sensitive”. Alle Regeln finden sich hier.

Gehen wirs’ an.

Projekt erstellen

Zunächst wird ein neues Projekt in Visual Studio 2015 angelegt. Dabei wird das Template Visucal C# – Cloud – QuickStarts – Data Services – Azure Storage: Blobs ausgewählt.

image

Der Wizard generiert ein Projekt. Dabei werden Referenzen zu den erforderlichen Bibliotheken hinzugefügt (wie etwa die Microsoft.WindowsAzureStorage Referenz).

image

Nach dem ersten Compile werden die NuGet Packages automatisch nachgeladen.

Packages aktualisieren

Alternativ – etwa bei bestehenden Projekten – können die Bibliotheken natürlich auch selbst im NuGet Package Manager hinzugefügt werden… (die Suche nach Azure bringt die Storage-Bibliothek gleich am Anfang der Liste), oder in der Package Manager Console mit Install-Package WindowsAzure.Storage geladen werden.

image

Der NuGet Package Manager kann auch verwendet werden, die installierte Version und alle Abhängigkeiten gleich zu aktualisieren – was ich sogleich getan habe. Damit werden die Pakete im \packages Verzeichnis sogleich aktualisiert und hier ist das Update auf WindowsAzure.Storage.6.2.0 erfolgt. Das Beispielprojekt kann wieder compiliert werden, somit haben wir gute Voraussetzungen.

Cloud Explorer

Am einfachsten ist das Erstellen von Ressourcen mit dem integrierten Cloud Explorer. Der Cloud Explorer kommt mit dem Microsoft Azure SDK for .NET (VS 2015) – 2.7 oder 2.8 mit. Die Installation erfolgt mit dem Web Platform Installer.

image

Blob Container erstellen und verwenden

Der Cloud Explorer integriert sich in Visual Studio (siehe auch hier, in Welcome to Visual Studio 2015 with Azure! oder Azure Tools). Hiermit wird ein neuer Container “documents” erstellt.

image image

Dieser kann auch gleich verwendet werden:

image

Somit werden gleich ein paar Files upgeloadet (Multi Select klappt):

image

Schön dabei ist die Integration und auch die Anzeige der File Properties.

image

Die Demo Files können mit dem Cloud Explorer verwaltet werden.

image

Soweit so gut. Dieser Exkurs dient zum Verständnis, dass sich Azure Blob Storage ähnlich wie ein Filesystem verhält.

Alles lokal?

Vorerst ja. Der Azure-Speicheremulator bietet eine lokale Umgebung, die die Azure-Dienste für Blobs, Warteschlangen und Tabellenspeicher für Entwicklungszwecke emuliert. App.config verwendet in dem Beispiel UseDevelopmentStorage=true.

image

Im realen Betrieb müssen dann nur der ConnectionString zum “echten” Azure Storage Endpoint getauscht werden (der Key steht darunter und muss nur auskommentiert und angepasst werden).

Let it run

Das Beispiel-Projekt kann sofort ausgeführt werden (F5). Der Output zeigt auch gleich, was hier drin passiert: Files werden in neue azure Blob-Container upgeloadet, angezeigt, downgeloadet und wieder gelöscht.

image

Die Main Methode in Program.cs ruft zwei Methoden zur Demonstration für den Blob-Zugriff auf:

  • BasicStorageBlockBlobOperationsAsync().Wait();
  • BasicStoragePageBlobOperationsAsync().Wait();

image

Drei BLOB-Typen: Block, Page, Append

Azure BLOB Storage kennt drei verschiedene BLOB-Typen. Somit möchte ich hier über den Unterschied der beiden verwendeten Methoden im Beispiel informieren und die Arten der Blob-Speicher kurz beschreiben. Dabei ist wichtig, dass der Typ eines Blobs beim Erstellen bestimmt wird und nicht mehr geändert werden kann.

  1. Block-Blobs sind ideal zum Speichern von Text- oder Binärdateien, also etwa für Dokumente und Mediadaten. Block-Blobs bestehen aus Blöcken von bis zu 4MB, von denen jeder durch eine Block-ID identifiziert wird. Zum Ändern müssen also bestimmte Blöcke geschrieben und mit Commit ausgeführt werden. Ein Block-Blob kann bis zu 50.000 Blöcke enthalten, somit ist die maximale Größe eines Block-Blobs etwa 195 GB (4MB * 50.000 Blöcke).
  2. Page-Blobs bestehen aus 512-Bytes-Seiten und sind für zufällige Lese- und Schreibzugriffe optimiert. So verwenden etwa Virtuelle Azure-Computer Page-Blobs für Betriebssystem und Datenträger. Beim Erstellen muss eine maximale Größe, etwa 2 * 512 Bytes = 1024 Bytes, angegeben werden. Ein Schreibvorgang erfolgt unter Angabe eines Offsets und kann nur eine Seite, mehrere Seiten oder bis zu 4 MB des Seiten-BLOB überschreiben und es wird kein zusätzliches Commit benötigt. Die maximale Größe für ein Page-Blob beträgt 1 TB.
  3. Append-Blobs bestehen aus Blöcken, die für das kontinuierliche Hinzufügen von Daten optimiert sind, etwa für Logfiles und ähnliche Anwendungen. Das Aktualisieren oder Löschen von vorhandenen Blöcken wird nicht unterstützt, nur das Anhängen von Daten. Die Block-ID ist nicht sichtbar. Die maximale Größe beträgt ebenso 195GB.

Für detaillierte Infos siehe Grundlegendes zu Block-BLOBs, Anhang-BLOBS und Seiten-BLOBs und Verwenden des Blob-Speichers mit .NET.

Wie funktionieren Block-Blobs?

Sehen wir uns die Funktionsweise von BasicStorageBlockBlobOperationsAsync an:

  • Der Beginn des Codes kümmert sich um den storageAccount und dass der Container existiert.
    image
  • Für den Zugriff wird zunächst ein storageAccount aus dem ConnectionString erzeugt.
    CloudStorageAccount storageAccount = CreateStorageAccountFromConnectionString(…);
  • Danach wird ein blobClient erstellt und es wird versucht, eine Referenz auf den Container “democontainerblockblob” zu erstellen.
  • Im Try-Block wird versucht, den Container zu erstellen. Dies erfolgt direkt in der Storage-Bibliothek in einer CloudBlobContainer Methode.
    image
  • Wenn die Voraussetzungen erfüllt sind (sprich, der Container “democontainerblockblob” existiert) gehts weiter im Code.
    image
  • Nun wird ein neues CloudBlockBlob Objekt erzeugt und es wrd versucht, dieses asnychron upzuloaden.
    CloudBlockBlob blockBlob = container.GetBlockBlobReference(ImageToUpload);
    await blockBlob.UploadFromFileAsync(ImageToUpload, FileMode.Open);

    Beim Upload wird auch das Commit durchgeführt. Das wars mit dem Upload.
  • Die Anzeige erfolgt ebenso einfach mit der ListBlobs() Methode und einer foreach Schleife:
    foreach (IListBlobItem blob in container.ListBlobs())
    {
    // Blob type will be CloudBlockBlob, CloudPageBlob or CloudBlobDirectory
    // Use blob.GetType() and cast to appropriate type to gain access to properties specific to each type
    Console.WriteLine("- {0} (type: {1})", blob.Uri, blob.GetType());
    }
  • Der Download kann mit der DownloadToFileAsync Methode erfolgen:
    await blockBlob.DownloadToFileAsync(string.Format("./CopyOf{0}", ImageToUpload), FileMode.Create);
    Das Ergbnis zeigt die downgeloadete Datei im bin Folder:
    image
  • Und danach wird das Demofile gelöscht:
    await blockBlob.DeleteAsync();

In diesem Beispiel sieht man, dass der Zugriff dank der Storage-Class sehr einfach erfolgt.

Wie funktionieren Page-BLOBs?

Methode BasicStoragePageBlobOperationsAsync funktioniert analog zu Beispiel Block-Blob, nur mit dem Unterschied, dass hier dieser Blob-Typ verwendet wird.

  • Wie zuvor wird der storageAccount erzeugt und der Container “democontainerpageblob” existiert. (Hier wird ein eigener Container verwendet).
    image
  • Neu hier ist das Erstellen des pageBlob mit 1024 Bytes maximale Größe.
    CloudPageBlob pageBlob = container.GetPageBlobReference(PageBlobName);
    await pageBlob.CreateAsync(512 * 2 /*size*/); // size needs to be multiple of 512 bytes
  • Hier werden 512 Zufalls-Bytes hineingeschrieben:
    byte[] samplePagedata = new byte[512];
    Random random = new Random();
    random.NextBytes(samplePagedata);
    await pageBlob.UploadFromByteArrayAsync(samplePagedata, 0, samplePagedata.Length);

    Es ist kein Commit erforderlich.
    image
  • Im Code geht es mit der Anzeige, Download und Löschen weiter:
    image
  • Das Anzeigen passiert dann seitenweise, solange Inhalt (resultSegment) des pageBlob Elements vorhanden ist:
    BlobContinuationToken token = null;
    do
    {
    BlobResultSegment resultSegment = await container.ListBlobsSegmentedAsync(token);
    token = resultSegment.ContinuationToken;
    foreach (IListBlobItem blob in resultSegment.Results)
    {
    // Blob type will be CloudBlockBlob, CloudPageBlob or CloudBlobDirectory
    Console.WriteLine("{0} (type: {1}", blob.Uri, blob.GetType());
    }
    } while (token != null);
  • Das Downloading erfolgt ähnlich wie zuvor:
    int bytesRead = await pageBlob.DownloadRangeToByteArrayAsync(samplePagedata, 0, 0, samplePagedata.Count());
  • Das Löschen ebenso:
    await pageBlob.DeleteAsync();

Der Zugriff auf PageBlob ist somit nicht ganz so einfach wie auf Block-Blobs. Das Demo zeigt aber die grundsätzliche Herangehensweise.

Fazit

Das generierte Beispiel aus den QuickStarts zeigt die grundsätzliche Verwendung von BLOB-Storage in eigenen Projekten. Die Verwendung von großen Files und Permissions auf die Files bleiben hier Außen vor, aber der Zugriff erfolgt sehr einfach.

Je nach Anforderung kann der Einsatz von Block-, Page- oder Append-Blobs in der eigenen Anwendung Sinn machen. Weitere Informationen über die Vewendung von Blob-Storage aus Code gibt es hier und hier.

Viel Spaß beim Experimentieren mit Azure BLOB Storage!