"PHP-Projekte in Mini Apps aufteilen: Micro Services mit Kompromissen"


Ich möchte in diesem Artikel gerne einen Ansatz vorstellen, um komplexere Projekte etwas zu modularisieren. Mit komplex meine ich vor allem solche, die verschiedene Komponenten von Drittanbietern verwenden, auf die man vielleicht selbst nicht direkten Einfluss hat. Probleme bei solchen Projekten können sein:

  • Sie "passen" nicht zu dem im Hauptprojekt verwendeten Framework, nutzen z. B. ein eigenes Mini-Framework, das die Code-Menge nochmal erheblich erhöht.
  • Es entstehen Abhängigkeitskonflikte, oder die Komponente hindert uns daran, für unser Code die neuste Version einer Library zu verwenden.

Als praktisches Beispiel:

  • Das eigentliche Projekt ist eine komplexe Website auf Basis des Zend Frameworks
  • Für die Dateiverwaltung auf dem Server wollten wir einen bestehenden Filemanager verwenden. Dieser bietet ein composer package, und einen Front controller (index.php Datei), die man an einem beliebigen Ort, z.B. unter /fileadmin installieren sollte.
  • Dummerweise verwendet der Filemanager das Symfony Framework
  • Für unsere App haben wir zusätzlich zum ZF noch die symfony/filesystem Komponente eingebunden.

Soweit funktioniert alles. Nun möchten wir aber das neuste Feature der Filesystem Komponente nutzen, wir erhöhen also in unserer composer.json Datei die Version von symfony/filesystem. Beim anschließenden composer update dann die Überraschung: Geht nicht, unser Filemanager benötigt eine andere Version. Abhängigkeitskonflikt.

Der Ansatz: Mini Apps

Ein vermutlich ganz guter Ansatz wäre, für diesen Filemanager eine eigene (sub-)Domain zu verwenden, und als komplett unabhängiges Projekt betreiben. Das ist nicht für jedermann machbar, da man z. B. ein weiteres SSL-Zertifikat benötigen würde. Doch Moment, der Teil: "als komplett unabhängiges Projekt betreiben" müsste doch auch auf der gleichen Domain gehen!

Der Ansatz der Mini Apps wäre also, Projekte, die nichts oder nicht viel miteinander teilen, als separate "Services" zu verwalten. Dies erinnert stark an Mikroservices, die ja aktuell gerne verwendet werden. Doch bei Mikroservices geht es i.d.R. um eine komplette Isolation der Services voneinander, inklusive separate Server. Dies wäre natürlich auch hier der Königsweg, ist aber auch mit zusätzlichem Aufwand verbunden. Hingegen könnte man ein Projekt mit "Mini Apps" wie folgt auslegen:

project/

├── api
│   ├── src
│   └── vendor
├── api2
├── common
│   └── logs
├── filemanager  <-- filemanager project
│   ├── config
│   ├── src
│   └── vendor
├── main         <-- main project
│   ├── config
│   ├── src
│   └── vendor
└── web          <-- document root
    ├── api_v1
    │   └── index.php <-- front controller api v1
    ├── api_v2
    │   └── index.php <-- front controller api v2 
    ├── filemanager
    │   ├── index.php <-- front controller filemanager
    │   └── upload    <-- files managed by filemanager
    └── index.php     <-- front controller main project

Wie mittlerweile üblich, sind im document root Verzeichnis web nur die Front Controller und statische Dateien enthalten. Aber anstatt alle Requests auf eine einzige index.php zu routen, und von dort aus verschiedene eigentlich voneinander unabhängige Projekte zu bedienen, nutzt man Unterverzeichnisse mit jeweils eigenständigen Front Controllern, die jeweils eigene Composer Projekte verwenden. Mit letzterem hat man die Möglichkeit, in zwei Projekten die gleiche Library in einer jeweils anderen Version zu verwenden.

Vorteile:

  • Weniger Versionskonflikte
  • Oft einfachere Integration von externen Komponenten (Beispiel filemanager)
  • Je nach Art der Integration von externen Komponenten können diese auch die Antwortzeit für andere Requests erhöhen (z. B. wenn aufwändige Initialisierungen notwendig sind). In diesen Fällen verbessert der Ansatz der Mini Apps also auch die Performance.

Nachteil:

  • Man muss nun mehrere Composer Projekte verwalten
  • Die gesamte Dateimenge ist geringer

Aus meiner Sicht sind die Nachteile hier vertretbar...

Der Fall API Versionierung

In obigem Beispiel-Layout habe ich neben der Hauptkomponente (main) und dem Filemanager als externe Komponente noch eine Api in 2 Versionen definiert. Bei der Weiterentwicklung einer Api hat man oft den Wunsch, auch neuere Abhängigkeiten zu verwenden, die vielleicht mit Teilen der älteren Version nicht kompatibel sind. Die Aufteilung in separate Mini Apps wäre hier eine Lösungsmöglichkeit.

Author: Claudio Kressibucher
Tags: PHP, Web-Applikationen, Micro Services