Samouczek: wprowadzenie do Azure Functions

W tym laboratorium dowiesz się, jak rozpocząć tworzenie aplikacji Azure Functions użyciu Visual Studio dla komputerów Mac. Zintegrujemy również z tabelami usługi Azure Storage, które reprezentują jeden z wielu rodzajów powiązań i wyzwalaczy dostępnych dla Azure Functions deweloperów.

Cele

  • Tworzenie i debugowanie lokalnych Azure Functions
  • Integracja z zasobami internetowymi i usługą Azure Storage
  • Organizowanie przepływu pracy obejmującego wiele Azure Functions

Wymagania

  • Visual Studio dla komputerów Mac 7.5 lub wyższa.
  • Subskrypcja platformy Azure (dostępna bezpłatnie w witrynie https://azure.com/free ).

Ćwiczenie 1. Tworzenie Azure Functions projektu

  1. Uruchom Visual Studio dla komputerów Mac.

  2. Wybierz pozycję > nowe rozwiązanie.

  3. W kategorii Cloud > General (Ogólne) wybierz Azure Functions szablon. Użyjemy języka C# do utworzenia biblioteki klas .NET, która hostuje Azure Functions. Kliknij przycisk Dalej.

    wybór szablonu usługi Azure Functions

  4. Ustaw nazwę Project na "AzureFunctionsLab", a następnie kliknij pozycję Utwórz.

    nazewnictwo i tworzenie projektu funkcji platformy Azure

  5. Rozwiń węzły w oknie rozwiązania. Domyślny szablon projektu zawiera NuGet do różnych pakietów Azure WebJobs, a także pakietu Newtonsoft.Json.

    Istnieją również trzy pliki: - host.json do opisywania globalnych opcji konfiguracji hosta — local.settings.json do konfigurowania ustawień usługi. — Szablon projektu tworzy również domyślny program HttpTrigger. Na potrzeby tego laboratorium należy usunąć plik HttpTrigger.cs z projektu.

    Otwórz local.settings.json. Domyślnie mają dwa puste ustawienia parametrów połączenia.

    okno rozwiązania z wyświetlonym plikiem local.settings.json

Ćwiczenie 2. Tworzenie konta usługi Azure Storage

  1. Zaloguj się do swojego konta platformy Azure na stronie https://portal.azure.com .

  2. W sekcji Ulubione po lewej stronie ekranu wybierz pozycję Storage konta:

    sekcja ulubionych w Azure Portal element kont magazynu

  3. Wybierz pozycję Dodaj, aby utworzyć nowe konto magazynu:

    Przycisk do dodawania nowego konta magazynu

  4. Wprowadź globalnie unikatową nazwę dla pola Nazwa i użyj jej ponownie dla grupy zasobów. Możesz zachować wszystkie inne elementy jako domyślne.

    szczegóły nowego konta magazynu

  5. Kliknij pozycję Utwórz. Utworzenie konta magazynu może potrwać kilka minut. Po pomyślnym utworzeniu otrzymasz powiadomienie.

    powiadomienie o pomyślnym wdrożeniu

  6. Wybierz przycisk Przejdź do zasobu w powiadomieniu.

  7. Wybierz kartę Klucze dostępu.

    ustawienie klucza dostępu

  8. Skopiuj pierwsze ciągi połączenia. Ten ciąg jest używany do integracji usługi Azure Storage z Azure Functions w późniejszym czasie.

    informacje dotyczące klucza 1

  9. Wróć do Visual Studio dla komputerów Mac i wklej pełne ciągi połączenia jako ustawienie AzureWebJobsStorage w local.settings.json. Teraz możesz odwoływać się do nazwy ustawienia w atrybutach dla funkcji, które wymagają dostępu do jego zasobów.

    plik ustawień lokalnych z wprowadzonym kluczem połączenia

Przykład 3: Tworzenie i debugowanie funkcji platformy Azure

  1. Teraz możesz rozpocząć dodawanie kodu. Podczas pracy z biblioteką klas .NET Azure Functions jako metody statyczne. W oknie rozwiązania kliknij prawym przyciskiem myszy węzeł projektu AzureFunctions i wybierz polecenie Dodaj > Dodaj funkcję:

    Opcja Dodaj funkcję

  2. W oknie dialogowym Azure Functions webhook Wybierz szablon Ogólny. Ustaw wartość Pola Nazwa na Dodaj, a następnie kliknij przycisk OK, aby utworzyć funkcję:

    Nowe okno dialogowe usługi Azure Functions

  3. W górnej części nowego pliku dodaj poniższe dyrektywy using:

    using Microsoft.Azure.WebJobs.Extensions.Http;
    using System.Web;
    using Microsoft.WindowsAzure.Storage.Table;
    
  4. Usuń istniejącą Run metodę i dodaj metodę poniżej do klasy jako funkcję platformy Azure:

    [FunctionName("Add")]
    public static int Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]
    HttpRequestMessage req,
    TraceWriter log)
    {
        int x = 1;
        int y = 2;
    
        return x + y;
    }
    
  5. Przejdźmy przez definicję metody fragment po części.

    Pierwszą rzeczą, jaką zobaczysz, jest atrybut FunctionName, który oznacza tę metodę jako funkcję platformy Azure. Atrybut wyznacza publiczną nazwę funkcji. Nazwa atrybutu nie musi odpowiadać rzeczywistej nazwie metody.

    Nowa metoda uruchamiania z wyróżniony atrybutem FunctionName

  6. Następnie metoda jest oznaczona jako publiczna metoda statyczna, która jest wymagana. Zauważysz również, że zwracana wartość to int. O ile nie określono inaczej przy użyciu atrybutów metody, każda niepusta wartość zwracana przez funkcję platformy Azure jest zwracana do klienta jako tekst. Domyślnie jest on zwracany w formacie XML, ale można go zmienić na format JSON, który zostanie później zrobiony w laboratorium.

    Nowa metoda uruchamiania z wyróżnioną inicjacją metody

  7. Pierwszy parametr jest oznaczony atrybutem HttpTrigger, który wskazuje, że ta metoda jest wywoływana przez żądanie HTTP. Atrybut określa również poziom autoryzacji metody, a także czasowniki, które obsługuje (w tym przypadku tylko "GET"). Możesz również opcjonalnie zdefiniować trasę, która zastępuje ścieżkę do metody i oferuje sposób automatycznego wyodrębniania zmiennych ze ścieżki. Ponieważ w tym miejscu trasa ma wartość null, ścieżka do tej metody domyślnie będzie mieć wartość /api/Add.

    Nowa metoda uruchamiania z wyróżnionym parametrem

  8. Ostatnim parametrem metody jest TraceWriter, który może służyć do rejestrować komunikaty dotyczące diagnostyki i błędów.

    Nowa metoda uruchamiania z wyróżnionym tracewriterem

  9. Ustaw punkt przerwania w wierszu zwracania metody, klikając margines wiersza:

    Punkt przerwania ustawiony w wierszu zwracania

  10. Skompilowanie i uruchomienie projektu w sesji debugowania przez naciśnięcie klawisza F5 lub wybranie polecenia Uruchom > Rozpocznij debugowanie. Możesz też kliknąć przycisk Uruchom. Wszystkie te opcje wykonują to samo zadanie. W pozostałej części tego laboratorium odwołuje się do klawisza F5, ale możesz użyć najbardziej wygodnej metody.

    Kompilowanie i uruchamianie projektu

  11. Uruchomienie projektu spowoduje automatyczne otwarcie aplikacji Terminal.

  12. Projekt przechodzi przez proces wykrywania Azure Functions na podstawie atrybutów metody i konwencji plików, która została pokryta w dalszej części tego artykułu. W tym przypadku wykrywa pojedynczą funkcję platformy Azure i "generuje" 1 funkcję zadania.

    Dane wyjściowe funkcji platformy Azure w terminalu

  13. W dolnej części komunikatów uruchamiania host Azure Functions drukuje adresy URL dowolnych interfejsów API wyzwalacza HTTP. Powinna być tylko jedna. Skopiuj ten adres URL i wklej go w nowej karcie przeglądarki.

    Adres URL interfejsu API funkcji platformy Azure

  14. Punkt przerwania powinien być wyzwalany natychmiast. Żądanie internetowe zostało kierowane do funkcji i można je teraz debugować. Najedz kursorem myszy na zmienną x, aby wyświetlić jej wartość.

    Wyzwolony punkt przerwania

  15. Usuń punkt przerwania przy użyciu tej samej metody, która została użyta do dodania go wcześniej (kliknij margines lub wybierz wiersz i naciśnij klawisz F9).

  16. Naciśnij klawisz F5, aby kontynuować działanie.

  17. W przeglądarce zostanie wyrenderowany wynik XML metody . Zgodnie z oczekiwaniami, operacja dodatku na dysku tworzy prawdopodobną sumę. Zwróć uwagę, że jeśli w przeglądarce Safari widzisz tylko "3", przejdź do pozycji Safari > Preferences > Advanced (Preferencje programu Safari > Zaawansowane) i zaznacz pole wyboru "Pokaż menu Tworzenie na pasku menu" i załaduj ponownie stronę.

  18. W Visual Studio dla komputerów Mac kliknij przycisk Zatrzymaj, aby zakończyć sesję debugowania. Aby upewnić się, że nowe zmiany są odbierane, nie zapomnij ponownie uruchomić sesji debugowania (zatrzymać ją, a następnie uruchomić).

    Opcja Zatrzymaj debugowanie

  19. W metodzie Run zastąp definicje x i y poniższym kodem. Ten kod wyodrębnia wartości z ciągu zapytania adresu URL, aby można było wykonać operację dodatku dynamicznie na podstawie podanych parametrów.

    var query = HttpUtility.ParseQueryString(req.RequestUri.Query);
    
    int x = int.Parse(query["x"]);
    
    int y = int.Parse(query["y"]);
    
    return x + y;
    
  20. Uruchom aplikację.

  21. Wróć do okna przeglądarki i dołącz ciąg /?x=2&y=3 do adresu URL. Cały adres URL powinien być teraz adresem http://localhost:7071/api/Add?x=2&y=3 . Przejdź do nowego adresu URL.

  22. Tym razem wynik powinien odzwierciedlać nowe parametry. Możesz uruchomić projekt z różnymi wartościami. Należy pamiętać, że nie ma żadnego sprawdzania błędów, więc nieprawidłowe lub brakujące parametry zwywają błąd.

  23. Zatrzymaj sesję debugowania.

Ćwiczenie 4. Praca z function.json

  1. We wcześniejszym ćwiczeniu wspomniano, że Visual Studio dla komputerów Mac "wygenerowała" funkcję zadania dla funkcji platformy Azure zdefiniowaną w bibliotece. Wynika to z Azure Functions, że program w rzeczywistości nie używa atrybutów metody w czasie wykonywania, ale zamiast tego używa konwencji systemu plików w czasie kompilacji do konfigurowania miejsca i sposobu, w jaki Azure Functions są dostępne. W oknie rozwiązania kliknij prawym przyciskiem myszy węzeł projektu i wybierz polecenie Reveal in Finder (Ujawnij w programie Finder).

    Opcja menu Ujawnij w programie Finder

  2. Przejdź w dół do systemu plików do momentu osiągnięcia bin/Debug/netstandard2.0. Powinien być folder o nazwie Dodaj. Ten folder został utworzony w celu odpowiadania atrybutowi nazwy funkcji w kodzie języka C#. Rozwiń folder Dodaj, aby ujawnić pojedynczy plik function.json. Ten plik jest używany przez środowisko uruchomieniowe do hostować funkcję platformy Azure i zarządzać tą funkcją. W przypadku innych modeli językowych bez obsługi w czasie kompilacji (na przykład skryptów języka C# lub JavaScript) te foldery należy tworzyć i obsługiwać ręcznie. W przypadku deweloperów języka C# są one generowane automatycznie na podstawie metadanych atrybutów podczas kompilacji. Kliknij prawym przyciskiem myszy pozycję function.json i wybierz ją, aby otworzyć ją w Visual Studio.

    plik function.json w katalogu plików

  3. Biorąc pod uwagę poprzednie kroki tego samouczka, musisz mieć podstawową wiedzę na temat atrybutów języka C#. Biorąc to pod uwagę, ten numer JSON powinien wyglądać znajomo. Istnieje jednak kilka elementów, które nie zostały uwzględnione we wcześniejszych ćwiczeniach. Na przykład każde powiązanie musi mieć ustawiony kierunek. Jak można wywnioskować, "in" oznacza, że parametr jest wejściowy, natomiast wartość "out" wskazuje, że parametr jest albo wartością zwracaną (za pośrednictwem $return ) albo parametrem wychodzącym metody. Należy również określić scriptFile (względem tej końcowej lokalizacji) i metodę entryPoint (publiczną i statyczną) w zestawie. W następnych kilku krokach dodasz niestandardową ścieżkę funkcji przy użyciu tego modelu, więc skopiujesz zawartość tego pliku do schowka.

    Plik function.json otwarty w programie Visual Studio dla komputerów Mac

  4. W oknie rozwiązania kliknij prawym przyciskiem myszy węzeł projektu AzureFunctionsLab i wybierz polecenie Dodaj > Nowy folder. Nazwij nowy folder Adder. Domyślnie nazwa tego folderu będzie definiować ścieżkę do interfejsu API, taką jak api/Adder.

    Opcja Nowy folder

  5. Kliknij prawym przyciskiem myszy folder Adder i wybierz polecenie Dodaj > Nowy plik.

    Opcja Nowy plik

  6. Wybierz kategorię Sieć Web i szablon Pusty plik JSON. Ustaw nazwę na funkcję i kliknij pozycję Nowy.

    Opcja pustego pliku JSON

  7. Wklej zawartość innego pliku function.json (z kroku 3) w pliku , aby zastąpić domyślną zawartość nowo utworzonego pliku.

  8. Usuń następujące wiersze w górnej części pliku JSON:

    "configurationSource":"attributes",
    "generatedBy":"Microsoft.NET.Sdk.Functions-1.0.13",
    
  9. Na końcu pierwszego powiązania (po wierszu "name": "req" dodaj poniższe właściwości). Pamiętaj, aby w poprzednim wierszu uwzględnić przecinek. Ta właściwość zastępuje domyślny katalog główny tak, aby teraz wyodrębniała parametry int ze ścieżki i umieszczała je w parametrach metody o nazwach x i y.

    "direction": "in",
    "route": "Adder/{x:int?}/{y:int?}"
    
  10. Dodaj kolejne powiązanie poniżej pierwszego. To powiązanie obsługuje wartość zwracaną funkcji. Pamiętaj, aby w poprzednim wierszu uwzględnić przecinek:

    {
    "name": "$return",
    "type": "http",
    "direction": "out"
    }
    
  11. Zaktualizuj również właściwość entryPoint w dolnej części pliku, aby użyć metody o nazwie "Add2", jak pokazano poniżej. Ma to na celu zilustrowanie, że ścieżka api/Adder... może zostać zamapowana na odpowiednią metodę o dowolnej nazwie (Dodaj2 tutaj).

    "entryPoint": "<project-name>.<function-class-name>.Add2"
    
  12. Końcowy plik function.json powinien wyglądać podobnie do następującego pliku json:

    {
    "bindings": [
        {
        "type": "httpTrigger",
        "methods": [
            "get"
        ],
        "authLevel": "function",
        "direction": "in",
        "name": "req",
        "route": "Adder/{x:int?}/{y:int?}"
        },
        {
        "name": "$return",
        "type": "http",
        "direction": "out"
        }
    ],
    "disabled": false,
    "scriptFile": "../bin/AzureFunctionsProject.dll",
    "entryPoint": "AzureFunctionsProject.Add.Add2"
    }
    
  13. Ostatnim krokiem wymaganym do tego, aby to wszystko działało, jest Visual Studio dla komputerów Mac skopiowanie tego pliku do tej samej ścieżki względnej w katalogu wyjściowym za każdym razem, gdy się zmienia. Po wybraniu pliku wybierz kartę właściwości na pasku po prawej stronie, a w obszarze Kopiuj do katalogu wyjściowego wybierz pozycję Kopiuj, jeśli jest nowsza:

    Opcje właściwości dla pliku JSON

  14. W pliku Add.cs zastąp metodę (w tym atrybut) następującą metodą, Run aby spełnić oczekiwaną funkcję. Jest bardzo podobny do , z tą różnicą, że nie używa żadnych atrybutów i Run ma jawne parametry dla x i y.

    public static int Add2(
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        return x + y;
    }
    
  15. Naciśnij klawisz F5, aby skompilować i uruchomić projekt.

  16. Po zakończeniu kompilacji i po zakończeniu działania platformy będzie ona wskazywać, że dla żądań mapowych na nowo dodaną metodę jest dostępna druga trasa:

    Adres URL funkcji Http

  17. Wróć do okna przeglądarki i przejdź do strony http://localhost:7071/api/Adder/3/5 .

  18. Tym razem metoda ponownie działa, ściągając parametry ze ścieżki i tworząc sumę.

  19. Wróć do Visual Studio dla komputerów Mac i zakończ sesję debugowania.

Ćwiczenie 5. Praca z tabelami usługi Azure Storage

Często kompilowana usługa może być znacznie bardziej złożona niż to, co skompilowaliśmy do tej pory, i wymagać znacznego czasu i/lub infrastruktury do wykonania. W takim przypadku efektywne może okazać się akceptowanie żądań, które są w kolejce do przetworzenia, gdy zasoby staną się dostępne, co Azure Functions zapewnia obsługę. W innych przypadkach należy przechowywać dane centralnie. Tabele Storage Azure pozwalają to szybko wykonać.

  1. Dodaj klasę poniżej do add.cs. Powinna ona być wewnątrz przestrzeni nazw, ale poza istniejącą klasą.

    public class TableRow : TableEntity
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Sum { get; set; }
    }
    
  2. W klasie Add dodaj poniższy kod, aby wprowadzić inną funkcję. Należy pamiętać, że ta jest unikatowa do tej pory, ponieważ nie obejmuje odpowiedzi HTTP. Ostatni wiersz zwraca nowy element TableRow wypełniony pewnymi kluczowymi informacjami, które ułatwiają późniejsze pobieranie wartości (PartitionKey i RowKey), a także jego parametry i sumę. Kod w metodzie używa również tracewriter, aby ułatwić wiedzieć, kiedy funkcja jest uruchamiana.

    [FunctionName("Process")]
    [return: Table("Results")]
    public static TableRow Process(
        [HttpTrigger(AuthorizationLevel.Function, "get",
            Route = "Process/{x:int}/{y:int}")]
        HttpRequestMessage req,
        int x,
        int y,
        TraceWriter log)
    {
        log.Info($"Processing {x} + {y}");
    
        return new TableRow()
        {
            PartitionKey = "sums",
            RowKey = $"{x}_{y}",
            X = x,
            Y = y,
            Sum = x + y
        };
    }
    
  3. Naciśnij klawisz F5, aby skompilować i uruchomić projekt.

  4. Na karcie przeglądarki przejdź do strony http://localhost:7071/api/Process/4/6 . Spowoduje to dodanie kolejnego komunikatu do kolejki, co ostatecznie powinno spowodować dodanie kolejnego wiersza do tabeli.

  5. Wróć do terminalu i obserwuj żądanie przychodzące dla 4 + 6.

    Dane wyjściowe terminalu przedstawiające żądanie dodatku

  6. Wróć do przeglądarki, aby odświeżyć żądanie pod tym samym adresem URL. Tym razem po metodzie Process zostanie wyświetlony błąd. Jest to spowodowane tym, że kod próbuje dodać wiersz do tabeli usługi Azure Table Storage przy użyciu kombinacji klucza partycji i wiersza, która już istnieje.

    System.Private.CoreLib: Exception while executing function: Process. Microsoft.Azure.WebJobs.Host: Error while handling parameter $return after function returned:. Microsoft.Azure.WebJobs.Host: The specified entity already exists.
    
  7. Zakończ sesję debugowania.

  8. Aby uniknąć błędu, dodaj następujący parametr do definicji metody bezpośrednio przed parametrem TraceWriter. Ten parametr instruuje platformę Azure Functions, że próbuje pobrać tabelę TableRow z tabeli Results w kluczu PartitionKey, której używaliśmy do przechowywania wyników. Jednak w przypadku zauważenia, że klucz RowKey jest generowany dynamicznie na podstawie innych parametrów x i y dla tej samej metody, pojawia się jednak prawdziwa magia. Jeśli ten wiersz już istnieje, tableRow będzie go miał, gdy metoda rozpocznie się bez dodatkowej pracy wymaganej przez dewelopera. Jeśli wiersz nie istnieje, będzie on miał po prostu wartość null. Tego rodzaju wydajność umożliwia deweloperom skoncentrowanie się na ważnej logice biznesowej, a nie na infrastrukturze.

    [Table("Results", "sums", "{x}_{y}")]
    TableRow tableRow,
    
  9. Dodaj poniższy kod na początku metody . Jeśli tableRow nie ma wartości null, mamy już wyniki dla żądanej operacji i możemy ją natychmiast zwrócić. W przeciwnym razie funkcja będzie działać tak jak poprzednio. Chociaż może to nie być najbardziej niezawodny sposób zwracania danych, ilustruje to punkt, w którym można orkiestrować niezwykle zaawansowane operacje w wielu skalowalnych warstwach przy użyciu bardzo małego kodu.

    if (tableRow != null)
    {
        log.Info($"{x} + {y} already exists");
        return null;
    }
    
  10. Naciśnij klawisz F5, aby skompilować i uruchomić projekt.

  11. Na karcie przeglądarki odśwież adres URL pod adresem http://localhost:7071/api/Process/4/6 . Ponieważ wiersz tabeli dla tego rekordu istnieje, powinien zostać zwrócony natychmiast i bez błędu. Ponieważ nie ma żadnych danych wyjściowych HTTP, dane wyjściowe są dostępne w terminalu.

    Dane wyjściowe terminalu pokazujące, że wiersz tabeli już istnieje

  12. Zaktualizuj adres URL, aby odzwierciedlał kombinację, która nie została jeszcze przetestowana, na przykład http://localhost:7071/api/Process/5/7 . Zanotuj komunikat w terminalu, który wskazuje, że wiersz tabeli nie został znaleziony (zgodnie z oczekiwaniami).

    Dane wyjściowe terminalu przedstawiające nowy proces

  13. Wróć do Visual Studio dla komputerów Mac i zakończ sesję debugowania.

Podsumowanie

W tym laboratorium nauczyliśmy się, jak rozpocząć tworzenie Azure Functions za pomocą Visual Studio dla komputerów Mac.