Serverless: Ohne Server in die Azure-Cloud
Seite 2: Polyglotter Datenbankdienst
Neben den Serverless-Compute-Instanzen zum Berechnen und Verarbeiten von Daten bietet Microsoft die Azure Cosmos DB als Speicher für diese Daten an. Azure Cosmos DB ist ein Datenbankdienst, der Daten bei Bedarf automatisch global verteilt und mehrere, verschiedene Sprachen/APIs für Abfragen unterstützt. Beim Anlegen eines neuen "Azure Cosmos DB"-Kontos ist die zu nutzende API auszuwählen. Aktuell stehen APIs für SQL, MongoDB, Gremlin (Graph), Azure Storage Table und Cassandra zur Verfügung. Mit Ausnahme der SQL API lassen sich alle anderen APIs auch mit existierenden Treibern beziehungsweise Clients nutzen, was die Umstellung von existierenden Anwendungen vereinfacht und so den Weg in die Serverless-Cloud vereinfacht. Die ausgewählte API gilt allerdings für alle Datenbanken innerhalb des "Azure Cosmos DB"-Kontos.
Die Daten werden innerhalb einer Datenbank als schemaloses JSON-Dokument in Sammlungen gespeichert und zwar unabhängig von der genutzten API. Eine Sammlung ist vergleichbar mit einer Tabelle und bildet einen Container, der die JSON-Dokumente beinhaltet. Bei den abgelegten JSON-Dokumenten erfolgt automatisch eine Indizierung aller Daten, sodass ein schnelles Abfragen der Daten gewährleistet ist. Alternativ lassen sich eigene Indizierungsrichtlinien anlegen, um beispielsweise die Schreibgeschwindigkeit zu erhöhen.
Um die Abfragegeschwindigkeit global verteilter Anwendungen zu verbessern, lässt sich eine Azure Cosmos DB sehr einfach global replizieren. Die Replizierung lässt sich mittels eines Klicks auf einer Weltkarte im Azure-Portal steuern und ist somit einfach einzurichten. Zu beachten ist, dass es derzeit nur eine Schreib-Master-Region gibt. Multi-Master-Unterstützung ist in Vorbereitung, bisher aber nur als Preview verfügbar.
Neben den verschiedenen APIs und der globalen Replikation ist die Lese- und Schreibgeschwindigkeit von Azure Cosmos DB ein großer Vorteil. Microsoft garantiert für ein typisches 1 KByte großes JSON-Dokument eine Ende-zu-Ende-Wartezeit von 10 ms bei Lesevorgängen und weniger als 15 ms bei indizierten Schreibvorgängen im 99. Perzentil.
Für die SQL API von Azure Cosmos DB bietet Microsoft einen Client an, der sich in .NET, Java, Node.js und Python nutzen lässt. Da für die anderen APIs kein spezieller Client notwendig ist, sondern sich existierende Treiber/Clients nutzen lassen, ist man hier prinzipiell nicht auf bestimmte Sprachen beschränkt.
Für Konten mit einer SQL- oder Graph API lassen sich in Azure Functions auch Trigger, Eingabe- und Ausgabebindungen nutzen. Der Trigger wird dabei über ein Änderungsfeed ausgelöst, welches eine Sammlung auf Veränderungen überwacht. Sobald sich also Dokumente in einer Sammlung verändern oder aber hinzugefügt oder entfernt werden, lässt sich eine Azure Function auslösen.
Beispiel: Azure Function mit CosmosDB-Eingabe-Bindung
Das folgende C#-Beispiel zeigt eine Azure Function, die ein Produkt in den Einkaufskorb des Benutzers legt. Das Auslösen der Funktion erfolgt durch einen HTTP-Aufruf. In der Route des HTTP-Aufrufs ist die ID des Produkts enthalten. Durch die CosmosDB-Eingabe-Bindung wird das Produkt aus der Sammlung "products" in der Datenbank "store" anhand der ProductId geladen. Das ShoppingCargItem wird mittels eines IAsyncCollector in der Sammlung "shoppingcart" der Datenbank "store" angelegt.
[FunctionName("AddToShoppingCart")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "ShopingCart/{productId}")]HttpRequest req,
[CosmosDB("store", "products", ConnectionStringSetting = "CosmosDbConnectionString", Id = "{productId}")] Product product,
[CosmosDB("store", "shoppingcart", ConnectionStringSetting = "CosmosDbConnectionString")] IAsyncCollector<ShoppingCartItem> shoppingCart)
{
var userId = GetUserId(req);
var item = new ShoppingCartItem(){
UserId = userId.Value,
Product = product
};
await shoppingCart.AddAsync(item);
return new OkResult();
}
private static Guid? GetUserId(HttpRequest request) {
// User ID aus request extrahieren.
}
public class Product {
public Guid Id { get; set; }
public string Name { get; set; }
}
public class ShoppingCartItem {
public Guid UserId { get; set; }
public Product Product { get; set; }
}