Der Code im Nichts?

Die Serverless Cloud – eine Einführung (Teil 2): Der FaaS-Anbieter-Vergleich

Bart Blommaerts

©Shutterstock / vs148

Im zweiten Teil der Reihe „Serverless Cloud“ schreibt JAX-Speaker Bart Blommaerts über Auth0, Webtask, Google Cloud Functions, Azure Functions und IBM Bluemix OpenWhisk.

Dieser Artikel wurde ursprünglich in englischer Sprache  auf  Bart Blommaerts‘ Blog Daggie.be veröffentlicht. Zudem hielt er auf der diesjährigen JAX London den thematisch passenden Vortrag „The Serverless Cloud“.

Im ersten Teil der Serie habe ich den serverlosen („serverless“) Architekturstil vorgestellt und mich hauptsächlich auf den „Market Maker“ AWS Lambda und das Serverless Framework konzentriert. In diesem Teil möchte ich mich anderen FaaS-Anbietern zuwenden.

Auth0 Webtask

Im Vergleich mit Giganten wie Amazon, Google, Microsoft oder IBM ist Auth0 ein eher kleiner Akteur. bedenkt man jedoch die Erfahrung, die Auth0 mit BaaS (Backend as a Service) hat, ist FaaS für dieses Unternehmen der nächste logische Schritt. Derzeit unterstützt Webtask nur NodeJS.

Empfohlen wird die Nutzung von Webtask über das wt Command Line Interface. Der Fokus von Auth0 wurde dabei ganz klar auf eine einfache Benutzbarkeit gelegt, wie das 30 Sekunden Beispiel deutlich zeigt. Das Kommando wt create generiert eine Funktion (einen webtask) und gibt automatisch einen HTTP-Endpoint zurück, der URL-Query-Parameter unterstützt. Jeder der Query-Parameter ist innerhalb des Webtasks als context.data-JavaScript-Objekt verfügbar. Mit AWS Lambda müsste man diese Objekte erst noch im AWS API Gateway konfigurieren, was sowohl zeitraubend als auch mühsam ist.

Ein sehr interessantes Feature von Webtask ist die Verfügbarkeit eines eingebauten Speichers. Webtask kann ein JSON-Dokument mit bis zu 500KB speichern. Derart gespeicherte Daten können mittels ctx.storage.set gespeichert und per ctx.storage.get abgerufen werden. Obwohl die eigenen Funktionen dieses Feature vermutlich nicht allzu oft benötigen werden, ist es schön, diese Option zur Verfügung zu haben.

Das folgende kleine Beispiel (in Lodash) zeigt einen Webtask, der Query-Parameter und den eingebauten Speicher verwendet.

module.exports = function (ctx, cb) {
    var name = ctx.query.name;
  
    if(name) {
        ctx.storage.get(function(err, data){
            if(err) cb(err);
  
            data = data || [];
  
            if(_.indexOf(data, name) === -1 ){
                data.push(name);
  
                ctx.storage.set(data, function(err){
                    if(err){
                        cb(err);
                    } else {
                        cb(null, data);
                    }
                })
            } else {
                cb(null, data);
            }
        })
    } else {
        cb(null, "422");
    }
}

Deploying des Webtasks per CLI:

Webtask created
  
You can access your webtask at the following url:
  
https://webtask.it.auth0.com/api/run/wt-<your username>-0/query_store?webtask_no_cache=1

Auf einen Webtask lässt sich allerdings auch in Form eines CRON-Jobs, mit dem wt cron-Befehl, oder über Web Hook zugreifen.

Im Gegensatz zu AWS Lambda müssen die verwendeten NodeJS-Module nicht gebündelt werden. Eine Liste von unterstützten Modulen ist hier einsehbar und eine Option zur Bündelung von anderen Modulen gibt es natürlich auch. Ein weiterer Unterschied ist die Nutzung von Query-Parametern.

Es überrascht niht, dass Auth0 für die Authentifizierung und Authorisation in Webtask integriert werden kann.

Google Cloud Functions

Die Google Cloud Functions (GCF) wurden Anfang 2016 veröffentlicht und befinden sich zurzeit in einer geschlossenen Alpha. Der Status einer geschlossenen Alpha-Phase bedeutet nicht nur, dass man die Verwendung der GCF API beantragen muss, sondern auch, dass man im Teilen von Informationen stark eingeschränkt ist. Obwohl das natürlich sehr unschön ist, zeigt es ebenfalls, dass Google ernsthaft vorhat, ein vollständiges Produkt zu releasen. Die Aktivitäten der (ebenfalls geschlossenen) Google Group beweist dies.

Wie die Konkurrenzprodukte, können die Cloud Functions asynchron durch Events (von Cloud Pub/Sub und Cloud Storage) oder synchron via HTTPS aufgerufen werden. Derzeit unterstützen die GCF nur NodeJS. Tutorials zu gewöhnlichen Use-Cases sind in der Dokumentation einsehbar. Um mit den GCF arbeiten zu können, muss allerdings zuerst das Google Cloud SDK heruntergeladen und installiert werden – nachdem das passiert ist, kann man eine initiale Funktion erstellen (datastore_gcf muss dafür durch den Namen des eigenen Staging Buckets ersetzt werden):

$ gsutil mb gs://datastore_gcf

Aus den (sehr nützlichen) (inoffiziellen) GCF-Snippets von Jason Polites (Product Manager, GCP) haben wir das Beispiel eines Datenspeichers geklont, das Daten an einen Google Cloud Datenspeicher weitergibt.

Aus dem Repository haben wir, mittels der nachfolgenden Codezeile, zwei Funktionen, ds-get und ds-set, deployt:

$ gcloud alpha functions deploy ds-set --bucket datastore_gcf --trigger-http --entry-point set

Die Namen der deployten Funktionen müssen in das Node.js-Modul exportiert werden. Sie können wie folgt aufgerufen werden:

$ gcloud alpha functions call ds-get --data '{"kind": "test", "key": "kid"}'

Alternativ ist es auch möglich, sie via Google Functions Console aufzurufen.

Die neu hinzugefügten Daten sind auch in den Datenspeicherobjekten („Datastore Entities“) verfügbar, nachdem ein Projekt ausgewählt wurde. Nach dem Ausführen einiger Funktionen, kann man zudem einige Metriken der Funktion einsehen (Anzahl der Aufrufe, Ausführungszeit, …).

Weitere Argumente für den Deploy-Befehl können der Dokumentation entnommen werden. Die gezeigten Schritte sind außerdem in der Konsole der Cloud Plattform verfügbar.

Nach dem Deployment wird die Webtrigger URL ähnlich wie in Webtask angezeigt werden.

Obwohl es noch nicht viele öffentlich zugängliche Informationen zu den Google Cloud Functions gibt, ist Google auf dem besten Weg, ein ernsthafter FaaS-Anbieter zu werden.

Azure Functions

Ähnlich der Google Cloud Functions sind die Microsoft Azure Functions derzeit noch im Preview, was bedeutet, dass sie (noch) nicht in effektiver Produktionsumgebung verwendet werden sollten. Die Azure Cloud Functions (ACF) bieten Support für eine Vielzahl von Sprachen, wie etwa NodeJS, C#, Python und PHP.

Aktuell können sie für die folgenden Fälle genutzt werden:

  • Events, die von anderen Azure Services getriggert wurden
  • Events, die von SaaS-Services getriggert wurden (nicht auf Microsoft beschränkt)
  • Synchrone Requests
  • WebHooks
  • Timer-basiertes Processing (CRON)

Dies eröffnet eine recht große Anzahl an Möglichkeiten, die ACF zu nutzen.

Azure Functions sind in sogenannte App Services gruppiert und unterscheiden sich damit wesentlich von AWS Lambda, wo die Funktionen unabhängig voneinander organisiert werden. Hardwareressourcen werden einzelnen App Services und nicht einer konkreten Azure-Funktion zugewiesen. Es ist wichtig einen dynamischen App Service zu wählen, wenn man auf „pay-per-execution“ abzielt.

Beim Erstellen einer neuen Funktion kann zwischen verschiedenen Vorlagen gewählt werden, was vergleichbar mit den Blueprints von AWS Lambda ist. Derzeit sind 44 Vorlagen verfügbar, wobei einige sich sehr ähnlich sind. Wenn beispielsweise der HttpTrigger ausgewählt wird, erzeugt Azure Functions eine Funktion, die alle an die Funktion übergebenen Query-Parameter, verwenden kann – ähnlich wie bei Webtask. Dieses kurze Video verdeutlicht dies.

Im folgenden Beispiel speichert eine Azure-Cloud-Funktion Entitäten in einer Speichertabelle, sobald sie einen HTTP-Request empfängt:

"bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ],
      "authLevel": "function"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "table",
      "name": "outTable",
      "tableName": "entities",
      "partitionKey": "functions",
      "rowKey": "%rand-guid%",
      "connection": "YOUR_STORAGE",
      "direction": "out"
    }
  ],
  "disabled": false
}
var statusCode = 400;
    var responseBody = "Invalid request object";
  
    if (typeof req.body != 'undefined' && typeof req.body == 'object') {
        statusCode = 201;
        context.bindings.outTable = req.body;
        responseBody = "Table Storage Created";
    }
  
    context.res = {
        status: statusCode,
        body: responseBody
    };
  
    context.done();
};

Und um die hinzugefügten Elemente abzurufen:

"bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get"
      ],
      "authLevel": "function"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "table",
      "name": "inTable",
      "tableName": "entities",
      "connection": "YOUR_STORAGE",
      "direction": "in"
    }
  ],
  "disabled": false
}
context.log("Retrieved records:", intable);
    context.res = {
        status: 200,
        body: intable
    };
    context.done();
};

Über die Funktions-URL (siehe Abb.1) kann man synchrone Requests ausführen:

Abb.1

Abb.1

Was mir sofort auffiel, war die Qualität der Dokumentation (Videos, Quickstarts, Templates, …) und die Nutzerfreundlichkeit des Azure Portals. Es kann mitunter etwas langsam sein, aber es ist im Sinne der Bedienbarkeit den Angeboten von Amazon und Google um Lichtjahre voraus. Azure Functions ist Open Source auf GitHub erhältlich. Demnächst wird Azure Functions zudem vom Serverless Framework supportet, was ein großer Schritt in Richtung eines anbieterneutralen FaaS ist.

IBM Bluemix OpenWhisk

Bei Bluemix OpenWhisk handelt es sich ebenfalls um einen Open-Source-Dienst, der derzeit NodeJS und Swift unterstützt. Im Gegensatz zu anderen FaaS-Anbietern, hat IBM seinen Fokus auf die Container-Integration gelegt. Wenn ein Event- oder ein API-Call eine Action hervorruft, erstellt OpenWhisk einen Container, der die aufgerufene Action in einer zur verwendeten Programmiersprache passenden Laufzeitumgebung ausführt. Es können sogar Docker-Funktionen (in OpenWhisk Actions genannt) erstellt werden, die es erlauben sämtliche Programmiersprachen einzubauen. Zudem kann OpenWhisk lokal auf der eigenen Hardware ausgeführt werden, was kein anderer Anbieter derzeit anbietet. IBM ist sehr offen was das betrifft und bietet sogar Leitfäden, wie dies durchzuführen ist.

Wie erwartet, beinhaltet die Dokumentation eine Anleitung, die das Erstellen und Ausführen des ersten „Hello World!“ dokumentiert. Während die Arbeit mit dem CLI wie beworben funktioniert, wird es, insbesondere wenn andere Bluemix-Dienste integriert werden, schnell mühselig. Nachdem die erste OpenWhisk-Funktion ausgeführt wurde, kann man einige Metriken im (hübschen) OpenWhisk-Dashboard sehen. Das OpenWhisk-Dashboard zeigt alle aufgerufenen Actions an – selbst jene, die nicht von ihnen selbst implementiert wurden, da sie z.B. aus bereits existierenden Paketen stammen, die verwendet werden.

Abb.2

Abb.2

Noch beeindruckender ist allerdings der OpenWhisk-Editor. Er listet ausschließlich die Actions auf, die selbst erstellt wurden:

Abb.3

Abb.3

Wie in dem Screenshot ersichtlich wird, erhält man sofort Links zum REST-Endpoint.

Fazit

Derzeit ist es noch zu früh, um irgendwelche Schlussfolgerungen zu ziehen, denn die Services ändern sich ständig. Was klar ist, ist jedoch, dass keiner der großen Cloud-Anbieter die FaaS-Chance verpassen will. Cloud-Anbieter erhöhen ihren Wert, indem sie FaaS-Services zu ihrer Produkt-Palette hinzufügen und auch integrieren. Dies unterstreicht auch allgemein den Wert der Serverless Cloud. Die aktuellen FaaS-Lösungen sind sich allesamt sehr ähnlich und eine eigene Wahl hängt vermutlich tendenziell davon ab, welche anderen Dienste eines Anbieters man bereits verwendet oder in Zukunft verwenden will. Es ist wichtig, die Umgebung eines FaaS-Codes und die für diesen zur Verfügung stehenden Dienste zu kennen. In dieser Phase ist die vorhandene Dokumentation ebenfalls entscheidend.

Natürlich enthält diese High-Level-Einführung nicht alle Unterschiede und Gemeinsamkeiten, aber sie bietet einen guten Ausgangspunkt, um die FaaS-Revolution aus erster Hand zu erleben.

Geschrieben von
Bart Blommaerts
Bart Blommaerts
Bart ist leidenschaftlicher Architekt von Apps. Er glaubt, es ist essentiell die Lücke der Model-Codes zu schließen, um schnelle, agile Deliveries nachhaltig zu machen. Bart hat einen starken Focus auf API Design, Wiederverwertung, Automatisierung und Sicherheit. Er ist ständig auf der Suche nach technischen Herausforderungen. Außerdem ist Bart im Aufsichtsrat von verschiedenen JWorks Competence Center Leads bei Ordina.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu: