In den letzten beiden Einträgen Azure Functions „“ Simple JavaScript Tutorial und Azure Functions „“ Vollgas mit dem Service-Bus haben wir unsere Azure Funktionen entwickelt und diese im Azure Portal getestet. Ist man in einer Azure Subscription unterwegs, die als Spielwiese oder fürs Testen gedacht ist, kann es noch praktikabel sein, etwas direkt im Portal zu entwickeln bzw. zu testen. Laufen jedoch bereits Produktiv-Systeme in der Subscription kommt man damit sehr schnell in Teufels Küche. Man stelle sich mal vor, dass wir nach dem Testen die falsche Funktion löschen oder wir uns verschrieben haben und unsere Testdaten in der Produktiv Queue landen „¦
Ich könnte noch weitere Beispiele nennen, aber ich denke, wir sind uns schon jetzt einig, dass dies nicht der Ideale Weg sein kann. Bei Azure Functions „“ Vollgas mit dem Service-Bus haben wir die Entwicklung unserer Funktionen daher schon aus dem Portal in unsere lokale Umgebung verlagert. Da wäre es jetzt natürlich noch super, wenn wir diese auch lokal testen und debuggen könnten. Vorneweg gesagt, ja man kann lokal debuggen und testen, doch nicht alles „¦ dazu aber später mehr.
Für das lokale Entwickeln und testen bietet uns Microsoft die Azure Functions Core Tools an. Die Azure Functions Core Tools sind eine lokale Version der Function Runtime. Daher gibt es zwei Versionen der Core Tools, zum einen für die Runtime Version 1.x und zum zweiten für die Version 2.x. Für unsere Beispiele haben wir die Version 1.x der Runtime genutzt, weil nur diese aktuell für Produktiv-Umgebungen zugelassen ist.
Die Version 1.x nutzt das .NET-Framework und unterstützt so nur die Plattform Windows. Beide Versionen der Core Tools stehen als npm Pakete zur Verfügung und könnten mittels nodeJS installiert werden. Wer es noch nicht installiert hat, findet nodeJs für Windows unter https://nodejs.org/en/download/. Nach der Installation kann man mittels dem Node.js Command Prompt oder der Windows Eingabeaufforderung (CMD) die Azure Functions Core Tools installieren (Abbildung 1).
Abbildung 1
Nach der erfolgreichen Installation können wir mittels func init ein lokales Azure Funktionen-Projekt erstellen (Abbildung 2). Dabei wird auch ein lokales Git Repository generiert. Wir führen diesen Befehl in dem in Azure Functions „“ Vollgas mit dem Service-Bus erstellten Projekt Ordner aus. In unserem Fall wird kein lokales Git Repository erstellt, da wir schon mit unserem Remote Repository verbunden sind. Wie in Abbildung 2 zu sehen, werden einige Dateien erstellt. In der host.json können übergreifende Einstellungen für die Funktionen hinterlegt werden. In der local.settings.json stehen die nötigen Einstellungen für das lokale Ausführen der Funktionen. In der launch.json finden sich die benötigten Informationen, um die Funktionen lokal im Visual Studio Code (https://code.visualstudio.com/) zu debuggen.
Neben func init gibt es den Befehl func new. Mit func new können wir eine Funktion erstellen. Dabei werden anhand des gewählten Templates die function.json und die index.js erstellt.
Der Befehl unterstützt folgende Optionen:
- –language -l
Damit können wir die Sprache für die Funktion angeben (C#, JavaScript“¦) - –template -t
Name der Vorlage, die genutzt werden soll, z. B. HTTP Trigger wenn man eine Funktion mit einem HTTP Trigger entwickeln möchte. - –name -n
Name der Funktion.
Lässt man die Optionen weg, bekommt man eine Auswahl der verfügbaren Sprachen und Templates angezeigt und kann unter diesen die passenden wählen (Abbildung 1b).
Abbildung 1b
Abbildung 2
So, Schritt eins ist nun geschafft. Einige Trigger bzw. Bindungen haben eine Connection-Eigenschaft, die im Portal in der Funktionen-App konfiguriert wird. Beim lokalen Ausführen müssen diese Verbindungseigenschaften in der local.settings.json hinterlegt werden. Es gibt zwei Wege, um dies zu erfüllen. Der erste besteht darin, die Informationen aus einer Funktionen-App zu beziehen. Das bedeutet, dass z. B. Nachrichten in einer Warteschlange (Queue) abgelegt werden, die in der Funktionen-App konfiguriert ist. Nutzt man diesen Weg sollte man eine Warteschlange (Azure Service Bus) und eine Funktionen-App für Testzwecke anlegen. Dafür führt man folgenden Befehl aus: func azure functionapp fetch-app-settings
Abbildung 3
Abbildung 4
Wie am Anfang erwähnt, kann nicht alles lokal getestet werden. Für den Azure Service Bus gibt es meines Wissens aktuell keinen Emulator. Wer seine Subscription nicht für Testzwecke nutzen möchte, kann in diesem Falle ein Service Bus für Windows Server installieren (https://msdn.microsoft.com/library/azure/jj193022(v=azure.10).aspx).
Zur Vereinfachung nutzen wir in diesem Beispiel unsere Azure Subscription.
Der Vollständigkeit halber sei erwähnt, dass es für den Azure Storage einen Emulator gibt. Der Azure Speicheremulator emuliert die Blob-, Warteschlangen- und Tabellendienste von Azure. Weitere Informationen findet man unter https://docs.microsoft.com/de-de/azure/storage/common/storage-use-emulator#differences-between-the-storage-emulator-and-azure-storage. Dort werden auch die Unterschiede zwischen dem Emulator und den Azure Storage aufgezählt. Bei der Warteschlange handelt es sich um eine Storage Queue, nicht um eine Service Bus Queue. Wie man den Speicheremulator installiert und konfiguriert, zeige ich kurz am Ende des Beitrags.
Nun aber zurück zu unserem Beispiel. Mit dem Befehl func host start werden die Trigger für alle Funktionen im Projekt (Funktion-App) aktiviert. Mit der Option – – debug vscode wird das Debuggen mittels Visual Studio Code (VSCode) ermöglicht (Abbildung 5). Weitere Optionen von host start können Abbildung 5a entnommen werden.
Abbildung 5
Abbildung 5a
Nach dem Starten der Funktionen kann mittels F5 bzw. über den Menüpunkt „Debuggen“ /“Debuggen starten“ im Visual Studio Code der Debugger aktiviert werden. In Abbildung 6 sieht man im unteren Bereich des VSCode, dass sich der Debugger an die Funktionen des Projekts „functionServiceBusTest“ gebunden hat. Dem Debuggen steht nun nichts mehr im Weg.
Abbildung 6
Benötigt die Funktion Testdaten, können diese mit Hilfe von HTTP Testtools wie cURL oder Postman übermittelt werden. Die Aufruf URL der Funktionen baut sich wie folgt auf: http://localhost:{port}/api/{function_name}.
Bei einer Funktion mit einem HTTP Trigger, der einen Übergabeparameter erwartet, würde der Aufruf wie in Abbildung 7 aussehen.
Abbildung 7
Bei Funktionen die nicht mittels eines HTTP Triggers ausgelöst werden, lautet die Aufruf-URL http://localhost:{port}/admin/functions/{function_name}. Wir werden nun mit Postman unsere Funktion „FunktionServiceBusReader“ aufrufen und als Nachricht „Mein Text“ übermitteln.
Dazu erstellen wir bei Postman einen neuen POST Request und geben dort die Aufruf URL http://localhost:9090/admin/functions/FunktionServiceBusReader ein. Als Content Typ wird im Reiter „Headers“ application/json ausgewählt. Im Reiter „Body“ geben wir den Content wie folgt ein:
{ „input“: „Mein Text“ } und senden den Request ab (Abbildung 8). Hat alles funktioniert, sollten wir im CMD (Windows Eingabeaufforderung) bzw. dem Node.js Command-Prompt-Fenster die Ausgabe ServiceBus Message Mein Text sehen (Abbildung 9).
Abbildung 8
Abbildung 9
Somit können wir nun unsere Funktionen lokal debuggen und zum Teil lokal testen. Beim Einsatz des Service Bus ist es aktuell, wie erwähnt, nicht möglich, komplett lokal zu testen.
Wie weiter oben angekündigt, schauen wir uns zum Schluss noch an, wie man den Azure Speicheremulator installiert und konfiguriert. Der Azure Speicheremulator benötigt eine lokale Microsoft SQL Server Instanz. Zu diesem Zweck können wir die SQL Server 2017 Express Edition nutzen (https://www.microsoft.com/de-de/sql-server/sql-server-editions-express). Nach der Installation der SQL Server 2017 Express Edition müssen wir noch den Speicheremulator installieren (https://go.microsoft.com/fwlink/?linkid=717179&clcid=0x409).
Nach Abschluss der Installationen wählen wir die Schaltfläche Start aus, geben dort „Azure Storage Emulator“ ein und wählen diesen aus. Daraufhin wird der Speicheremulator gestartet und initialisiert. Zuerst wird dabei geprüft, ob es eine MSSQLLocalDB-Instanz gibt. Da dies bei uns nicht der Fall ist, wird geprüft, ob es eine andere SQL-Instanz auf dem System gibt. Wie man in Abbildung 10 sieht, findet das System die eben installierte SQL Express Instanz und konfiguriert sie. Nach Abschluss der Konfiguration läuft der Speicheremulator und kann von unseren Funktionen lokal genutzt werden.
Abbildung 10
Um nun den Speicheremulator nutzen zu können, muss die local.settings.json angepasst werden. Dazu weisen wir AzureWebJobsStorage den Wert UseDevelopmentStorage=true zu (Abbildung 11). Die Endpoints z. B. für den Blob Storage bekommen wir mit dem Befehl AzureStorageEmulator.exe status angezeigt und können diese bei Bedarf in die local.settings.json übernehmen (Abbildung 12).
Abbildung 11
Abbildung 12
Wie wir gesehen haben, können wir unsere Funktionen debuggen und mit einigen Einschränkungen lokal testen. Mit dem Einsatz des Azure Speicheremulators und dem Service Bus für Windows Server kann man auch komplett losgelöst von einer Azure Subscription arbeiten. Gesagt sei das wir mit den Emulatoren die Azure Plattform nicht zu 100% abbilden können. Die aktuell praktikabelste Lösung ist die Erstellung einer Development / Testing Stage in der Cloud. So können die benötigten Komponenten, in unserem Beispiel der ServiceBus, direkt in der Laufzeitumgebung getestet werden. Durch eine eigene Stage hat man auch eine Saubere Trennung zur Live Umgebung. Falls man aus den kostenfreien Kontingenten herausläuft, kann die separate Stage bei nicht Nutzung ausgeschaltet werden.