Die Idee eines serverlosen Blogs und ein neues Theme

by Armin 0 Comments

Nachdem ich mich schon seit einiger Zeit mit serverlosen Webseiten beschäftige (siehe Post 1 und Post 2) wollte ich diesen Ansatz auch auf diesen Blog hier übernehmen. Ein serverloser Blog basiert im Grunde einfach auf statischen HTML-Seiten, die dann – wie bereits beschrieben – über ein CDN ausgeliefert werden können; ohne, dass serverseitige Preprocessor-Verarbeitungen anfallen würden. Nachdem es gerade bei einem Blog viele Querverweise gibt (chronologische Post-Liste verteilt auf mehrere blätterbare Seiten, Kategorien, Tags, …) wäre es sehr umständlich diese Seiten alle manuell zu erstellen.
Ein Beispiel: Bei diesem Blog hier wären das über 1.180 statische HTML-Dateien in über 800 Ordnern verteilt. Bei jedem Post, der dazu kommt, müsste sowohl eine Post-Datei, die Übersichts-Datei(en), die Kategorie-Datei(en) und die Files der Tags geändert werden. Wenn man dann beispielsweise nur 10 Posts pro Seite anzeigt und auch eine blättern-Funktion hat, dann sind das schnell mal 50 Files die geändert werden müssten, wenn nur ein einziger Post dazu kommt. Der Aufwand wäre enorm.

Aus diesem Grund gibt es für statische Webseiten Tools, die denn Text des Posts aus Quell-Dateien einlesen und dann automatisiert alle HTML-Files generieren. Der wohl prominenteste Vertreter dieser Engines ist Jekyll, von einem der GitHub Co-Founder. Ganz anfreunden konnte ich mich mit Jekyll aber nicht. Außerdem ist die Software für Windows nicht offiziell supported. Ich wollte aber eine Lösung, die auf allen Systemen läuft, da ich teilweise Windows, teilweise Mac und ggf. auch Linux im Einsatz habe. Auf der Suche nach Alternativen bin ich auf Hexo gestoßen. Hexo ist durch Node.js mit npm auch auf Windows leicht einzurichten und funktioniert nach dem gleichen Prinzip wie Jekyll. Praktisch ist auch, dass man Posts aus anderen Blog-Software-Lösungen (etwa WordPress) importieren kann.

hexo

Nach der Installation und der Definition des Arbeitsverzeichnisses mit hexo init kann man mit hexo server einen Webserver starten, der die statischen Files anbietet. Beim Schreiben eines neuen Posts wird im Unterordner /sources/_posts/ eine .md-Datei angelegt, die alle wichtigen Informationen und den eigentlichen Text enthält. Das schaut dann etwa so aus:

---
title: Hello World
date: 2000-01-01 12:00:00
categories:
- Allgemeines
tags:
- test
---
Welcome to [Hexo](https://hexo.io/)! This is your very first post.

Anschließend genügt ein hexo generate um alle Files im Ordner /public/ zu aktualisieren. Dieser Ordner kann in weiterer Folge einfach auf ein CDN hoch geladen werden – und schon läuft der statische Blog.

So weit, so gut … nur: Ohne serverseitige Dynamik gibt es keine Kommentarfunktion – denn wo sollten die Kommentare hin gespeichert werden, wenn am (nicht vorhandenen) Server kein Preprocessor läuft? Die meisten Static-Webseit-Blog-User greifen dafür auf den Dienst Disqus zurück. So kann man Kommentare zum Post ermöglichen. Wirklich schön finde ich diese Möglichkeit aber nicht. Denn erstens passt das Layout von Disqus nicht wirklich zum individuellen Blog-Design und zweitens würde ich mir das lieber selbst programmieren.

Um eine eigene Kommentar-Funtkion zu ermöglichen, könnte man auf AWS Lambda zurück greifen. Zusammen mit dem API Gateway, SNS und einer DynamoDB könnte man so eine gute Kommentarfunktion entwicklen: Der User füllt das Formular aus, das statisch in die Post-Seite des Blogs integriert ist. Die Daten werden via API Gateway an Lambda geschickt, dort validiert und in eine DynamoDB geschrieben. Das DynamoDB Document enthält eine Referenz zum entsprechenden Blog-Post. Zusätzlich kann man noch SNS nutzen, um sich als Blog-Autor über den neuen Kommentar informieren zu lassen und diesen ggf. moderieren. Beim Laden der entsprechenden Post-Seite muss dann einfach über einen XHR eine Anfrage an das API Gateway gestellt werden. Eine so getriggerte Lambda-Funktion schaut dann in der DynamoDB nach und liefert die entsprechenden Kommentare zurück.

So würde ich das jedenfalls machen. Momentan fehlt mir aber die Zeit dazu. Deshalb habe ich mich, wie ihr vielleicht schon bemerkt habt, vorläufig dafür entschieden, dass ich einfach das Theme des Blogs ändere und werde mir die Sache mit Hexo später nochmal etwas genauer ansehen. Auch deshalb, weil das erstellen von Themes mit Hexo nicht in 10 Minuten erledigt ist. Um da ein schönes Layout zu basteln, ist einige Zeit notwendig … vermutlich sogar mehr, als für die Kommentarfunktionen mit Lambda.

Kurzurlaub in der Steiermark

by Armin 0 Comments

Heute mal ein ganz anderes Thema. Urlaub, Wellness, Entspannung! 🙂

Die letzten Tage haben wir einen Kurztripp in die Steiermark unternommen. Wir haben uns ein paar Tage in Bad Waltersdorf erholt und die Seele baumeln lassen. Nach 6 Stunden Fahrzeit (wir sind über Lienz gefahren, weil wir da noch jemanden mit genommen haben) sind wir endlich am Ziel angekommen. Die Heiltherme in Bad Walterdorf ist ein riesiges Areal, dessen Anfang sogar mit einem eigenen Ortsschild gekennzeichnet wird. Wir haben im Quellenhotel eingecheckt, das direkt an die Therme angeschlossen ist.

badwaltersdorf01

Der Empfang war sehr freundlich. Die Zimmer haben wir dann auch gleich gefunden. Allerdings fand ich das Zimmer relativ klein und ehrlich gesagt, war ich davon (und vor allem vom Bad) etwas enttäuscht. Bei ca. 270,- Euro pro Nacht (für 2 Personen mit Halbpension) hätte ich mir ein etwas größeres Zimmer mit einer Badewanne im Bad erwartet, nicht ein kleines Zimmer mit einem Bad, in dem man sich gerade einmal alleine umdrehen kann. Auch die Aussicht (auf die anderen Zimmer und den „Innenhof“) war suboptimal. Insofern war der erste Eindruck vom Zimmer … naja. Nachdem ich ja erst vor gut einer Woche in Wien war und dort um ca. 65,- Euro in einem größeren Zimmer übernachtet hatte, war ich wohl auch extra kritisch.

Allerdings, und das soll auch gleich erwähnt werden, war das kleine Zimmer wirklich der einzige Kritikpunkt. Alles andere war tip-top! Das Quellenhotel besteht aus 4 Gebäuden, die sich in unterschiedliche Himmelsrichtungen erstrecken. Insofern heißen die Gebäude auch Süd, West, Nord und Ost. Das Gebäude Süd sieht man im linken oberen Bereich des obigen Bildes.

Bei unserer Verwöhn-Halbpension war neben dem Frühstück auch ein 4-Gänge-Abendmenü inkludiert. Die Auswahl am Salat- (und teilweise) Nachspeisenbuffet war 1A. Auch die angebotenen Hauptspeisen (immer 3 zur Auswahl: Fleisch, Fisch, vegetarisch) waren alle sehr, sehr gut. Das Personal war stehts sehr zuvorkommend und freundlich.

Aber kommen wir zum wichtigsten bei einem Thermenurlaub – der Therme. Diese ist direkt vom Zimmer aus im Bademantel zu erreichen. Fährt man vom Hotel aus in das zweite Untergeschoss, dann landet man in einem Gang der direkt in die „weiter unten liegende“ Thermenlandschaft führt. (Das Heilthermen-Areal ist am Hang gelegen.) Dort gibt es dann mehrere Innenbecken und auch vier Außenbecken. Neben den Hotelgästen sind da auch die Tagesgäste zu finden, die einfach mal einen Tag in die Therme wollen. Wegen dem verlängerten Wochenende war deshalb recht viel los.

badwaltersdorf02

Aber auch dafür gibt es eine Lösung: Neben der auch öffentlich zugänglichen Therme hat das Hotel auch noch einen eigenen Wellnessbereich im Anschluss an das Gebäude „West“. Auch dieses kann direkt vom Zimmer aus im Bademantel erreicht werden, ohne in’s Freie zu müssen. Im hoteleigenen Bereich ist logischer Weise weniger los, weil da keine Tagesgäste zu finden sind. Neben einem Innenbecken gibt es dort auch einen Außenbereich der neben normalen Becken auch einen Badeteich beinhaltet. Da quaken die Frösche und es schwimmen Wasserschlangen durch das Wasser. Mit 15 °C war uns der Teich aber zu kalt. Die Idylle kann man auch aus dem 36°C warmen Becken mit Thermalwasser genießen, das direkt in den Badeteich integriert ist. Etwas entspannenderes gibt es nicht. 🙂

Alles in allem kann man also zusammenfassen, dass der Urlaub in Bad Waltersdort super war. Wir werden da sicher wieder einmal hin fahren. Lediglich die Zimmer waren nicht über-drüber groß, aber da hält man sich sowieso nicht primär auf.

Nächste Woche geht es dann nach Wien. Um das 4 Sterne-Hotel in Bad Walterdorf zu toppen, werden wir da im 5-Sterne-Hotel Le Méridien einchecken. Ich freu mich schon und werde dann hier wieder berichten.

 

Ich bin jetzt AWS-zertifiziert :-)

by Armin 0 Comments

Nach dem AWSomeDay im Le Méridien Wien habe ich gleich für den Folgetag eine Zertifizierungsprüfung zum AWS Certified Solutions Architect – Associate geplant. Dabei handelt es sich um eine von 5 Zertifizierungen, die AWS anbietet. (Es gibt drei Prüfungen auf Associate-Level und zwei auf Professional-Niveau, die jeweils eine der Associate-Zertifizierungen voraussetzen.)

Meine Prüfung dauerte 80 Minuten und beinhaltete 60 Fragen. Das ist übrigens nicht immer so: Denn AWS-Prüfungen haben mal ein bisschen mehr Fragen, mal ein bisschen weniger. Es wird nicht einmal bekannt gegeben, wie viele Punkte bzw. Prozent der richtig beantworteten Fragen notwendig sind, um die Prüfung zu bestehen. Im Hintergrund wird das Bestehen einer Prüfung von einem Algorithmus auf Basis einer Bell-Kurve berechnet, soweit ich gelesen habe. Recht interessanter Ansatz, den ich bisher noch nicht kannte. Im Endeffekt, kann man aber wohl davon ausgehen, dass man die Prüfung mit 70% besteht.

Als Vorbereitung auf die Prüfung habe ich den entsprechenden (sehr empfehlenswerten) Kurs von A Cloud Guru durch gemacht, mir eine 19-seitige Zusammenfassung und 17 Seiten mit Beispielfragen zusammen geschrieben. A Cloud Guru bietet im Rahmen des Kurses auch ein Probeexamen an, das 60 Fragen beinhaltet. Das habe ich 3x durch gemacht, jedes mal 15-20 Minuten gebraucht und bei allen Versuchen mindesten 93% errecht.

Das echte Examen, das man übrigens über Kryterion ablegen muss und in Österreich auch nur in Wien ablegen kann, war dann aber noch um einiges schwieriger. Von den 60 Fragen habe ich im ersten Durchlauf 20 als „unsicher“ markiert und habe mir diese dann in einem zweiten Durchlauf nochmal angesehen. Gesamt habe ich für die Prüfung über 75 Minuten gebraucht, also fast die komplette, zur Verfügung stehende, Zeit ausgeschöpft.

aws-asa-cert

Lange Rede, kurzer Sinn: Seit heute bin ich nun jedenfalls zertifizierter Lösungsarchitekt für die Amazon-Wolke. 🙂

Alle prüfungsrelevanten Themen hat der Online-Kurs leider nicht voll abgedeckt. Auch wenn A Cloud Guru den Kurs laufend aktualisieren und erweitern, so muss man doch schon auch ein gutes Stück praktische Erfahrung mit bringen. (AWS selbst schreibt dazu: „Mindestens ein Jahr praktische Erfahrung mit der Konzeption verfügbarer, wirtschaftlicher, fehlertoleranter und skalierbarer verteilter Systeme in AWS.“) Ich habe mich aber in den letzten Wochen und Monaten recht intensiv mit AWS beschäftigt, wie man auch hier im Blog immer wieder lesen kann. Vor allem serverlose Architekturen mit Lambda habe es mir angetan – in diese Richtung werde ich bestimmt noch einiges machen. Und wenn mir zu langweilig wird: Es gäbe da ja nach 4 andere AWS-Prüfungen. Der nächste logische Schritt wäre die Zertifizierung zum AWS SysOps Administrator – das Kursmaterial habe ich mir schon gekauft.

An AWSomeDay in Vienna

by Armin 1 Comment

AWSome – nein, ich hab kein „e“ bei awesome vergessen: AWSome ist viel mehr ein Event von Amazon Web Services (AWS), das in diversen Städten auf der Welt eine Einführung in die Services von AWS gibt. In Österreich fand heute der AWSome Day in Wien statt. Geschätzte 50 Teilnehmer aus Österreich und anderen Ländern ließen sich dabei von Sébastien Stormacq von AWS die Services von AWS näher bringen.

Nachdem ich bereits zum AWS Summit (einem etwas größeren AWS-Event) nach Berlin fahren wollte, das dann aber leider nicht geklappt hat, habe ich mich entschlossen, den AWSome Day in Wien zu besuchen und habe es nicht bereut.

awsomeday2016

Impressionen vom AWSomeDay 2016 in Wien.

Neben der Erklärung der wichtigsten Dienste (S3, EC2, VPC, EBS, …) wurde auch auf recht neue Services, wie etwa Lambda, eingegangen. Ein praktisches Beispiel wurde mit dem Simple Mustache Service gezeigt (siehe links oben im Bild) – einer Demo-WebApp, die auf drei unterschiedliche Arten implementiert wurde: Als einzelne EC2-Instanz, als Cluster hinter einem ELB mit S3 für static Files und als Lambda-Funktion mit API-Gateway.

Alles in allem ein tolles Event, das man nur jedem empfehlen kann, der sich für AWS interessiert. Man hat selten die Gelegenheit, an einem einzigen Tag einen so guten Einblick in AWS zu bekommen.

Focus 15: 15 Minuten Workouts von Mark Lauren

by Armin 0 Comments

Endlich wieder einmal ein Fitness-Post!

Fitnessbegeisterte Leser meines Blogs kennen sicher Mark Lauren: Ehemaliger Ausbilder beim US Militär und Champion im Thaiboxen, Rekordhalter im militärischen Apnoe-Tauchen … aber vor allem bekannt für seine Bodyweight-Trainings. Etwa Fit ohne Geräte (englisch: You Are Your Own Gym), Fit ohne Geräte für Fortgeschrittene (englisch: EFX – Elite Functional Exercise) oder das Mobility Workout (englisch: Mobility Rx)

Ab heute ist das neueste Training von Mark auf Amazon verfügbar: Focus 15. Wie der Name schon vermuten lässt, handelt es sich dabei um Trainings die in 15 Minuten erledigt sind. Sie sind also für alle Leute geeignet, die nicht viel Zeit in das Training investieren können oder wollen. Zugegebenermaßen muss man zu den 15 Minuten aber noch ein Warm-Up und ein Cool-Down dazu rechnen. Entsprechende Videos sind auch dabei, aber nicht in den 15 Minuten inbegriffen.

Ich habe das Glück zu den auserwählten Mitgliedern des Launch Teams von Mark zu gehören und konnte die Workouts bereits vorab testen: Focus 15 besteht aus drei Einheiten, die einen Unterschiedlichen Fokus haben. Beine und Gesäß, Total Core und Oberkörper. Jede Einheit besteht aus 6 Übungen die in 3 Blöcken (á 2 Übungen) absolviert werden. Wer sich also mit geringem Zeitaufwand fit halten möchte, ist bei Focus 15 genau richtig.

Fitness-Tracker: Von Garmin Vivosmart bis Fitbit Blaze

by Armin 0 Comments

Ein Uhrenfan war ich schon immer. Egal ob klassisch analog oder digital mit Fitness-Funktionen. Alleine was die zweite Kategorie betrifft, hatte ich bereits einige Modelle in Verwendung:

Angefangen habe ich mit einer Garmin Vivosmart mit Brustgurt. Den Brsutgurt fand ich immer etwas störend, aber dafür war die Form und Einfachheit der Vivosmart selbst bestechend. Ich habe die dann einem Kollegen verkauft, der nach wie vor seine Freude damit hat.

Darauf folgte dann eine Garmin Forerunner 225, die einen integrierten optischen Pulssensor verwendet. Der Sensor hat so mittelprächtig funktioniert. An den Brustgurt der Vivosmart kam die Genauigkeit natürlich nicht heran. Außerdem hat die Forerunner 225 auch GPS integriert. Wäre ein tolles Gerät gewesen – wenn da nicht die Hautirritationen aufgetreten wären, wegen denen ich die Forerunner leider nicht mehr verwenden konnte.

Danach habe ich mir wieder eine Vivosmart gewünscht, weil mir die Smart Notifications auch irgendwie abgingen. Damals (Ende 2015) gab es die neue Vivosmart HR von Garmin. Toll, dachte ich: Smart Notifications und integrierter Pulssensor. Da konnte ich auch damit leben, dass kein GPS integriert ist. Leider hat der Pulssensor komplett versagt. Selbst bei einem hoch-intensiven Training (HIIT), bei dem ich kaum mehr Luft zum Atmen hatte, zeigte mir das Vivosmart in 90% der Fälle einen Puls von 52 Schlägen pro Minute an – wirklich immer genau 52. Ich habe sogar mit der Garmin-Hotline telefoniert und gefragt ob „52“ irgend ein Standardwert ist, den die Vivosmart anzeigt, wenn sie den Puls nicht mehr messen kann. Das wurde aber verneint. Man teilte mir lediglich mit, dass die Vivosmart HR für so einen Trainingsart wohl einfach nicht geeignet sei. Mittlerweile habe ich das Tracken von Aktivitäten mit der Vivosmart HR aufgegeben. Die Pulswerte stimmen leider überhaupt nicht. (Sie zeigt selten über 60 bpm an.) Da war der Sensor der Forerunner noch viel besser. Soweit ich gelesen habe, wurde in der Forerunner ein (von Mio?) zugekaufter Sensor verwendet, in der Vivosmart HR wurde dann angeblich der erste selbst entwickelte Sensor verbaut. Offensichtlich ist der aber noch nicht ausgereift.

Nachdem ich in den letzten Tagen immer wieder Synchronisationsprobleme mit der Vivosmart HR hatte, dachte ich mir, ich schau mir einmal einen anderen Hersteller an. So bin ich bei Fitbit gelandet. Zuerst habe ich die Fitbit Surge ins Auge gefasst. Die Surge wird als Superwatch beworben und hat sowohl einen Pulssensor als auch GPS integriert. Nur wirklich schön ist sie meiner Meinung nach leider nicht. Bestellt habe ich sie aber trotzdem. Mal testen, dachte ich.

Während die Bestellung im Amazon-Logistikzentrum für den Versand vorbereitet wurde habe ich dann aber beim Durchstöbern von Reviews auf YouTube die nagelneue Fitbit Blaze entdeckt. Schaut echt stylisch aus, hat ein Farbdisplay und auch sonst alles was man sich wünscht – inklusive Pulssensor (neuere Generation als die 2014 erschienene Surge). GPS ist zwar nicht on-board, aber durch Connected-GPS kann man trotzdem Strecken aufzeichnen. Mann muss lediglich das Smartphone dabei haben, was man normalerweise aber sowieso immer dabei hat. Also Amazon-Bestellung der Surge noch rechtzeitig storniert und stattdessen die Blaze bestellt. Dank Prime kam sie dann auch schon am nächsten Tag bei mir an.

fitbit-blaze

Bei der Blaze handelt es sich um ein Tracker-Modul, das in den Rahmen des Armbands gesteckt wird. Das hat den Vorteil, dass man die Bänder beliebig wechseln kann. Fitbit bietet neben dem Standard-Armband auch noch Bänder aus Leder und Metall an, die aber mit ca. 100,- bis 130,- Euro unverschämt teuer sind. Im Vergleich zur Vivosmart HR ist die Blaze extrem dünn und angenehm zu tragen. (Erinnert mich von der Größe her etwas an die einfachen Meister-Anker Digitaluhren die vor 25 Jahren im Quelle-Katalog angeboten wurden.) Das Tragegefühl ist jedenfalls 1A.

Natürlich wollte ich auch den Pulsmesser gleich testen. Ist Fitbit da mit der Technologie weiter als Garmin? Laut den Amazon-Kundenrezensionen: Ja. Aber besser selbst testen. Also habe ich Blaze und Vivosmart HR zu einer Gassi-Runde angezogen. Ich gehe mit dem Hund immer recht schnell, demnach sollte der Puls schon erkennbar über dem Ruhepuls liegen. So um die 100 bpm fände ich logisch. Und siehe da:

pulsvergleich

Die Anzeige der Blaze passte zu dem, was ich auch erwartet habe. Die Vivosmart pendelte sich jedoch, wie vermutet, zwischen 50 und 60 Schlägen pro Minute ein. (Teilweise zeigte die Vivosmart HR gar nur halb so viele Schläge an, als die Blaze.) Ein klarer Punkt also für die Fitbit Blaze. Die Distanzmessung ergab nur geringfügige Unterschiede. Fitbit hat die Connected-GPS-Funktion genutzt, Garmin nur die Schrittlänge mit der Schrittanzahl multipliziert.Eine Differenz von 100 Metern bei einer 3 km langen Runde ist da aber durchaus vertretbar.

Kommen wir anschließend zur App, die ebenso wichtig ist, wie der Tracker selbst. Bisher hatte ich ja nur Erfahrung mit Garmin Connect. Auch hier hat mich Fitbit voll überzeugt. Die App ist schön aufgeräumt.

fitbit-app

Neben dem Tracken von Aktivitäten bietet Fitbit auch noch ein integriertes Ernährungstracking an, in dem man hinterlegen kann was man wann gegessen und getrunken hat. Die aufgenommenen Kalorien werden dann automatisch mit den verbrauchten Kalorien gegengerechnet. Ein wirklich tolles Feature, das die Garmin nicht bieten kann. Garmin Connect bietet lediglich eine Schnittstelle zu myFitnessPal. Dann braucht man aber erstens wieder zwei unterschiedliche Apps für’s Tracking und außerdem klappt der Datenabgleich zwischen Garmin Connect und myFitnessPal auch nicht immer. Auch die Flüssigkeitsaufnahme kann Fitbit loggen und zeigt an, wenn man noch was trinken sollte.

Ebenfalls genial ist die Echtzeit-Anzeige der App. Anstatt wie bei anderen Apps, die nur sporadisch Daten mit dem Tracker abgleichen, erfolgt bei Fitbit ein permanenter Datenabgleich, wenn die App geöffnet ist. Man sieht also sofort, wenn man 2 Schritte gegangen ist und auch der Puls wird in der App aktuell angezeigt. Rückblickend kann man in der App auch zu jedem Punkt Diagramme mit dem Tagesverlauf (für über 2 Monate) ansehen.

Ach ja, eine Sache habe ich noch vergessen. Aktivitäten versucht Fitbit automatisch zu erkennen. Beginnt man also beispielsweise zu laufen, dann zeigt die App nach dem Lauf automatisch an, dass die Blaze einen Lauf erkannt hat und diesen automatisch als Activity gespeichert hat. Man muss also nicht einmal eine Aktivität starten. Es sei denn, man möchte GPS-Tracking. Das ist bei „SmartTrack“ nicht aktiv, da die Aktivität erst nach 15 Minuten als solche erkannt wird. (Den Zeitraum kann man aber einstellen.)

Weitere Features der Blaze sind PurePuls (kontinuierliche Messung der Herzfrequenz), Musiksteuerung (ist mittlerweile eigentlich eh schon Standard), Anzeige von Mitteilungen auf der Uhr (eingehende SMS, Anrufe,.. leider unter iOS noch kein Whatsapp.) und FitStar-Workouts, die direkt auf der Uhr gespeichert sind (7-minütig und 10-minütig).

Alles in allem bin ich mit der Fitbit Blaze bisher einwandfrei zufrieden. Lediglich die Smart Notifications von Drittanwendungen (WhatsApp, Outlook, Facebook,…) fehlen für iOS noch. Für Android gibt es schon eine Lösung. Nachdem es aber auf der Fitbit-Webseite schon ein paar entsprechende Feature-Requests gibt, hoffe ich, dass diese Funktion mit einem der nächsten App-Updates nach geliefert wird.

 

Serverless Website #2: Dynamischen Inhalt in statische Seite nachladen

by Armin 1 Comment

Im ersten Artikel zum Thema Serverless Website habe ich bereits darüber geschrieben, wie man eine Webseite ohne eigenen Webserver (dafür aber mit einem hoch-skalierbaren Content Delivery Network) realisieren kann. Das ist eine tolle Sache, weil es eben eine skalierbare und kostengünstige Lösung ist. Aber natürlich möchte man nicht für jede neue Zeile auf der Webseite lokal eine statische HTML-Datei bearbeiten und diese anschließend auf S3 hoch laden. Ganz zu schweigen von der Wartedauer, bis die Datenn dann in der CF-Distribution global auf alle Edge-Locations ausgerollt ist, denn das ist leider keine Sache die in 1-2 Minuten vorbei ist.

Die Lösung lautet also: Serverlos ja, aber ohne Einbußen wegen fehlender Dynamik. Zum Glück gibt es auch dafür diverse Lösungsansätze. Auf einen davon möchte ich heute etwas eingehen. Die folgende Grafik erweitert die bisherige Konstellation aus dem ersten Beitrag.

serverless2

Man sieht hier, dass im unteren Bereich der Grafik ein API-Gateway mit einer Lambda-Funktion und eine Backend-Datenbank in der Cloud dazu gekommen sind. Was passiert nun also beim Aufruf der Seite? Nehmen wir an, ein Besucher surft auf die Webseite. DNS-Auflösung durch R53, Laden der Daten von der besten CF-Edge-Location, welche die Daten von S3 bekommen hat. Eventuell spielt auch noch ACM wegen dem SSL/TLS-Zertifikat mit. Die statische Webseite ist somit also am Client angekommen. Wie bekommt man nun die dynamischen Inhalte zum Browser? Die Lösung dafür kann einfach Javascript heißen. Durch einen AJAX-Request können mit JS (etwa mit jQuery, um es etwas einfacher zu machen) dynamische Inhalte aus der Cloud nachgeladen werden. Der Client hat in dem Fall von CF nur ein leeres Grundgerüst bekommen, das dynamisch mit Inhalten befüllt wird.

Ich habe das gestern einmal ausprobiert. Der Aufwand hält sich sehr in Grenzen. In meinem Fall ist der am Client notwendige Code auf folgende paar Zeilen reduziert:

$(document).ready(function(){
 var site = 'node.one';
 $("p").each(function(index) {
  if($(this).attr("n1cont") != undefined) {
   var e = site+'/'+$(this).attr("n1cont");
   var data = { elem: e }; $.ajax({
    type: 'POST',
    url: 'https://api.n1cloud.net/n1webcontent',
    contentType: 'application/json',
    data: JSON.stringify(data),
    dataType: 'json',
    success: function (data) {
     var de = jQuery.parseJSON(JSON.stringify(data)).Item.elem.S.replace(site+'/','');
     var dc = jQuery.parseJSON(JSON.stringify(data)).Item.cont.S;
     $("p[n1cont='" + de + "']").html(dc);
    },
    error: function (e) { alert("Fehler! " + e); }
   });
  }
 });
});

Was macht dieser Code? Wenn die Seite geladen ist, durchsucht sie der jQuery-Code nach Platzhalter-Absätzen, die das Attribut n1cont aufweisen. Dieses Attribut ist das Kennzeichen, dass an dieser Stelle ein dynamischer Inhalt nachgeladen werden soll. Der Wert dieses Attributs gibt wiederum genau an, welcher Inhalt angezeigt werden soll. Dadurch besteht der HTML-seitige Code beispielsweise einfach aus folgender Zeile:

<p n1cont="news/latest"></p>

Natürlich ist dieses Vorgehen nicht auf Absätze beschränkt, sondern kann auf beliebige HTML-Tags angwendet werden. Für jeden gefundenen Platzhalter wird in weiterer Folge ein Request auf die N1WebContent-API ausgeführt, die dann die entsprechenden Daten liefert. Die Inhalte werden dann einfach mit .html() an die entsprechende Stelle eingefügt.

Dabei muss man aber auf folgendes aufpassen: Zum Ersten erwartet die API die übergebenen Parameter im JSON-Format. Hier hilft ebenfalls JavaScript mit JSON.stringify(). Zum Anderen – und da bin ich auch erst beim Testen drüber gestolpert, ist aber eigentlich klar – werden alle AJAX-Requests nacheinandere abgefeuert. jQuery wartet nicht auf die Antwort des ersten Requests bevor der zweite gesendet wird. Das ist gut für die Performance, bringt aber Probleme mit sich, wenn man sich auf ein Element im HTML-Code beziehen möchte ein $(this) kann somit leider nicht mehr verwendet werden, weil eventuell bereits Request #1, #2, #3 und #4 gesendet wurden und während der Bearbeitung von Element #5 als erste Antwort die Response #2 eintrifft. Anstatt mit $(this) zu arbeiten gibt in meinem Fall also die API wieder den Key mit retour, der definiert an welcher Stelle (n1cont-Attribut) der neue, dynamische Inhalt eingebaut werden soll. So ist sichergestellt, dass der Inhalt immer an der korrekten Position eingefügt wird, unabhängig von der Reihenfolge der eintreffenden Antworten.

Für einen praktischen Test habe ich einen Teil meiner node.one-Webseite mit minimalistischem Layout nachgebaut:

aws-lambda-webcontent

Im unteren Bereich von Edge sieht man den entsprechenden Quellcode, der in diesem Beispiel sechs Platzhalter befüllt.

Sicher kann man das Ganze noch schöner realisieren, etwa mehrere AJAX-Requests zu einem zusammen fassen und größere Blöcke nachladen, anstatt einzelner Absätze. Aber ich denke für ein Proof-of-Concept reicht dieses Beispiel so aus. Das soll nur ein Denkanstoß sein, und jede(r) Interessierte kann sich selbst etwas dazu überlegen. 🙂

Um noch kurz auf der Cloud-Komponenten einzugehen: Die verwendete N1WebContent-API habe ich mit Lambda realisiert. Sie wird über ein API-Gateway aufgerufen und greift im Backend auf eine DynamoDB NoSQL-Datenbank zu. Letztere verwendet im einfachsten Fall nur 2-Key-Value-Paare für Identifier und Content. Kostengünstiger kann man das eigentlich gar nicht realisieren – vor allem weil AWS zeitlich unbeschränkte Free Tiers für Lambda und DynamoDB bietet, womit die Requests für eine kleine Webseite (bis auf das API-Gateway) komplett kostenlos sind.

Am längstrn habe ich übrigens für die Lambda-Funktion benötigt. Die wollte einfach nicht funktionieren … bis ich im Endeffekt darauf gekommen bin, dass der Fehler eigentlich an der DynamoDB gelegen ist: Ich hatte in meiner DynamoDB einen Key mit dem Namen „element“. Das hat Lambda/Node.js offenbar nicht gefallen und deshalb den Funktionsaufruf mit einem (nicht aussagekräftigen) Fehler beendet. Irgendwann bin ich auf die Idee gekommen, die Datenbank mit anderen Key-Namen anzulegen. Das hat das Problem dann zum Glück gelöst.

CNAMEs: Probleme und Alternativen

DNS Resource Records sind so eine Sache. Man braucht sie fast für alles im Internet, aber viele können sich damit nicht wirklich anfreunden. Mir geht das anders – ich mag DNS. 🙂 Aus diesem Grund will ich heute einmal auf einen speziellen RR-Typ eingehen, der immer wieder zu Problemen führen kann: Den Canonical Name Record, kurz CNAME (Typ 5 laut RFC 1035).

Ein CNAME ist sozusagen ein Alias für einen anderen (Sub-)Domainnamen. Dieser kann entweder innerhalb der eigenen Domain liegen, oder der CNAME kann alternativ auch auf einen komplett anderen Domainnamen verweisen. Ist also etwa test.example.com ein CNAME, dann könnte dieser etwa auf abc.example.com verweisen oder aber auch auf xyz.otherdomain.org. Eine praktische Sache, die vor allem dann hilfreich ist, wenn es mehrere Namen gibt, die auf den gleichen Host verweisen sollen.

Ein Beispiel: Der Webhoster examplehost.com bietet seinen Kunden Webspace an. Auf dem Server  webserver0815.examplehost.com liegen die Domains von 100 Kunden. In dem Fall ist es schlau, wenn jeder Kunde für www.kundendomain.com einen CNAME auf webserver0815.examplehost.com setzt. So kann sich die IP-Adresse des Webservers 0815 ändern, ohne dass die Kunden ihre DNS-Einstellungen anpassen müssen. Würden die Kunden hingegen direkt einen A-Record für www.kundendomain.com verwenden und die IP-Adresse des Webservers 0815 hinterlegen, dann könnte der Webhoster die IP-Adresse des Webservers nicht ändern, ohne, dass alle Kunden ihre DNS-Konfiguration aktualisieren. Ansonsten wäre ihre Webseite nicht mehr erreichbar.

Das sind also die praktischen Vorteile eines CNAME. Es gibt aber auch einige Probleme, die sich schon am Text von RFC 1912 erkennen lassen:

A CNAME record is not allowed to coexist with any other data. In other words, if suzy.podunk.xx is an alias for sue.podunk.xx, you can’t also have an MX record for suzy.podunk.edu, or an A record, or even a TXT record. […] Don’t use CNAMEs in combination with RRs which point to other names like MX, CNAME, PTR and NS.

Ein CNAME darf also nicht mit einem anderen Resource Record kombiniert werden. Problematisch ist das also etwa bei MX-Einträgen. Und generell darf der Zone Apex (also der „nackte Domanname“, etwa example.com) keinen CNAME verwenden. Eigentlich klar, weil es im Apex immer andere Record-Typen gibt. Wenn schon keinen MX-Record, dann zumindest einen SOA- und NS-Record.

Je nach DNS-Anbieter gibt es dafür mittlerweile unterschiedliche Lösungen. Manchmal heißen sie ANAME, manchmal ALIAS oder CNAME Flattening. ALIAS-Einträge bietet etwa AWS mit Route53 an. So kann man etwa den Zone-Apex einer DNS-Zone auf eine AWS-Ressource verweisen lassen – beispielsweise eine CloudFront-Distribution oder einen Elastic LoadBalancer. Anstatt bei einem DNS-Request dann einen CNAME zurück zu geben, löst Route53 den dahinter liegenden Hostnamen der CF-Distribution oder des ELB auf und gibt direkt die IP-Adressen an den anfragenden Client weiter. Für diesen schaut es dann so aus, als wären es A-Records. CloudFlare’s RFC-konforme Lösung für das Problem nennt sich CNAME Flattening. Auch hier wird gleich von Seiten des CloudFlare-DNS-Servers eine CNAME-Abfrage an den dahinter liegenden Host durchgeführt und es werden A-Records weiter gegeben. Beim Zone-Apex stellt CloudFlare einen CNAME automatisch auf Flattening um. Für Subdomains ist das nur bei den kostenpflichten Produkten (nicht aber beim Free Plan) möglich.

Man sieht also: CNAMEs sind eine feine Sache, können aber auch so ihre Probleme verursachen. Deshalb sollte man wissen, was man tut und eine der alternativen Lösungen verwenden, wenn es erforderlich ist.

Wenn der Webserver dem Kundenansturm nicht gewachsen ist

by Armin 0 Comments

Neben der Höhle der Löwen (VOX) bin ich auch ein Fan der österreichischen Variante 2 Minuten 2 Millionen (Puls 4). Wenn sich dann eine Firma vorstellt, die ein interessantes Produkt anbietet, dann besuche ich manchmal noch während der Sendung die Webseite dieser Firma. Speziell bei Firmen die ihre Produkte an Endkunden verkaufen wollen, sollte die Webseite deshalb  zum Zeitpunkt der Ausstrahlung auf einen möglichen Kundenansturm vorbereitet sein. Schade ist es dann, wenn dann aber so etwas passiert:

kinderkistl

Im konkreten Fall ging es im das Kinderkistl, das in der heutigen Folge von 2Min2Mio vorgestellt wurde. Eine tolle Idee. Möchte man sich aber zu Ausstrahlungszeitpunkt über die Firma bzw. das Produkt informieren, dann erhält man unter Umständen leider nur die oben abgebildete Meldung. (Das ist mir in den letzten Folgen der beiden Sendungen schon mehrfach passiert, Kinderkistl ist da kein Einzelfall.)

Das sollte eigentlich nicht passieren. Warum ist das so? Denken die Firmen einfach nicht daran? Rechnen sie nicht mit einer höheren Serverlast? Oder sind sie sich vielleicht einfach nicht bewusst, dass ein Webserver auch einmal überlastet sein kann? Die Lösung wäre hierfür ganz klar eine gut skalierbare Cloud-Lösung, die sich kosteneffizient dynamisch an die Last anpassen kann.

a0.io wird zum Kurz-URL-Dienst

Nachdem dieser Blog hier nun doch schon seit ein paar Monaten primär unter der Adresse armix.one (und nicht mehr a0.io) erreichbar ist, habe ich mich entschlossen der Domain a0.io eine neue Bedeutung zu geben: a0.io (die kürzeste, von den über 30 Domains, die ich momentan besitze) wird ab sofort als Kurz-URL-Dienst genutzt.

Die Programmierung eines Kurz-URL-Dienstes ist in ein paar Minuten vorbei. Prinzipiell reicht eine Datenbanktabelle mit 2-3 Spalten um die Verknüpfung zwischen Kurz-URL und eigentlicher URL abzubilden. Dazu braucht es dann nur ein kleines Script, das auf besagter Kurz-URL-Domain läuft und mit dem aufgerufenen URI einen entsprechenden Datensatz in der Tabelle sucht. Über einen Location-Redirect leitet man dann einfach weiter. Bereits vor einigen Jahren habe ich damals den Dienst ARMIXCDN.id in Betrieb genommen, diesen aber nur für eigene Zwecke genutzt. Der Code im Hintergrund ist sehr einfach gestrickt:

<?
// database connection
$AWE_DBCONN = @mysql_connect($AWE_DBSERVER, $AWE_DBUSR, $AWE_DBPWD);
@mysql_select_db($AWE_DBNAME, $AWE_DBCONN);
// caching verhindern
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
// id lookup
$acdnid = substr(strip_tags($_REQUEST["acdnid"]), 0, 31);
$success = false;
// direct content
if($acdnid == "favicon.ico") {
 header("Location: http://www.armix.net/favicon.ico");
 $success = true;
}
elseif($acdnid == "crossdomain.xml") {
 header("content-type: text/xml");
 echo "<?xml version=\"1.0\"?>\n";
 echo "<!DOCTYPE cross-domain-policy SYSTEM\n\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n";
 echo "<cross-domain-policy>\n<allow-access-from domain=\"*\" />\n</cross-domain-policy>\n";
 $success = true;
}
// request routing
if(!$success) {
 $query = "SELECT armixcdn_uri FROM " . $AWE_DBTAB_ACDN . " WHERE armixcdn_id = '" . $acdnid . "' LIMIT 1";
 $result = mysql_query($query);
 while($queryresult = mysql_fetch_array($result)) {
 $success = true;
 $armixcdn_uri = $queryresult["armixcdn_uri"];
 @mysql_query("UPDATE " . $AWE_DBTAB_ACDN . " SET armixcdn_count = armixcdn_count+1, armixcdn_ts = NOW() WHERE armixcdn_id = '" . $acdnid . "'");
 header("Location: " . $armixcdn_uri);
 }
}
// redirect to homepage
if(!$success) { header("Location: http://www.armix.net"); }
?>

Die Besucher-Statistiken pro Link beschränken sich im obigen Beispielcode auf einen Counter und den Zeitpunkt des letzten Aufrufs. Das kann man natürlich noch viel weiter ausbauen, wenn einem genauer interessiert wer wann wo auf welchen Link geklickt hat.

Berücksichtigen muss man sonst lediglich einige Besonderheiten: Etwa, dass Browser unter Umständen ein Favicon suchen. Auch beim Darstellen von (mittlerweile immer weniger verbreiteten) Flash-Videos muss man darauf achten, dass die Cross-Domain-Policy angeboten wird.

…fehlt nur noch die entsprechende Rewrite-Rule am Webserver; die könnte dann etwa so aussehen:

RewriteRule ^([^/]*)$ /index.php?acdnid=$1 [L]

…und schon hat man einen eigenen, minimalistischen Kurz-URL-Dienst. 🙂

Ein Beispiel für den neuen Dienst liefert gleich der folgende Link, der erklärt was Chaos Monkeys sind und warum ein Videoportal via Netflix so etwas im eigenen Netzwerk braucht: http://a0.io/1S6MjtX