Technischer Aufbau von Allschools

20.05.2010
 

 

Die neue Seite von Allschools hat inzwischen ja schon ein paar Monate auf dem Buckel und endlich komm ich mal dazu den versprochenen Artikel über die Technik hinter der Neuauflage zu schreiben. Wie eben schon erwähnt geht es hier primär um Technik und somit richtet sich dieser Blog primär an die Nerds und Programmierer unter Euch. Mit der neuen Allschools Version haben wir im Vergleich zu den anderen Fanzines und professionell arbeitenden Online Magazinen auf technischer Ebene einen anderen Weg eingeschlagen. Wir verwenden nämlich weder ein Content Management System oder eine Forensoftware oder eine PHP / MySQL basierte Lösung sondern haben uns in Sachen Software Architektur und Programmierung eher von Twitter, Xing, Facebook (obwohl die noch stark auf PHP setzen) und co. beeinflussen lassen. Lasst uns aber doch erstmal weit in die Vergangenheit blicken:

Allschools hat vor 13 Jahren auf Geocities losgelegt und wurde ein paar Jährchen später mit einer reinen HTML Oberfläche ausgestattet. Das Framelayout war natürlich obligatorisch.



Schon kurze Zeit später hab ich dann angefangen an einem PHP basierten Prototypen zu basteln. Aus diesem ging dann das Magazin disfunction.de hervor, welches jedoch ein paar Jahre später wieder in Richtung Allschools überführt wurde.



Die Technik von Disfunction wurde jedoch übernommen und war die Basis für die erste Datenbank-basierte Allschools Fassung. Dieses Ding hat uns dann auch auf technischer Ebene recht lange begleitet. Hier und da wurde zwar noch ein wenig am Design gefeilt und geschraubt aber im Hintergrund blieb alles beim Alten.



Gleiches gilt auch für die Zeit nachdem Torben das Magazin von mir und Simone übernommen hatte. Jedoch sorgte Torben nochmals für ein größeres und auch überfälliges Redesign der Seite.




Um ganz ehrlich zu sein: zum Schluss hab ich die Seite und den PHP-Spaghetti Code gehasst wie die Pest. Es war klar, dass was neues her musste und zwar von Grund auf. Aber wie sollten wir das Ding programmieren. Ein Standard Content Management System wie Typo3 war eine Option, diese wurde jedoch wegen der bestehenden Datenbank recht schnell verworfen. Im Rennen waren dann noch ein kompletter Rewrite auf Basis von PHP, Ruby On Rails oder einer Java basierten Lösung. PHP flog relativ schnell aus dem Rennen weil wir diesbezüglich mit der Vorgänger Version einfach nicht glücklich waren. Ruby On Rails wurde verworfen weil mich der Datenzugriff nicht überzeugen konnte (Fehlen von Bind Variablen) und so hab ich mich für eine Java basierte Lösung entschieden. Im Bereich des Backends waren die Technologien schnell gesetzt: PostgreSQL ist und bleibt die Datenbank der Wahl im Hause Allschools. Das war schon vor 10 Jahren so und wird auch weiterhin so bleiben. Im Java Umfeld haben wir uns für folgende Haupttechnologien entschieden:

Hibernate sorgt für die Persistierung unserer Daten.

Spring wird primär für die Bereiche Dependency Injection / Wiring von Komponenten, Aspekt Orientierte Programmierung mit AspectJ und Transaktionssteuerung verwendet.

Spring und Hibernate sind im Java EE Umfeld de-facto Standards und werden auch im professionellen Umfeld häufig eingesetzt. Betrachtet man den Markt für Java Web Frameworks wäre Java Server Faces mit einer entsprechenden Komponenten Bibliothek die naheliegende Wahl. Allerdings besitzt JSF in der Version 1.x einige Design Flaws (welche grösstenteils in 2.0 addressiert wurden). Des Weiteren kann mich das stark markup-orientierte „Programmiermodell“ auch in der Folgeversion nicht überzeugen. Deshalb habe ich für Allschools Wicket als Web Framwork auserkoren. Wicket ist, wie JSF und Tapestry, ein Komponenten-basiertes Framework für die Programmierung von Web Oberflächen. Das schöne an Wicket ist im Vergleich zu den Konkurrenten jedoch die Verwendung von reinem Java und reinem HTML ohne Taglibs. Des Weiteren besitzt Wicket eine sehr gute Unterstützung für AJAX und ist hervorragend dafür geeignet wiederverwendbare UI-Komponenten zu programmieren. Die Comment Section von Allschools ist zum Beispiel ein einziges Code Artefakt, welches auf den jeweiligen Seiten einfach wiederverwendet wird.

Um ein sauberes, cross-Browser fähiges und möglichst barrierefreies HTML zu erhalten verwenden wir die CSS Bibliothek YAML. An dieser Stelle möchte ich hervorheben, dass wir mit der Kombination Wicket + YAML sehr gute Erfahrungen gemacht haben. Das fertige Design von Lena konnte ich so in gerade mal 1-2 Stunden Arbeit über den Anwendung stülpen.



Intern ist Allschool in einer 3-Schicht Architektur aufgebaut:

Die UI Schicht sorgt für die Darstellung und das Verhalten der Seite.

Die Geschäftslogik Schicht kümmert sich und die „fachliche“ Logik.

Die Datenhaltungsschicht (basierend auf dem Data Access Object Pattern) regelt die Zugriffe auf unsere Datenbank.

Der Zugriff erfolgt immer von „oben nach unten“. Soll heissen: die UI greift niemals direkt auf die Datenbank zu. Des Weiteren sind wir somit problemlos in der Lage weitere Clients wie zum Beispiel iPhone, Android oder iPad aufzuschalten. Alles was wir machen müssten wäre die Publikation der Business Services via REST oder WebService.

Soweit so unspannend. Viel interessanter ist jedoch die Art und Weise woher die Daten, die ihr täglich auf der Seite seht, kommen. Bei Allschools kommen 99% der Daten aus dem Speicher und nicht aus der Datenbank. Unsere Datenbank ist eigentlich nur noch ein Backup für einen Server-Restart. Den Rest erledigt ein mehrschichtiges Caching System, welches dem von Twitter nicht unähnlich ist. Im Regelbetrieb kommen wir somit pro Seitenaufruf mit einem einzigen Datenbank Zugriff aus: dem Update des View-Counts unseres Banners. Der Rest kommt aus dem Cache.



Das Cache System ist wie folgt aufgebaut. Auf Ebene der Datenhaltungs-Schicht haben wir neben dem obligatorischen First-Level Cache von Hibernate einen Second-Level Cache konfiguriert, der einzelne Entitäten und Abfragen im Speicher vorhält. An dieser Stelle verwenden wir die Java Bibliothek EHCache. Dieser erste Cache ist am Ende des Tages ein Feature von Hibernate. Neben diesem Cache habe ich einen AOP Interceptor programmiert, der sich zwischen die UI-und die Geschäftslogik-Schicht hängt und read-only Aufrufe abfängt. Allschools basiert zu grossen Teilen aus rein lesenden Zugriffen, weshalb dieser Cache so effizient arbeiten kann. Der eben erwähnte Interceptor interagiert mit einem weiteren Cache, der nicht auf EHCache sondern auf Memcached basiert. Memcached ist ein verteilter, Speicher-basierter Cache der es ermöglicht eine Anwendung beliebig zu skalieren. So könnten wir beispielsweise jederzeit einen weiteren Cache Server aufschalten wenn wir jemals Last- und Skalierungsprobleme bekämen. Memcached ist auch das Caching-Rückrat von Twitter und Facebook. Angenommen User „Heinz“ ruft die CD-Kritik der neuen Heaven Shall Burn Platte auf so würde die Allschools Anwendung zuerst über den Interceptor in Memcached nachschauen ob die entsprechende Kritik dort im Speicher vorrätig ist. Falls das der Fall ist, dann würden wir an dieser Stelle den Aufruf abbrechen und die Daten direkt aus dem Speicher an die Oberfläche liefern. Wenn der Datensatz nicht gefunden wird gehen wir durch die Geschäftslogik auf die Datenzugriffsschicht. Dort würde Hibernate erst einmal in seinem First Level Cache nachschauen um dann zu versuchen einzelne Entitäten aus dem EHCache basierten Second-Level zu ziehen. Erst wenn auch dieser Zugriff nicht von Erfolg gekrönt ist würden wir auf die Datenbank zugreifen und dann die beiden Caches mit den Daten zu befüllen und die CD-Kritik an die Web-Oberfläche zu liefern.

Ich denke, dass wir mit dieser Architektur eine extrem starke und saubere Basis für die nächsten Jahre Allschools haben werden und hoffe, dass das ganze für die Techies unter euch interessant war. Rückfragen gerne hier als Comment oder via PM.