PHP-Entwicklung

PHP-Entwicklung

Posts 1-10 of 11
  • Jens Sieckmann
    Jens Sieckmann
    The company name is only visible to registered members.
    Architekturfrage verteilte Anwendung mit PHP
    Hallo,

    ich habe eine eher architektonische Frage. Es geht darum, rechenintensive Aufgaben innerhalb einer Webapplikation auszulagern, um den Websever zu entlasten. Diese Aufgaben können z.B. das Erstellen großer PDF-Dokumente.

    Natürlich könnte man anwendungsunabhängig die Hardware stärken, aber da macht man es sich als Anwendungsentwickler zu einfach. Ich suche deshalb Konzepte bzw. Architekturen, um die o.g. Aufgaben zu verteilen. Als grundsätzliche Möglichkeiten sehe ich z.B.

    1) REST. Man kann recht einfach mit ein paar Kommandos (GET, POST, PUT etc.) Aufgaben verteilen.
    2) Webservices mit SOAP (z.B. der Standard-SOAPClient und -Server). Etwas mächtiger als REST, aber auch etwas komplizierter.

    Bei diesen beiden stellt sich mir aber die Frage, was passiert, wenn die angefragten Server überlastet sind. Dann müsste auf Serverseite Weiterleitungen auf "freie" Server erfolgen. Gibt es evtl. PHP-Projekte oder Frameworks, die mich bei diesem Problem unterstützen könnten

    3) Job-Server wie z.B: Gearman. Hier habe ich mal etwas zu gelesen. Es klingt durchaus interessant. Gearman hat eine PHP-API, mit der man Aufgaben verteilen kann. Für recht einfache, aber durchaus rechenintesive Tätigkeiten wie o.g. scheint mir das sehr geeignet zu sein. Was aber, wenn es nicht bei einfachen Aufgaben bleibt, sondern komplexe Aufgaben erledigt werden müssen, die komplizierte Logik und Daten enthalten? Dann muss auf der Serverseite diese Logik auch "verstanden" und umgesetzt werden. Aber dieses Problem stellt sich wohl generell.

    4) Wenn mit 2) um eine ganze Architketur erweitert, könnte sowas wie SOA herauskommen, wofür es in http://www.osoa.org/ eine Implementierung (und reichlich Spezifikationen) gibt. Aber hier wird es dann komplex.

    Als zusätzliche Anforderung könnte ich mir prioritätsgesteuerte Aufgaben vorstellen.

    Im Moment habe ich nur ein paar Ideen, von denen ich gerne ein paar weiterverfolgen möchte. Könnt ihr mir aufgrund der obigen Schilderung eine spezielle Möglichkeit empfehlen? Habt ihr konkrete Erfahrungen mit den o.g. Modellen/Architekturen gemacht? Was sind die Vor- und Nachteile? Wie leicht kann man sich einarbeiten?

    Vielen Dank und freundliche Grüße,
    Jens
  • André Sabosch
    André Sabosch
    The company name is only visible to registered members.
    Re: Architekturfrage verteilte Anwendung mit PHP
    Hallo,

    je nach Anwendung ist es sinnvoll, solche Aufgaben asyncron zu erledigen. Die Anwendung schreibt einfach in eine Queue. Aus dieser Queue werden Aufgaben entnommen: immer nur eine definitierte Anzahl von Aufgaben gleichzeitig, damit die Last konstant bleibt.

    Ich persönliche nehme für Queues gerne einen Redis Server. Es gibt jedoch simplere Varianten dies aufzusetzen, zb mit einer vorhandenen mysql oder file-basiert.

    Die Queues lassen sich natürlich auch auslagern, so dass zb REST oder SOAP doch wieder ins Spiel kommt. Aber eine reine Auslagerung ohne Queue verschiebt das Problem nur :)

    Beste Grüße
    André Sabosch
  • Jens Sieckmann
    Jens Sieckmann
    The company name is only visible to registered members.
    Re^2: Architekturfrage verteilte Anwendung mit PHP
    Hallo,

    an eine Queue hatte ich auch gedacht. Und es scheint mir wirklich das einfachste zu sein. Redis klingt interessant, aber ich glaube, es würde auch, wie Sie sagen, eine MySQL tun.

    Eine einfache Tabellenstruktur würde ausreichen: Tätigkeit, Prio und sowas wie eine Payload. Wenn es aber komplizierter wird, muss derjenige, der sich den Task aus der Queue holt noch mit weiterem Input versorgen. Was ist z.B. wenn für die Erzeugung der PDF-Dokumente Inhalte als XML vorliegen, aus denen das Dokument gerendert werden soll? Oder Koordinaten, wohin bestimmte Absätze geschrieben werden oder Bilder als Titelblätter. Macht es Sinn, diese Daten und ggf. Logiken ebenfalls dort zu platzieren wo die Queue ist. Eine Tabelle mit Texts und Blobs?

    Die andere Möglichkeit wäre, den "Task-Abnehmer" mit den notwendigen Rechten und "Vollmachten" auszustatten, um sich die entsprechenden Daten und Logiken zu besorgen. Und da wäre man wieder ein Stück bei Webservices, denen man diese Payload übergibt.

    Viele Grüße,
    Jens
  • André Sabosch
    André Sabosch
    The company name is only visible to registered members.
    Re^3: Architekturfrage verteilte Anwendung mit PHP
    >Redis klingt interessant, aber ich glaube, es
    würde auch, wie Sie sagen, eine MySQL tun.
    Das liegt sicher mit am Umfang. Wir pflegen Queue Systeme in denen sekündlich nach fälligen Aufgaben geschaut wird. Da ist eine Queue in Redis wesentlich Resourcen schonender.

    Eine Tabelle mit Texts und Blobs?
    Meine Erfahrungen aus dem High-Traffic Bereich: lassen Sie Ihre Datenbanken so klein wie möglich! Solche Daten gehören nicht direkt in die Queue, in Datenbanken auf umfangreichere Daten (Bilder, etc) nur verweisen.

    Sollten Sie die Queues auf einem externen System betreiben, können Sie Binärdaten etc sehr schön auf einem System wie Amazon S3 pflegen, damit jeder Server Zugriff hat.

    Apropos Amazon, mit SQS bietet Amazon auch eine Queue Struktur an.

    Und da wäre man wieder ein Stück bei Webservices, denen man diese Payload übergibt.
    Es kann auch eine Kombination sinnvoll sein. Um die Last auf dem Webservices Systeme konstant zu halten, rufen Sie diese aus einer Queue Struktur auf.

    Beste Grüße
    André Sabosch
  • Harald Doderer
    Harald Doderer    Premium Member
    The company name is only visible to registered members.
    Re^4: Architekturfrage verteilte Anwendung mit PHP
    André Sabosch schrieb:

     
    Eine Tabelle mit Texts und Blobs?
     
    Meine Erfahrungen aus dem High-Traffic Bereich: lassen Sie Ihre Datenbanken so klein wie möglich! Solche Daten gehören nicht direkt in die Queue, in Datenbanken auf umfangreichere Daten (Bilder, etc) nur verweisen.
     

    Also grundsätzlich sollte man so wenig Daten wie möglich und soviel wie nötig haben. Egal ob in einer DB oder nicht. Das ist klar. Aber wenn man ein mehrstufiges "Publishing" macht, dann spielt es eine größere Rolle wie die Daten verteilt sind.

    Ohne Verteilung sieht es ja meistens so aus:
    Backend => DB => Frontend

    Etwas besser ist es so:

    Backend => DB (gut normalisiert) => Publish => DB (mit Aggregaten, Suchtabellen usw. und ggfs auf einzelne Systeme verteilt) => Webservice => Frontend

    Das sieht jetzt natürlich umständlich aus, hat aber ein paar Vorteile. Man greift im Frontend nur auf publizierte Inhalte zu, spart sich also das Filtern der noch nicht veröffentlichten Inhalte. Dadurch bleiben die Daten übersichtlicher.
    Suchtabellen, beispielsweise nach dem Schema ID, Content_Typ, Content_ID, Content_Name bieten sich an, wenn man im Frontend z.B. eine Auswahlbox anbieten will, die durchsuchbar sein soll. Im Frontend wird beim Formular immer nur die Content_ID hinterlegt und als Anzeigename der Content_Name.
    Klickt man dann auf einen solchen Eintrag kann man mit der Content_ID und Content_Typ auf die Aggregat Tabellen zugreifen ohne dass man vorher schon sämtliche Inhalte braucht. Man spart sich das mühsame JOIN Spiel über viele viele normalisierte Tabellen und kann ein simples SELECT verwenden.

    Im weiteren Schritt kann man sich sogar diese DB Abfrage sparen, wenn man das Aggregate schon als Objekt serialisiert auf Platte legt.
    Um das Aktualisieren kümmert sich das Publish.

    Jetzt kommt der Webservice wieder ins Spiel.
    Der besteht aus Client und Service. Im Frontend haben wir dann eine Sammlung von Clients. Die Services können auf verschiedenen Servern liegen und dort auf ihre Datenquellen (FILE, DB, weitere Webservices usw) zugreifen.
    Nun ist SOAP ja schon eine gute Idee, aber hat den Nachteil, dass man XML als Austausch Format hat, was bei größeren Daten in PHP langsamer wird bei der Umformatierung.
    Ich würde hier falls möglich mit REST und JSON arbeiten.

    Das bietet zwei Vorteile.

    Erstens kann man mit json_encode und json_decode nativ Objekte und Arrays hin und herkonvertieren ohne großen XML Overhead.

    Zweitens kann man im View (hier Browser gemeint) auch per JavaScript und AJAX diese Webservices mit JSONP ansteuern.
    Sprich man kann sich den Umweg über den Server manchmal einfach sparen und Darstellungsgeschichten direkt über den Browser abfackeln und asynchron arbeiten. Erfordert zwar dann schon wieder Javascript aber das lässt sich bei sauberen Codes auch schon ein Stück weit automatisiert generieren.

    Gehen wir nun einen Schritt weiter, dann ist die Sammlung von Webservice Clients im Frontend selbst irgendwann ein Flaschenhals, weil wir jede Menge TCP Traffic erzeugen.

    Dann hat man die Möglichkeit Caches zu verwenden. Dann wird die Anfrage jeweils nur initial benötigt. Aber sie passiert eben mindestens einmal.

    Auch nicht so schön. Aber meistens schon ausreichend. Noch etwas besser wäre es dann, wenn man sich sogar das sparen kann. Das geht, wenn man zwischen die Webservices und dem Frontend Server einen Distribution Server schaltet, der sich um die vielen einzelnen Webservice Verbindungen kümmert und selbst per Webservice Client erreichbar ist.
    Der Vorteil liegt dann darin, dass man sich auf Frontendseite auf wirklich wenige Requests konzentrieren kann und das große Einsammeln delegiert. Ich schreibe wenige Requests, denn dynamische Dinge wie Usereingaben, Suchanfragen etc. müssen vom Frontend richtig weitergeleitet werden, was nicht zwangsläufig auf den selben Server gehen muss.

    Jetzt ist so ein Distribution Server praktisch, aber bringt allein auch den Nachteil, dass er selbst zum Flaschenhals werden könnte. Deshalb sollte es dann schon mehrere gleichartige solcher Server geben. Dann kann man im Frontend beispielsweise mit GEARMAN per Zufall oder gesteuert nach Reihenfolgen usw. diese Lasten verteilen.

    Das ist natürlich auch generell für alle Webservices sinnvoll, wenn wir im Hochlastbereich sind. Immer schön auf mehrere Server gleichmäßig verteilen.

    Allerdings ist das nicht das Ende der Optimierung. Wenn man jetzt diesen einen Frontend Server hat, bricht er irgendwann vielleicht auch ein, obwohl er selbst fast nichts mehr tut.

    Dann hat man noch die Option klassisches Load Balancing zu fahren und mehrere Frontend Server einzuspannen.

    Ein allgemeiner Nachteil ist aber immer dabei: je verteilter die Systeme desto komplexer wird die Wartung. Allerdings gewinnt man Flexibilität und kann einzelne Komponenten gezielt austauschen, sofern man sich auf saubere APIs verständigt hat.

    Nachtrag: das mit der Queue habe ich jetzt mal außen vor gelassen. Das setze ich einfach mal als gegeben für die einzelnen Schritte.

    Als kleine Faustregel: Das Publish hat immer mehr Zeit zur Verfügung als der Aufruf der Seite übers Frontend. Darum sollte man komplexe Dinge möglichst von Frontend nach Backend / Publish verlagern.

    Und weiter: dem User ist es egal wie komplex die Daten im Hintergrund sind, er braucht sie auf _einer_ Seite, also letztlich sowieso aggregiert. Darum sollte im Frontend alles so einfach wie möglich zusammengefasst sein.
    Im Backend dagegen muss alles so granular und atomar sein, wie möglich um konsistente nicht redundante Daten zu erzeugen und verwalten zu können.
    This post was modified on 28 Aug 2011 at 02:25 pm.
  • Post visible to registered members
  • Post visible to registered members
  • Post visible to registered members
  • Daniel Scherrer
    Daniel Scherrer
    The company name is only visible to registered members.
    Re: Architekturfrage verteilte Anwendung mit PHP
    Die Frage ist halt auch immer von was für eine Datenmenge wir hier reden. Ich denke um einen richtigen Architekturvorschlag zu machen, benötigt man mehr "Randinformationen" welche essenziell für eine optimale Beantwortung der Frage ist.

    Wenn ich eine Webapplikation für 10 aktive User, welche pro Tag 5-10 PDFs generieren, darf ich eine andere Architektur verwenden, wie wenn ich ca. 1000 User mit rund 300 PDFs pro Tag habe.

    Als zusätzliche wichtige Frage stellt sich doch noch das Budget für das zu erstellende System. Wenn ich zwar die 1000 User Variante habe, aber dennoch mit einem Budget von 0 Euro (für Investitionen, etc.) auskommen muss, bedeutet dies meistens mehr Aufwand als Entwickler. Wenn ich jedoch ein Budget von x Tausend Euro für Investitionen und x tausend für den Betrieb habe, dann kann man natürlich eine ganz andere Variante bevorzugen.

    Als 3. Punkt ist die Kritikalität wohl auch noch zu bemessen. Wenn es den 10 Key-Usern, welche diese Applikation verwenden mal egal ist, dass das System "ausgelastet" ist, dann benötigt man natürlich nicht ein solch umfangreiches LoadBalancing-System. Btw. braucht man das ja sowieso nur, wenn die Lastspitzen über die eigentlichen Ressourcenkapazität steigen. Ist dies denn der Fall? Also versteht mich nicht falsch. Ich liebe gute skalierbare Systeme welche nahezu unmöglich sind in die Knie zu zwingen. Aber für ein Intranet-System, welche wie schon gesagt von wenigen Usern benutzt werden, wäre dies wohl zu Overpowered in meinen Augen.


    Lange Rede, kurzer Sinn:

    Es gibt viele Ansätze. Viele Gute wurden hier schon erwähnt. Wenn ich jetzt als Entwickler eine solche Applikation entwickeln müsste, dann würde ich in erster Linie auf den REST/SOAP-Webservice Ansatz zurückgreifen, welcher Asynchron die Daten übermittelt. Auf der Seite des Clients würde ich die Asynchronität mittels eines AJAX-Scripts realisieren (wenn natürlich der User Besitzer der zu generierenden Daten ist und dies nicht anderweitig über andere Systeme/Schnittstellen automatisiert werden kann).

    Bei grösserem Budget, vielen Usern und schnell benötigter Realisierung wäre dies natürlich der klassische Ansatz für die Verwendung von CloudComputing-Technologien eines Public Cloud Providers.

    z.B. (bring jetzt Azure, da ja der Begriff AWS schon verwähnt wurde):
    Bei Azure kann ich einen gewünschten Service entwickeln, welcher genau die Lastenfrage mittels LoadBalancing von sich aus löst (interne Mechanismen, je nach Konfiguration). Als Entwickler muss ich mich nur noch um die WebApp, sowie den Service kümmern (WebApp: kann ein Webserver im eigenen RZ sein oder bei einem externen Provider oder auch der Azure-Plattform. Microsoft unterstützt relativ gross PHP). Wenn also eine Instanz ausgelastet ist, wird einfach eine neue hinzugeschaltet. Wenn die Last tief ist, ist sie auf dem Minimum. Die Verrechnung findet auf die tatsächlich verwendeten Ressourcen statt.
    Wenn ein Webservice abgestürzt ist, wird automatisch eine exakt gleiche wieder hochgefahren und steht jederzeit zur Verfügung.
  • Jens Sieckmann
    Jens Sieckmann
    The company name is only visible to registered members.
    Re^2: Architekturfrage verteilte Anwendung mit PHP
    Hallo,

    ja, sowas kommt durchaus auch in Frage. Ein Request auf einen Loadbalancer zu einem von x Servern, wo PDFs generiert werden. Die müssen dann natürlich Zugriff auf die Daten haben, aus denen das PDF generiert wird.

    Das ganze muss geschedult werden, ist also in erster Linie kein on-Domand-Prozess.

    Gruß,
    Jens