Konfiguracja Azure Functions i Table Storage, czyli jak prosto przechować swoje dane - część 1

Posted by Maciej Gos on Monday, August 6, 2018

Przechowywanie danych w modelu serverless nie musi być trudne i skomplikowane. Dzisiaj kolejny tydzień z Azure Functions w którym zajmiemy się przechowywaniem danych. Na pierwszy ogień pójdzie Table Storage.

O Azure Functions pisałem już w poprzednich częściach artykułów do, których serdecznie zapraszam

  1. Azure Functions na macOS? Pokażę Ci jak zacząć
  2. Jaki rodzaj rozliczania wybrać dla Azure Functions?
  3. Jak w 5 minut zbudować swoje pierwsze mock API w Azure Functions?
  4. Konfiguracja Azure Functions Routing Na 3 Sposoby
  5. Jak skonfigurować różne wersje interfejsu API w Azure Functions?
  6. Azure Functions i Swagger, czyli jak profesjonalnie zaprezentować nasze API

Natomiast jeżeli chcielibyście poczytać ogólnie o serverless możecie to zrobić tutaj. Serverless, do czego może się przydać w aplikacjach mobilnych?

Czym jest Table Storage?

Jest to najprostsza usługa w Azure stworzona do przechowywania danych typu „NoSQL”. Nie jest ona w żaden sposób rozbudowana i nie dostarczazaawansowanych funkcjonalności jak np. CosmosDB. Jest ona za to prosta, tania i szybka. Nasze dane są dodatkowo zapisywane z użyciem transakcji, orazpodlegają automatycznej replikacji do różnych datacenter.

Można w niej w bardzo prosty sposób przechować bardzo duże ilości danych. Jedna tabela jest w stanie przechować aż 500 TB danych. Table Storage pozwala na przechowanie do 252 unikalnych kolumn w tym 3 kolumny systemowe takie jak:

  • PartitionKey - używane jako element klucza głównego, oraz ustawiane przez programistę
  • RowKey - używane jako element klucza głównego, oraz ustawiane przez programistę
  • Timestamp - jest to data modyfikacji danego rekordu ustawiana automatycznie przez system

Połączenie Storage Account, Table i Partition Key pozwala systemowi zidentyfikować partycję na której znajdują się nasze dane. Pozwala nam również na używanie prostych typów danych takich jak:

  • byte[]
  • bool
  • DateTime
  • double
  • Guid
  • int
  • long
  • String

Po takim krótkim wprowadzeniu przejdźmy teraz do tzw. mięsa, czyli jak to wszystko ze sobą połączyć.

Jak połączyć Azure Functions i Table Storage

W Azure Functions w wersji v1 (runtime) można to było zrobić prosto z poziomu portalu wybierając jako output Table Storage. Azure Table Storage output

Od wersji v2 (preview) taka opcja znikneła z portalu i trzeba output skonfigurować ręcznie używając edytora. Advanced editor

Konfiguracja w portalu

Jako, że głównie się skupiam na funkcjach w wersji v2 dlatego też pokaże konfiguracje Table Storage dla funkcji które obecnie są nadal w wersji beta runtime. Zakładam, że mamy już stworzoną aplikacje i funkcje, oraz skonfigurowany odpowiedni runtime. Jak to zrobić znajdziecie w innych częściach serii o Azure Functions.

Klikamy w naszej funkcji opcję Integrate -> Advance editor. Pokaże nam się zawartość pliku function.json. Musimy dodać nowe wyjście z naszej funkcji używając JSON

{
  "name": "personTable",
  "direction": "out",
  "type": "table",
  "tableName": "personTable",
  "connection": "MyConnectionString"
}

Co my tu mamy?

  • “name”: “personTable” - nazwa naszego parametru w kodzie CSharp Script
  • “direction”: “out” - kierunek w którym nasz parametr będzie dostępny. Czy będzie wejście czy naszym wyjście z funkcji
  • “type”: “table” - typ parametru (table, queue )
  • “tableName”: “personTable” - nazwa naszej tabeli
  • “connection”: “MyConnectionString” - nasz connection string. do Table Storage

Finalny plik będzie wyglądał następująco

{ 
  "bindings": [ 
    { 
      "authLevel": "function", 
      "name": "req", 
      "type": "httpTrigger", 
      "direction": "in", 
      "methods": [ 
        "post" 
        ], 
      "route": "todo" 
    }, 
    { 
      "name": "$return", 
      "type": "http", 
      "direction": "out" 
    }, 
    { 
      "name": "personTable", 
      "direction": "out", 
      "type": "table", 
      "tableName": "personTable", 
      "connection": "MyConnectionString" 
    } 
  ] 
}

Konfiguracja w kodzie

Teraz zostaje nam konfiguracja w kodzie funkcji. Na początek zmienimy sygnaturę naszej metod i dodamy parametr

ICollector<Person> personTable

Aby dodać nowy wiersz musimy wywołać metodę Add.

personTable.Add(new Person());

Finalny kod naszej funkcji będzie wyglądał jak na poniższym listingu.

#r Newtonsoft.Json

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Newtonsoft.Json;

public static IActionResult Run(HttpRequest req, ICollector<Person> personTable, TraceWriter log)
{
  log.Info("C# HTTP trigger function processed a request.");
    
  string name = req.Query["name"];
  string requestBody = new StreamReader(req.Body).ReadToEnd();
  dynamic data = JsonConvert.DeserializeObject(requestBody);
  name = name ?? data?.name;

  var person = new Person { Name = name, RowKey = name, PartitionKey = "todoPartition" };
  personTable.Add(person);

  return name != null 
    ? (ActionResult)new OkObjectResult("Hello, {name}")
    : new BadRequestObjectResult("Please pass a name on the query string or in the request body"); 
}
    
 
public class Person
{
  public string RowKey { get; set; }
  public string PartitionKey { get; set; }
  public string Name { get; set; }
}

Podsumowanie

Na dziś koniec części pierwszej artykułu o Table Storage. W przyszłym tygodniu zajmiemy się konfiguracją funkcji w wersji pre-compiled.

Photo by chuttersnap on Unsplash

Maciej Gos

真诚赞赏,手留余香

使用微信扫描二维码完成支付


comments powered by Disqus