Microservices – ein Wort, viele Deutungen

Microservices, der große Hype! Mit dem Einzug von Docker als sehr leichte Virtualisierung wurde es nochmal ein Stück leichter Projekte als derartige (Software-)Strukturen zu realisieren. Mittlerweile ist der Hype vorüber und Microservices sind eine von mehreren etablierten Architekturen. Wichtig: eine von vielen, ob sie auf das „Problem“ bzw. den Bedarf des „Stakeholders“ passt, steht auf einem anderen Blatt.

Wie ich lernen durfte, verwenden viele Menschen den Begriff des Microservice sehr unterschiedlich. Das sorgt immer wieder für Schwierigkeiten in der Kommunikation, denn wenn der Gesprächspartner ein anderes Bild im Kopf hat als man selbst, dann redet man sehr schnell aneinander vorbei und keiner ist glücklich bzw. fühlt sich missverstanden. Im Folgenden will ich ein wenig Licht ins Dunkel bringen bzw. eine aus meiner Warte wichtige Unterscheidung und Bezeichnungen die ich gerne verwende um Klarheit zu haben.

Aus meiner Erfahrung heraus wird der Begriff „Microservice“ in folgenden „Geschmacksrichtungen“ benutzt:

  • technischer Mikroservice
  • fachlicher Mikroservice

Bevor wir zu den Unterschieden kommen, es gibt selbstverständlich auch Gemeinsamkeiten.

Was Mikroservices eint

Mikro kommt von klein und im besten Falle meint kleiner auch übersichtlicher. Dies ist eine wichtige Gemeinsamkeit – egal ob fachlich oder technisch man beschreibt oder möchte eine Struktur haben die man noch gut überblicken kann. Gerade in der Software heißt das: Wenn man etwas ändert dann muss man nicht gleich Angst haben, dass einem alles auf die Füße fällt, weil die Abhängigkeiten und Querverbindungen so umfangreich sind dass man sich gar nicht erst ausmalen kann was alles den Bach runter geht wenn man eine Änderung durchführt.

Ganz häufig ebenfalls genannt werden hinsichtlich der Gemeinsamkeiten natürlich auch Technologien wie Docker, Podman, Kubernetes um einmal nur die aktuell wichtigsten zu nennen. Wichtig ist hierbei: Das sind typische Hilfsmittel um Microservices zu gestalten, einen absoluten kausalen Zusammenhang gibt es aber nicht zwingend. Man kann auch Mikroservices auf virtuellen Maschinen ausrollen und wenn man die Prozesstrennung auf einem Server genauer anschaut, dann ist das auch schon eine Art Mikroservice, auch wenn man es in der Regel nicht so nennt: Der Webserver hat im Speicherbereich des Datenbankservers nichts verloren, diese Form der Trennung gibt es aber schon sehr lange und sie ist aus gutem Grund sehr erfolgreich.

Wichtig und ebenfalls häufig genannt: Skalierbarkeit. Mikroservices baut man geschickter Weise so auf, dass diese ggf. mehrfach (auf unterschiedlichen Systemen) laufen können. Das Stichwort hier heißt horizontale Skalierung. Wenn der Ansturm ist, verteile ich die Last auf mehrere Schultern. Das wohl bekannteste Beispiel ist die Supermarkt-Kasse: Wenn die Schlange (Last) zu groß wird dann wird eine weitere Kasse aufgemacht, ist wieder weniger los, reduziere ich die Anzahl der offenen Kassen. Das ermöglicht es die Ressourcen effizient einzusetzen – im Supermarkt kann der Mitarbeiter die Zeit die er an der Kasse nicht gebraucht wird z.B. zum Auffüllen von Regalen nutzen.

Der technische Mikroservice

Spricht man unter Entwicklern oder auch DevOps, so ist man sehr nahe an der Technik. Dementsprechend wird der Mikroservice dort sehr häufig (aber eben nicht immer) als technischer Mikroservice betrachtet. Ich habe eine klare Aufgabenteilung: Der Datenbank-Prozess kümmert sich um die Datenhaltung, der Webserver um die Anfragen per HTTP(S) und dazwischen gibt es wahrscheinlich noch ein wenig Applikations-Code (wahlweise in PHP, Java, NodeJS oder was auch immer gerade passt).

Setzt man nun Docker ein, so sollte man pro Prozess einen Container bekommen, die Kommunikation erfolgt über Netzwerk-Sockets. Dabei ist noch nicht einmal gesagt, dass beide Prozesse auf der gleichen Maschine laufen, im Zweifel steht die Datenbank am anderen Ende der Welt (ob das dann sinnvoll ist, ist eine andere Sache). Kommt nun mehr Last dann kann ich in der Regel einfach mehr Container starten (auch wenn es da bei Datenbank natürlich noch das Thema ACID zu beachten gilt, häufig ist aber nicht die Datenbank der Flaschenhals sondern schon der Webserver kommt nicht hinterher). Brauche ich mehr Rechenleistung und die Aufgabe lässt sich parallelisieren kann ich auch hier einfach weitere Container hochfahren und jeder schnappt sich einen Teil der Arbeit (siehe Supermarktkasse). Sinnvoller Weise sollten die Aufgaben dann nicht auf der gleichen Hardware laufen, wenn die schon am Limit ist, dann macht ein zusätzlicher Container die Sache an der Stelle sogar eher schlimmer denn besser.

Merke „technischer Mikroservice“: Wir reden tatsächlich über einzelne Container-Instanzen.

Der fachliche Mikroservice

Meist eine Stufe höher in der Abstraktion findet sich der fachliche Mikroservice. Wie üblich wenn man die Abstraktionspyramide nach oben geht, werden die Element mit denen man es zu tun hat etwas gröber.

Das ist genau der Punkt an dem viele Product-Owner, Abteilungsleiter oder Manager vom Mikro-Service reden. Gemeint ist dabei aber nicht zwingend die Verteilung auf einzelne Prozesse (das wäre zu fein granular), stattdessen geht es um einzelne „Funktionen“ in einem Unternehme. Im E-Commerce hat sich bei entsprechend großen Unternehmen eine Aufteilung in verschiedene Fachgebiete durchgesetzt, z.B. Suche, Warenkorb, Checkout, Payment, Logistics. Ganz wichtig dabei ist: die einzelnen Aufgabenbereiche agieren unabhängig voneinander über definierte Schnittstellen (das können Rest-APIs sein, aber jeder andere Form der Schnittstelle geht fast genauso gut). Ob innerhalb eines Aufgabenbereichs dann noch eine weitere Unterteilung stattfindet und ob diese dann ggf. technische Mikroservices oder doch eher einen monolithischen Ansatz verfolgen ist für den fachlichen Mikroservice unerheblich. Wichtig ist: Die Aufgaben sind für ein Team überschaubar, es geht also nicht darum von der Beschaffung bis zur Auslieferung von Ware oder Leistungen an den Kunden alles zu beherrschen sondern nur einen (An)-Teil. Den sollte man dann aber eben richtig gut machen.

Fazit

Die Welt ist voller Homonyme und der Terminus „Mikroservice“ macht da keine Ausnahme. Es lohnt sich daher immer, einmal genau nachzufragen was denn nun der Gesprächspartner meint. Dabei schließen sich die beiden Konzepte nicht einmal gegenseitig aus – ganz im Gegenteil: technische Mikroservices sind ganz häufig die Grundlage für eine Mikroservice-Architektur auf der organisatorischen Ebene.

Docker healthchecks – things to consider

While working on a recent docker project I encountered an issue when it comes to health checks. You may define a health check for a container from within your Dockerfile, such as

HEALTHCHECK --interval=5s --timeout=5s --start-period=20s
         --retries=5 CMD wget --output-document=- 
         --quiet --tries=1 http://127.0.0.1

The syntax is quite simple to understand, you basically define how and when the health check should be executed and which command(s) to use. Breaking things down from the example

  • –interval=5s – run the check every 5 seconds
  • –timeout=5s – maximum time to wait for the health check to complete
  • –start-period=20s – allow some time for the process to be monitored to come to a functioning state, avoids false alarms during startup, in this case we allow 20 seconds
  • –retries=5 – only trigger an alarm after 5 unsuccessful tries (non zero exit code) – this helps avoiding false alarms in case the process is under heavy load
  • After the CMD follows the command to execute, this is done from inside the container, in the given example we check for the webserver to deliver something indicating the server is working properly

However every one should consider on how flexible the health check should be to match as many use cases as possible. This is especially true if you are dealing with web-based endpoints as pointed out in the example.

Continue reading

Why IPv4 is not better compared to IPv6 in terms of security of your home/office network

If you look at the internet at the moment, from a more technical point of view, you will often find users complaining about the „new“ Internet-protocol IPv6. Most of the time the complaints are about issues with the Internet-Service-Provider ISP used.

I will focus on the issue based on my experience in Germany (things might be different in your location, feel free to leave a note in the comments). In fact the technical introduction of IPv6 went unnoticed for most of the average users. This is partly due to the fact, that in the beginning there were not so much services that were accessible via IPv6 (a typical chicken-egg-problem) and most operating systems seamlessly degrade to IPv4 if a service is not available in IPv6.

Continue reading

PowerDNS mit Pi-Hole auf RasPi

Eines der etwas länger schon mal angedachten Projekte, welches ich dann aufgrund Zeitmangels und auch etwas Frustration in die Ecke gelegt hatte ist ein eigener, lokaler DNS-Server den man auch schnell aktualisieren kann – wer häufiger in verschiedenen Projekten arbeitet weiß es zu schätzen wenn man den Stall der Entwicklungs-Container nicht per IP-Adresse auswendig lernen muss, sondern ihn per sprechenden Namen ansprechen kann. In diesem Post geht es erst einmal darum die Grundlagen zu schaffen, auch das ist bereits etwas mehr Arbeit als ich gedacht hätte.Wichtige Eckpunkte / Material zum Nachbauen:

  • Raspberry Pi (inklusive Netzteil)
  • als DNS-Server kommt PowerDNS zum Einsatz
  • MySQL/MariaDB als Datenbank für die DNS-Einträge
  • DNS-Dist als Loadbalancer für DNS-Queries
  • PiHole als Resolver mit Blacklist
  • Docker als Virtualisierung für alle Services
  • IPv6 als primäres Netzwerkprotokoll, IPv4 nur als Fallback

Continue reading

Datenbankversionierung – Vor- und Nachteile bestimmter Praktiken

Gerade hatte ich mal wieder ein Schlüsselerlebnis in meiner Programmierung. In diesem Fall gab es ein Kollision mit YAML (YAML Ain’t Markup Language) – ich spreche explizit von Kollision, denn meine Erfahrung ist für den verwendeten Anwendungsfall einfach nur schlecht bzw. ich sehe leider aktuell einige Nachteile.

Datenbank-Schemata versionieren

Zur Versionierung von Datenbank-Änderungen bzw. um den Weg von einer „leeren“ Datenbank bis hin zum aktuellen Stand der Entwicklung zu beschreiben verwendet man in der Regel entsprechende Tools wie Liquibase oder Flyway. Das Prinzip ist im Prinzip immer das Gleiche – mit ein wenig „Rahmenwerk“ drum herum steuert man die Ausführung der Datenbank-Statements. Dabei kann man auf verschiedene Szenarien eingehen, einer der häufigst genannten ist, dass man ein Produkt mit verschiedenen Datenbank-Servern laufen lassen kann. Das ist beispielsweise wichtig wenn man Software an Firmen (seltener private Anwender) ausliefert, sich aber darauf einstellen muss, dass dort nicht unbedingt die aktuelle Version von MySQL läuft sondern eben im Zweifel auch ein PostgreSQL oder eine andere (kommerzielle) Datenbank wie Oracle. Continue reading

Frameworks in der Programmierung – wirklich so essentiell wie immer behauptet?

Wenn immer man sich aktuell umschaut auf dem Jobmarkt, dann sind im Softwarebereich immer Erfahrungen mit Frameworks gefordert oder zumindest gern gesehen. Nun habe ich ja auch einige Erfahrung und ich sehe das immer wieder etwas zwiegespalten.

Machen wir uns erst einmal ein Bild mit welchem Ziel Frameworks entstanden sind. Mehrheitlich ist ihr Ziel die Entwicklung von Software zu vereinfachen und zu beschleunigen. Der Entwickler soll sich weniger Gedanken machen müssen über einige technische Details und soll sich ganz und gar auf seine Applikation konzentrieren können. Das klingt ja erst einmal nicht schlecht. Wer möchte sich schon gerne mit den Details einer TCP/IP-Verbindung womöglich sogar noch Verschlüsselung beschäftigen müssen wenn er nur Daten von einem Server irgendwo im Netz abholen möchte. Das klingt doch schon insgesamt sehr verlockend, aber jede Medaille hat bekanntlich zwei Seiten. Jede Technologie bringt ihre Tücken und ggf. auch Einschränkungen mit. Eine dieser Einschränkungen ist es, dass ein Framework gewisse Regeln vorgibt an die man sich halten muss, wenn man es verwendet. Das muss noch nicht mal negativ sein, vermeidet es doch, dass man sich unfreiwillig irgendwo eine Bremse einbaut, die man ggf. später wieder ausbauen muss.

Da ich relativ viel im Bereich Webentwicklung mache, beschränke ich mich im Folgenden bei den Beispielen auf dort häufig anzutreffende Frameworks und meine Erfahrungen mit Ihnen.

Eines der für mich wichtigsten Frameworks ist und bleibt JQuery und es ist eines der wenigen Frameworks, das ich schätzen gelernt habe. Warum das so ist? JQuery schreibt mir als Entwickler nicht irgendein Gerüst vor, vielmehr gibt es eine Reihe von best-practices und jede Menge Beispiele. Brauche ich aber nur eine simples Ein- und Ausblenden eines Formularelements dann muss ich mich nicht erst mit dem Bauen und Administrieren von Formularen im Sinne des Frameworks beschäftigen. Stattdessen kann ich es einfach aus und einblenden wie es gerade nötig ist. Minimaler, schlanker Code mit dem ich das Element finden und damit etwas machen kann. Derartige Abstraktion (noch dazu über Browser-Grenzen hinweg) finde ich sehr hilfreich. Auch wenn sich JQuery selbst als Framework bezeichnet – für mich hat es eher den Charakter einer umfangreichen Library (aber Library klingt natürlich so altbacken, das kannten ja schon die Entwickler aus C … daher kann man das natürlich in einem modernen Umfeld nicht offiziell so nennen).

Das nächste Framwork, mit dem ich auch immer noch arbeiten darf, ist ZendFramework. Mittlerweile ist davon die Version 3 auf dem Markt, vor allem nachdem die Version 2 reichlich wenig Akzeptanz gefunden hat. Im Arbeitsumfeld sind wir noch größtenteils mit Zend1 unterwegs. Das wird mittlerweile definitiv nicht mehr weiter entwickelt, aber wenn es läuft und es keine sicherheitskritischen Probleme gibt gilt die alte Weisheit: „never touch a running system“. Leider muss ich sagen, dass mir das Framework häufig mehr Arbeit verursacht als es je einsparen könnte. Vieles ist einfach nur sehr umständlich, trotz oder gerade wegen der vorgegeben Struktur. Auf der einen Seite ist sie recht starr – es gibt nur eine Möglichkeit bestimmte Ergebnisse zu erreichen. Auf der anderen Seite sind die Funktionen dann doch recht häufig wachsweich – nahezu an jeder Stelle kann (oder muss) man Parameter als indiziertes Array übergeben.

Richtig enttäuscht hat mich das Framework dann bei der Umsetzung von Commandozeilen-Parametern. Im Quellcode des Framworks stehen noch jede Menge offene Todo-Punkte. Die Funktion an und für sich kann man „out of the box“ fast nicht gebrauchen, denn unbekannte Parametern führen zwangsweise zu einem Abbruch der Verarbeitung. Man kann natürlich dann kurzerhand die Framework-Klasse als Basis hernehmen und die notwendigen Routinen in einer eigenen Klasse überschreiben. Aber so wirklich prickelnd ist das nicht, noch dazu bindet man sich damit sehr stark an das Framework – will man die Funktionalität in einem anderen Projekt wieder verwenden, so muss man die dort mit hoher Wahrscheinlichkeit neu implementieren. Ich habe mich in diesem Falle dazu entschieden, es dann gleich selbst zu machen, PHP bietet von Haus aus bereits recht umfangreiche Funktionen, unter anderem sei hier Getopt genannt.

Natürlich wollte ich auch mal schauen was aktuelle Frameworks so können und vielleicht machen die es ja besser. Also habe ich mir Symphony angeschaut. Auf den ersten Blick ist wieder alles „nice and shiny“. Sobald man aber etwas damit arbeiten möchte, musste ich feststellen: Die Doku und die Beispiele sind einfach nur sehr akademisch gehalten. Ich habe das Framework nach einigen Versuchen ad acta gelegt, weil es ein verdammt hoher Aufwand ist, einen recht simplen Fall abzubilden: Man nehme eine einfache 1:n-Relation wie sie jede Datenbank ohne Probleme abbildet: Eine Art News-Artikel wird einer Kategorie zugeordnet. Ein priviligierter Nutzer ist in der Lage die Tabelle der Kategorien bei Bedarf zu erweitern. Ein klassischer Fall, den man im User-Interface gerne und effizient mit Drop-Down-Menu realisiert. In Symfony ist das ein echter Krampf, spätestens bei der Verwendung der Anzeigenamen als Array-Indizes und der eindeutigen Werte als Array-Werte habe ich mir nur noch an den Kopf gelangt. Das funktioniert zwar dank UTF-8-Unterstützung aber es widerspricht sämtlicher Intuition. Die Beispiele zu Formularen sind da auch keine wirkliche Hilfe – da wird einfach darauf gesetzt, dass man es ja doch per Text umsetzen könnte. Das mag für schnelle Projekte sinnvoll sein, aber im Businessumfeld sind die Regeln dann doch etwas strikter. Man kann es natürlich auf der Server-Seite dann wieder prüfen und eine Fehlermeldung ausspucken – aber warum muss der Anwender erst Tippfehler machen und ggf. raten wenn es nur wenige valide Auswahlen gibt?

Das ist jetzt sicherlich keine umfassende Evaluation, aber in vielen Punkten gleichen sich die Frameworks dann doch. Ich werde mir auch noch weitere anschauen. In einem der nächsten Posts werde ich einige generelle Kritikpunkte die mir bisher bei nahezu jedem „Backend-Framework“ aufgefallen sind näher ausführen.

 

Magento 2 – Rest-API oder Reste-API?

Beruflich darf ich mich gerade mit Magento als Shop-System auseinandersetzen. Auf den ersten Blick ein Shopsystem wie es viele auf PHP-Basis gibt. Jedes System hat eine andere Geschichte und damit seine Eigenheiten und besonderen Pluspunkte. Leider finde ich von den Pluspunkten bei Magento für meinen aktuellen Fall etwas zu wenig bis gar keine. Wir haben eine externe Datenquelle, welche verschiedene Verwaltungsabläufe abbildet, an deren Ende eine Reihe von Produkten für den Shop stehen.

Anfänglich war ich vielleicht etwas naiv und dachte: Ein paar Zeilen SQL und dann lässt sich das Datenmodell sicherlich so extrahieren, dass man recht schnell und zuverlässig die Daten vom Quellsystem in den Shop überführen kann. Leider ist das nicht der Fall, denn Magento hat sich als Datenmodellierung für EAV entschieden. Damit ist nicht die erste allgemeine Verunsicherung gemeint (auch wenn die dann nicht mehr weit her ist) sondern eine Modellierungstechnik namens Entity-Attribute-Value. Im ersten Moment klingt das Modell für einen Shop sogar sehr lohnenswert, denn eine Shopsoftware muss ja ggf. mit verschiedensten Waren zurecht kommen. Genau das ist mit EAV möglich: Man bildet die Modellierung von zusätzlichen Eigenschaften über weitere Tabellen ab. So vernünftig das anfänglich klingen mag, um so schwieriger wird die Umsetzung in der Praxis. Da man bestimmte Attribute ja auch in verschiedenen Fällen wieder brauchen kann hat man die noch eine Stufe weiter abstrahiert. Das Ergebnis ist ein sehr umfangreiches Modell, das Anna Völkl schön aufbereitet hat. Übersichtlich ist etwas anderes, auf diesem Datenmodell  manuell direkt auf Tabellenebene zuzugreifen kann man getrost vergessen.
Continue reading

Posted in Web |

Fiese Falle in MySQL bei Verwendung von Views in (Left)-Joins

Da habe ich doch kurz vor Weihnachten noch eine echte Knobelaufgabe erlebt, deren Ergebnis für den ein oder anderen sicherlich interessant sein dürfte. Ausgangspunkt war folgendes eigentlich simple SQL-Statement:

Select * from tableA left join viewC 
     on tableA.id=viewC.lookup

Soweit so unspektakulär, auch wenn das Original noch mit einigen weiteren Filtern gespickt war und die View nicht gerade ein einfaches Query kappselt.

Was allerdings gar nicht lustig war, waren die Ergebnisse dieser Abfrage, denn sie entsprachen nicht den Erwartungen. Aus der View erhielt ich nämlich keinen Join-Partner obwohl ich diesen als Test extra geprüft hatte mit:

 Select * from viewC where lookup='TestValue'

Folgende Punkte habe ich als „übliche Verdächtige“ abgeprüft:

  • Vergleich der Datentypen – auch nicht die Ursache
  • Collations (also Zeichensätze) – auch mit Casting, das Ergebnis bleibt das Gleiche

Spannender Nebeneffekt, der bei der weiteren Untersuchung heraus kam – nutze ich die view nicht sondern packe 1:1 den Code aus der Definition mit in mein Statement

 
Select * from tableA left join 
   (select * from tableB 
     left join tableF 
         on tableB.id=tableF.foo 
      where tableF.bar='baz' and deletedDate is null)
   as testview on testview.id=tableA.id

Dann funktioniert wieder alles wie erwartet. Es staunt der Laie und der Fachmann wundert sich. Höchste Zeit das Problem genauer unter die Lupe zu nehmen und die bekannten Bugs von MySQL bzw. den Deviraten wie MariaDB und Percona zu durchforsten. Ergebnisse sind leider recht dürftig und beschreiben nicht das was ich erlebe. Immerhin stoße ich auf weitere Probleme die erst einmal völlig losgelöst von der Thematik erscheinen, es geht dabei um möglich Einstellungen des Servers und den Standard-Verhalten. Das hat sich in den letzten Jahren immer mal wieder etwas verändert und spiegelt des „Erwachsen werden“ von MySQL wieder. Wir erinnern uns: Es hat eine geraume Zeit gedauert bis MySQL endlich als Standard auf INNODB als Engine gewechselt hat und somit referenzielle Integrität in Form von Transaktionen und Foreign Keys unterstützt wurden. Ebenso aus der grauen Urzeit von MySQL stammen Probleme mit NULL-Werten bei Datumsfeldern (DATE,DATETIME). Und genau da liegt der Hase am Ende auch begraben. Die Server-Konfiguration gibt vor, dass der Server sich strikt verhalten soll, unter anderem bei den Datumsfeldern.
Somit ist es nicht mehr zulässig den „uralten NULL-Ersatz 0000-00-00 00:00:00“ zu verwenden. Die Routinen für den Ersatz kann man aber per Session einschalten, und genau das ist bei der manuellen Abfrage der Werte jedes mal passiert, sei es per manuellem Join oder bei der Abfrage der einzelnen Tabellen. Dabei verhält sich das isnull je nach eingestelltem Modus. Mal liefert es Zeilen mit „0000-00-00 00:00:00“ als Ergebnis, mal nicht, je nachdem ob strict-mode gesetzt ist oder nicht.

Warum läuft es dann beim Verwenden der View aus dem Ruder? Das liegt an der Art und Weise wie MySQL mit Views umgeht: Sind diese übermäßig komplex werden sie als separater Thread gestartet, der eine temporäre Tabelle bereitstellt auf die dann wiederum gejoined werden kann. Dieser Thread wird allerdings vom Serverprozess angestoßen, und dort steht der Modus per default auf strict und dieser wird dann auch angewandt. Somit ist das Ergebnis nicht das was ich bei der singulären Abfrage erhalten habe, sondern leider eben ein leeres da in der Tabelle anstelle NULL eben noch „0000-00-00 00:00:00“ verwendet wird.

Die temporäre Lösung ist, den Join manuell auszuführen, mittelfristig werden wir den Server umstellen. Das sind aber eigentlich nur kosmetische Lösungen. Die eigentlich korrekte Maßnahme für dieses Problem ist die Verwendung von sauberen NULL-Werten anstelle obskurer Workarounds. Leider verlassen sich sehr viele Applikationen bei uns noch auf die Tabelle und diese kruden Werte, einfach Umstellen ist also erstmal leider nicht drin. Ich kann jedem Entwickler nur wärmstens empfehlen, sich auf derartige Altlasten nicht zu verlassen und schnellstmöglich dafür zu sorgen diese abzubauen.

Routing mit HTTP – Query-String oder Verzeichnis-Notation?

In loser Folge werde ich in den nächsten Monaten einige Vorgehensweisen im Netz technisch etwas näher beleuchten und hinterfragen.

Jedes aktuelle Framework, das etwas auf sich hält im Bereich Webentwicklung, bringt einen Routing-Mechanismus mit. Was macht das Ding? Es kümmert sich darum, dass aus einer URL heraus die passende Applikation bzw. Teilapplikation aufgerufen wird. Wenn man also http://example.com/cart/list aufruft, dann wird der passende Programmcode ausgeführt, der sich um die Anzeige des Warenkorbs kümmert. Soweit so einfach. Innerhalb der Frameworks wird dann häufig per Model-View-Controler gearbeitet. Die Url wird dann noch weiter „genutzt“ um den passenden Controller und die passende Action (sofern es verschiedene gibt) zu ermitteln. Mittlerweile auch gängige Praxis ist es alles was danach noch als scheinbare Verzeichnisstruktur kommt als Parameter zu betrachten, immer wechselweise Name/Wert.

Auf den ersten Blick sieht das ja schick aus, denn die URLs werden dadurch ggf. „sprechender“ bzw. man kann sie sich leichter merken. Aber nicht alles was schön / schick aussieht ist auch technisch sinnvoll. Ich selbst reibe mich regelmäßig an dieser Form der Applikationssteuerung.

Am ärgerlichsten finde ich den Missbrauch der Verzeichnisstruktur zur Parameterübergabe. Hierfür hat das HTTP-Protokoll bzw. das generische URL-Schema nämlich seit den Kindertagen des Netzes eine passende Lösung. Diese nennt sich Query-String und ist an vielen Stellen des Netzes erfolgreich im Einsatz. Es handelt sich dabei um das „Anhängsel“ an Internet-Adressen die nach einem Fragezeichen folgen: Also z.B. http://example.org/suche.html?was=einThema. Die Applikation kann den Querystring (im Code wird er häufig als „GET-Parameter“ genannt) dann direkt auswerten. Auch für den Fall mehrerer Parameter ist vorgesorgt: Diese werden per Kaufmanns-Und (Ampersand) getrennt. Das sieht dann so aus: http://example.org/suche.html?was=einThema&wo=wohnort

Technisch steht dabei das Konzept des Parametrisierens von Programmen (und letztlich Funktionen) dahinter. Das Äquivalent aus der Vor-Web-Zeit (das auch heute immer noch ständig im Einsatz ist) auf einer Kommandozeile (also Bash, SSH und Co) sind Parameter die man dem Programmaufruf mitgeben hat. In den meisten Programmiersprachen werden die Parameter in arg oder argv Array übergeben.

Ich finde es nicht weniger ansprechend als die Verzeichnisschreibweise. Ganz im Gegenteil – ich muss als Benutzer ggf. nicht raten was jetzt Parameter und was noch Verzeichnis ist.

 

Posted in Web |

IPv6 – das „neue“ Internet-Protokoll und der steinige Weg dorthin

Nun habe ich am 22. und 23.05.2014 die Möglichkeit bekommen am IPv6-Kongress in Frankfurt teilzunehmen. So langsam aber sicher wird es Zeit sich um das neue Internet-Protokoll zu kümmern und damit vertraut zu werden. In erster Linie ist es natürlich ein berufliches Interesse, hier am Ball zu bleiben. Aber auch für mich privat als „digital Native“ bis „Nerd“ – irgendwo dazwischen liege ich wohl – ist es natürlich interesant zu wissen was als nächstes kommt.

Nun ersteinmal: Warum das ganze? Nun, das Internet ist langsam aber sicher gewachsen, schneller als man es ursprünglich einmal gedacht hat und noch dazu in Ausdehnungen die sich früher kein Mensch so recht vorstellen konnte. Wichtigstes Prinzip war immer die sogenannte Ende-zu-Ende Kommunikation nach dem Best-Effort-Prinzip: Jeder leitet alle Daten zielführend und so gut es geht weiter, die kleinste Einheit dafür sind sogenannte Pakete. Egal was man an Daten im Internet verschicken möchte, alles wird in kleine Häppchen zerlegt und vom Sender zum Empfänger transportiert. Dabei ist es (fast) unerheblich was transportiert wird: Sprache, Text, Bilder, Videos, Dateien etc.: Alles wird auf die Pakete verteilt – man kann es wie das Versenden einer umfangreichen Lieferung sehen: Was auf einen LKW passt wird auf einen geladen und verschickt, wenn es mehr wird, teilt man es auf. Vorteil: Wenn mal tatsächlich etwas nicht ankommt, muss man nur den fehlenden Teil der Daten nachschicken (da wird es dann mit den LKWs ggf. etwas schwierig).
Was braucht man um Pakete zu verschicken? Richtig, eine Adresse damit der Postbote oder Paketdienst weiß wohin mit der Lieferung. Dazu wurde das Internet-Protokoll entwickelt, kurz IP. Derzeit werden Adressen mit 32 bit Länge verwendet, geschrieben in 4 Blöcken zu je 8 Bit. Das gibt dann Angaben wie 192.168.10.74. Diese Adressen werden gemäß ihrer Historie als IPv4 (vierte Revision des Protokolls in Verbindung mit TCP) bezeichnet.

Nun funktioniert das ja momentan schon, weshalb also ein neues Protokoll einführen? Never touch a running system bzw. never change a winning team…. Nun es gibt gute Gründe dafür, denn das Netz ist seit der letzten Protokollversion immens gewachsen. Niemand hätte anfänglich davon zu träumen gewagt, dass IP derartig populär und weltweit im Einsatz sein würde. Auch waren 32 Bit zu dem Zeitpunkt ein nahezu unvorstellbar großer Zahlenbereich.
Heute hat fast jeder mindestens einen PC, Laptop und ein Smartphone ggf. noch weitere Geräte wie Netzwerkdrucker, IP-Telephone, IP-Webcams, Internetfähige Fernseher etc. Für jedes Gerät wird eine eigene Adresse benötigt… Wenn jeder Mensch auf der Erde ein Gerät hat, dann reicht es schon nicht mehr…
Für den Gebrauch in abgeschlossenen Netzwerken gibt es Adressen, die nicht weltweit eindeutig sind – so lange die Netzwerke nicht miteiander kommunizieren müssen ist das auch legitim. Die bekannstesten Adressen für diesen Fall sind die der Class C: 192.168.x.y, für größere gibt es die Class b (172.16.0.0 bis 172.32.255.255), in großen Unternehmen gibt es meist Class A (10.x.y.z).
Schon früh hat man Methoden entwickelt um Internet-Anschlüsse für mehrere Rechner auf einmal nutzbar zu machen. Einige alte Hasen erinnern sich unter Linux noch an ipfwadm, später ipchains und heute iptables. Die Werkzeuge können noch viel mehr aber eben auch IP Masquerading bzw. Network-Address-Translation (NAT). Noch heute kommen genau die gleichen Mechanismen zum Einsatz, meist hübsch verpackt in einem Multifunktionsgerät das viele als Router bezeichnen (was technisch nur teilweise korrekt ist). Netter Nebeneffekt: ohne besondere Einstellungen (z.B. Portweiterleitungen) sind die Geräte im Netz auch erst mal vor Zugriffen von außen geschützt.
Im öffentlichen Internet dürfen die oben genannten Bereiche nicht verwendet werden, sie fallen (wie einige andrere Bereiche mit speziellen Funktionen) aus den zur Auswahl stehenden IP-Adressen heraus. Es wird also noch knapper.
Nun kann man ja sagen: was einmal klappt, geht auch zweimal… Also schachteln wir doch ein Netz mittels IP Masquerading in ein anderes. Das funktioniert (leider) recht gut. Zudem erhöht es die Sicherheit, sollte man meinen. Schwierig wird es dann aber Geräte in der zweiten Ebene anzusprechen: am eigenen Router kann man noch Portweiterleitungen einrichten, ein Provider mit mehreren tausend kunden kann das nicht. Insgesamt wird also das Ende zu Ende Prinzip ausgehebelt. Im kleinen ist das ja noch ok, aber weltweit wird es schwierig… Denn ein Fernzugriff aus die zentrale Dateiablage daheim ist sehr praktisch (dann muss man die Dateien nicht irgendwelchen Clouddiensten anvertrauen). Genau das klappt dann aber eben nicht mehr.
Es gibt noch einige gute Gründe mehr weshalb IPv4 ersetzungsreif ist, aber das würde den Rahmen hier sprengen.

Nun gut, ich bin technisch ja durchaus interessiert, also würde ich IPv6 dann auch gerne baldest möglich nutzen. Zumal ein Parallelbetrieb ja sogar explizit vorgesehen und möglich ist. Das brauche ich beispielsweise für meinen gut gedienten Netzwerkdrucker, für diesen wird es keine Softwareaktualisierung geben, die ihn  IPv6 fähig macht. Aber der Rest meines Geräteparks ist soweit eigentlich fit. Bis auf … wer hätte es gedacht? Den Router. Nun gut, der hat auch schon einige Jahre auf dem Buckel und es gab ihn bereits bei Vertragsabschluss als Endgerät.

Also frage ich erst mal bei meinem Provider nach, wie es denn aussieht mit IPv6 und vor allem ob es eine Möglichkeit wieder ein subventioniertes Gerät zu erhalten. Fragen kostet nichts und man kann nur Erkenntnis gewinnen. Prompt habe ich die Antwort, das er Ersatz des Routers wahrscheinlich möglich sei, aber ich möge doch bitte nochmal in der Technik anrufen. Gesagt getan. Dort verweißt man mich dann aber doch in die Vetragsbetreuung. Dort heißt es dann, dass ein Upgrade des Routers nur gegen Zuzahlung von 90 EUR möglich ist, was mir für das kleinste Gerät mit Branding dann doch etwas viel Geld ist. Ich lehne das Angebot also erst einmal ab und schaue mich derweil bei den Gerbauchtgeräten um.

Am nächsten Tag erfolgt ein weiterer Anruf, man signalisiert beim Router Entgegenkommen und senkt die Hürde auf 49 EUR – immer noch zu viel wie ich finde – die Geräte gehen bei ebay für um die 35 EUR über den virtuellen Tresen und Versandkosten hätte ich in beiden Fällen. Also ordere ich erst mal eine FritzBox mit IPv6-Fähigkeit – immer in dem Glauben, dass dies das Tor zur IPv6-Welt aufstoßen wird.

Einige Tage vergehen, ich bin auch sonst gut ausgelastet, aber einige Wochen danach komme ich dann endlich dazu die Box anzuschließen. Erste Ernüchterung bei den Fähigkeiten: Bisher gab es zwei normale analaoge Anschlüsse intern, jetzt nur noch einen, der andere ist für ein Fax reserviert (TAE-N-Anschluss) – die Software lässt sich auch nicht überreden den Anschluss zweckentfremdet zu nutzen. Das ist ärgerlich, denn mittlerweile haben wir ja zwei Telefone die wir auch beide parallel nutzen möchten und bisher konnten. Aber egal: Jetzt will ich erst einmal wissen wie es um IPv6 steht und für einen Test ist das Setup ja durchaus geeignet.

Doch was muss ich feststellen: Ich bekomme keine IPv6-Adresse bzw. ein entsprechendes Präfix zugeteilt. Das ist ein Problem des Providers, weshalb ich den wieder kontaktiere. Die Antwort ist diesmal ernüchternd: IPv6 gibt es nur für einige Kunden mit V-DSL und in einem Pilotprojekt. Ein allgemeiner Start ist noch nicht in Aussicht.

Also wird es erst mal nichts mit IPv6 bei mir. Auf eine Lösung mit Tunnel möchte ich eigentlich ungern setzen, die Option Dualstack-Lite wäre für mich ja auch noch OK gewesen. Was bleibt ist ein schaler Beigeschmack über das Verhalten meines Providers bezüglich des Routers – wollte man mir hier einfach nur ein Neugerät verkaufen oder ist das nur ein Kommunikationsproblem gewesen. Ersteres fände ich reichlich dreist, letzteres ist wohl aber in modernen Unternehmen immer wieder der Fall. Warten wir also ab, was kommen wird – vielleicht auch irgendwann IPv6.