NodeJS vs PHP - Wann was nutzen?

B

BloodSteam

Guest
Moin,
den Unterschied zwischen NodeJS und PHP kenne Ich.
Wann ist NodeJS besser als PHP und viceversa?
Sollte die Registrierung eines Users via NodeJS oder PHP erfolgen?

NodeJS is ja non-blocking, was wenn jemand irgendwo was ändert (bspw ein Mod) und eine andere Person greift auch drauf zu und ändert es auch. Dann wird doch das letzte überschrieben.

In PHP hat alles seine Reihenfolge. Also es empfängt Daten dann sendet es was zurück, was wenn bei NodeJS zwei Sachen gesendet werden und irgendwas durcheinander kommt?
 
Zuletzt bearbeitet:
Hi,

also so zu allererst wäre mal ganz interessant was du vorhast. Aufgrund das ich Software Entwickler bin und auch im Web-Bereich tätig war, habe ich mit beiden Sprachen so meine Erfahrungen gemacht.

NodeJs ist eigentlich nix anderes als Serverseitiges JavaScript (schwach typisiert), dabei handelt es sich eigentlich nicht wirklich um eine non-blocking Sprache, da es zum einen immer noch eine Interpretersprache ist und zum anderen „Threading“ nicht wirklich existiert. NodeJs bietet dir die Möglichkeit mithilfe von Cluster mehrere Instanzen eines Scripts seiner selbst auf die Anzahl verfügbarer Physicher Prozessorkerne zu Forken aber das ist nicht wirklich Threading.

Dein Beispiel müsstest du etwas näher ausführen. Wenn du bspw. einen Webserver laufen hast, auf welchem deine NodeJs backend läuft und mehrere Leute gleichzeitig Datensätze bearbeiten dann werden diese dennoch irgendwo nacheinander ausgeführt. Ein Request wird eher fertig sein als der andere. Wirklich durcheinander kann da eigentlich nichts kommen.

Für größere Backend Systeme welche viele Requests bearbeiten müssen, kann ich dir weder PHP noch NodeJs empfehlen. Ich lege dir Go(lang) ans Herz. Das ist eine sehr Performante kompilierbare Sprache, welche stark typisiert ist und dir nebenläufigkeit via goroutines ermöglicht.

Edit: Es sei denn du möchtest mit SNMPv3 arbeiten, das würde wirklich super in PHP implementiert
 
NodeJS is ja non-blocking, was wenn jemand irgendwo was ändert (bspw ein Mod) und eine andere Person greift auch drauf zu und ändert es auch. Dann wird doch das letzte überschrieben.
Das hat weder etwas mit Blocking oder Non-Blocking der Infrastruktur zu tun. Du musst in diesem Fall das Ganze sehen. Wie werden denn die Daten von einem Nutzer bearbeitet? In allererster Linie über ein Formular, das die alten Daten enthält. Ruft Nutzer A mit dem ersten Request das Formular auf und kurz danach Nutzer B vor dem Speichern von Nutzer A genau das selbe, dann enthalten beide Formulare die gleichen Daten. Nutzer A ändert nun den Inhalt von Feld 3 und Nutzer B von Feld 5, werden genau die Daten überschrieben, die zuerst gespeichert werden. Keiner der Beiden weiß, das ein anderer den Datensatz bearbeitet. Speichert Nutzer A die Daten zuerst, setzt Nutzer B mit seiner Speicherung den Inhalt von Feld 3 wieder zurück und ändert Feld 5 in seinem Wert.

Das Problem, was du schilderst liegt auf Datenbankebene und hat mit der Sprache erst einmal nichts am Hut.
 
@DataDino: nicht zwingend. Wenn ich Felder abspeichere, aktuallisiere ich nur die Felder, die ich auch verändert habe. Sprich: Nutzer A ändert Feld 5 und Nutzer B Feld 3. Nach dem Update sind beide Felder aktuell. Zusätlich kann das Update Statement so schreiben, das man in der WHERE Klausel das alte Feld mit dem alten Wert vergleicht. Wenn sich der in der Zwischenzeit geändert hat, dann gibt es einen Fehler und ein Rollback.

@BloodSteam: Meiner Meinung nach gibt es die beste Programmiersprache nicht. Es kommt immer auf den Anwendungszweck darauf an. Ohne eine genaue Anforderung kann man leider keine Empfehlung Aussprechen.
 
@DataDino: nicht zwingend. Wenn ich Felder abspeichere, aktuallisiere ich nur die Felder, die ich auch verändert habe. Sprich: Nutzer A ändert Feld 5 und Nutzer B Feld 3. Nach dem Update sind beide Felder aktuell. Zusätlich kann das Update Statement so schreiben, das man in der WHERE Klausel das alte Feld mit dem alten Wert vergleicht. Wenn sich der in der Zwischenzeit geändert hat, dann gibt es einen Fehler und ein Rollback.
Genau darauf wollte ich doch hinnaus. Es geht darum, das man diesen Umstand in seine Überlegung mit einbezieht. Es ging schlicht darum, das die Datenkonsistenz in der Datenbank nichts mit der Sprache oder dem Interpreter zu tun hat. Sondern mit der Art und Weise, wie man mit den Datenbanken und den Daten selbst arbeitet.

Ich persönlich hasse dieses Gefuddel mit Feldvergleichen und Rollbacks. Ich bin dazu übergegangen, Datensätze einfach zu locken, wenn sie zur Bearbeitung aufgerufen wurden. So bekommt ein anderer Nutzer direkt Feedback, ob jemand gerade den Datensatz bearbeitet und kann dann, wenn dieser fertig ist mit den aktuellen Daten arbeiten. Das ist meiner Meinung nach komfortabler, als parallel an den Daten zu arbeiten und dann eine Meldung zu bekommen, erneut abzugleichen und dann Änderungen wieder auszuarbeiten. Der zweite im Bunde kann, wenn der Datensatz gesperrt ist, seine Bearbeitung nach hinten verschieben und mit dem aktualisierten Bestand arbeiten. Bis dahin kann er sich um etwas anderes kümmern. Kann er aber parallel arbeiten und bekommt eine entsprechende Meldung, muss er unter Umständen nach seiner Arbeit noch einmal nacharbeiten. Das würde ich dann doch als frustrierend empfinden.
 
PHP:
- Programmieren einzelner Seiten
- Ein Thread/Prozess pro Anfrage
- Synchrones Abarbeiten von Anfragen (Anfrage, warten auf Antwort, weitermachen)
- Beonders gut geeignet für gängige Webseiten
- Hohe Produktivität durch einfachen Upload einer .PHP-Datei
- Einfach zu lernen, da man schnell Ergebnisse erzielen kann

Node:
- Programmieren eines Webservers
- Ein Prozess für alle Anfragen
- Asynchrones Abarbeiten mehrer Anfragen (Anfrage mit Callback, sofort weitermachen, Callback wird irgendwann ausgeführt)
- Besonders gut geeignet für Dinge wie WebSockets, generell Server, Anfragen-Übergreifende Logik ganz ohne Datenbank
- Hohe Produktivität erst durch Einsatz eines Frameworks (sonst: bei jeder Änderung den Prozess neustarten)
- Einfach zu lernen, da man schnell Ergebnisse erzielen kann (npm install express)

Das letzte Mal als ich mich mit PHP beschäftigt habe hatte node auch noch einen signifikaten Throughput-Vorteil, da es aufgrund der Tatsache, dass nie ein Prozess warten muss, mehr Anfragen pro Zeit abarbeiten konnte. Da gab's allerdings noch kein HHVM und PHP7, das kann sich inzwischen also auch relativiert haben.
 
Bezüglich Golang stelle ich übrigens die These auf, dass ein ordentlich entwickeltes Go- und ein ordentlich entwickeltes node- Programm nur marginale Geschwindigkeitsunterschiede aufweisen, insofern es sich nicht unbedingt um einen Video-Encoder o.Ä. handelt. Moderne JavaScript VMs wie V8 sind überraschend schnell. Das Arbeiten mit statischer Typisierung hat aber natürlich seine Vorteile, da es Fehler vermeidet, was im node.js Umfeld meist durch den Einsatz von TypeScript kompensiert wird/werden muss.
 
PHP, Node sowie Golang haben heute etwas gemeinsam. Am Ende wird weniger interpretiert, als wir schreiben. PHP hat bereits einen mächtigen Bytecode-Compiler/Interpreter. Der Prozess hällt zudem die nativen Codes, die aus dem Bytecode kompiliert wird, für gewisse Zeit vor. PHP 7 ist in seiner Ausführung im Vergleich zu seinen Vorgängern pfeilschnell geworden. Zudem ist der Prozess in der Lage, die Systemressourcen optimaler zu nutzen.

Node (V8) kompiliert den Code direkt beim Start einmal in Maschinensprache und hält ihn im RAM vor, wodurch Node durchweg nahzu nativ läuft. Golang kompiliert den Code vorab, bevor er ausgeführt wird. Es bleibt am Ende also nur der Wegfall dieses zwischenschritts.

Ob statische oder dynamische Typisierung Fluch oder Segen ist, ist wie immer eine Einzelfallentscheidung. Ich bin da geteilter Meinung. Mal ist es Fluch und mal ist es Segen. Ich bin in PHP dazu übergegangen, wie auch in statischen Sprachen mir einem Code-Block an den Beginn jeder Funktion, Methode oder Scripts zu setzen, in denen ich die Variablen deklariere ind kommentiere sie mir mit dem Datentyp. Danach kommt es auf die eigene Displin an, diese Datentypen strikt beizubehalten. Aber ich empfinde es auch als unfassbaren Segen, mit dem "Array" in PHP zu arbeiten. Ich liebe es einfach, für Maps, Lists, Strukturen und Arrays ein und die selbe Arbeitsweise zu haben und liebe die Möglichkeit, mit einfachsten Mitteln die Daten zu serialisieren.

PHP hat aber einen unfassbaren Nachteil, den ich in den letzten 10 Jahren immer stärker am eigenen Leib spüren musste. PHP ist einfach zu erlernen ... Auf jeden Fall! Man kommt schnell zu guten und funktionierenden Ergebnissen ... Absolut! Nur diese schnellen, guten und funktionierenden Ergebnisse stoßen auf keinerlei Aktzeptanz mehr. Und dann bringt einem das nichts, wenn man seine Projekte oder Anwendungen mit anderen teilen will. Es wird generell von Anwendungen abgeraten, ohne überhaupt zu wissen, ob die Anwendung etwas taugt oder nicht. Denn so lange die Anwendung nicht auf eines der bewehrten Frameworks basiert, stoßen Anwendungen schnell auf Ablehnung. Ich persönlich lehne hingegen diese Frameworks ab, weil für mich der Code-Overhead und der extrem hohe Grad an Abstraktion gegen den Strich geht. Ich hatte bei PHP nie das Gefühl oder Bedürfnis, irgend etwas so schwerwiegend abstrahieren zu müssen. Das einzige Framework, das ich mir definitiv mal ansehen werde ist F3 (Fat Free Framework). Das sehe ich als leichtgewichtiges und logisches Framework an, mit dem ich mich einigermaßen anfreunden könnte. Aber die anderen Bomber ... Ähm nä!
Fat-Free Framework for PHP
 
Dein Beispiel müsstest du etwas näher ausführen. Wenn du bspw. einen Webserver laufen hast, auf welchem deine NodeJs backend läuft und mehrere Leute gleichzeitig Datensätze bearbeiten dann werden diese dennoch irgendwo nacheinander ausgeführt. Ein Request wird eher fertig sein als der andere. Wirklich durcheinander kann da eigentlich nichts kommen.

Für größere Backend Systeme welche viele Requests bearbeiten müssen, kann ich dir weder PHP noch NodeJs empfehlen. Ich lege dir Go(lang) ans Herz. Das ist eine sehr Performante kompilierbare Sprache, welche stark typisiert ist und dir nebenläufigkeit via goroutines ermöglicht.

Es soll eine Internetseite wie die von Steam werden, wo User Profile erstellen können und wo es Foren (bzw Communities) gibt.

Am Anfang wird es natürlich auch über PHP sehr schnell laufen. Was passiert wenn es doch sehr aktiv wird und alles sehr langsam wirkt? Es soll auch später die Möglichkeit haben zu skalieren.

NodeJS wirkt bisschen wenig durchdacht. Es ist als würde jeder sein Ding durchziehen und es irgendwie alles zusammenkleben. Es gibt auch was neues bzw NodeJS 2.0 namens "DENO" und es ist auch OpenSource, jedoch hab Ich keine Ahnung wie man es benutz etc. Es gibt auch keine Tuts etc dafür. Ich bin besser im Frotnend als im Backend, Backend mit PHP ist sehr einfach auch mit OOPHP. Ich schau mir Golang an.

@Edit
Hab ein cooles Tutorial gefunden.
Basics of Golang [For Beginners] – Hacker Noon
Irgendwie cool was naues zu lernen :D

Braucht man auch ein root server bzw virtual server für Go genauso wie für NodeJS?
 
Zuletzt bearbeitet:
Braucht man auch ein root server bzw virtual server für Go genauso wie für NodeJS?
Kurz ... Ja

Zum Thema skallierung und PHP. Über mehrere Server zu skallieren ist mit PHP ebenfalls kein Problem. Da in der Regel vor einem PHP-Interpreter ein Webserver vorgeschaltet ist und die meisten einen Loadbalancer haben, kann der Webserver Anfragen auch an einen anderen Server weiterleiten. So kannst du die Last auf mehrere Server verteilen. Allerdings musst du dann auch bei der Datenbank auf die Skallierung achten. Gerade das Thema Replikation ist da spannend, aber auch umfangreich. Alternativ kannst du aber auch einen zentralen Server für die Datenbank verwenden.

Und nicht zu vergessen: Mediendateien

Bilder, Videos und Co. verursachen zwar nicht sonderlich viel Last auf dem Server. Aber sie sorgen für starken Traffic, der bei großer Anzahl an Anfragen die Netzwerkanbindung des Servers schnell verstopfen können.
Du solltest also, wenn du merkst, das der Server am Ende ist, genau schauen wo der Bottleneck sitzt. Es bringt nichts, PHP oder die Datenbank über mehrere Systeme zu verteilen, wenn die Mediendaten einfach nur das Interface verstopfen. Dann wäre es vielleicht sinnvoller, die Mediendaten auf einen weiteren Server auszulagern, anstatt die Dienste zu skallieren. Denn in der Regel hält nur bezogen auf PHP ein gut ausgestatteter Server so einiges aus (so lange die verwendete Software nicht bis zum erbrechen aufgeblasen und abstrahiert ist!).
 
Ich glaube es wird nichts mit Golang.
Man bekommt ein Tutorial wo so eine Funktion drin ist:
Code:
func (this *MyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {

Ich verstehe Funktionen so:
Code:
func funcName (parameter) { exec }

Die Dokumentation mag für Leute die C, C#, Golang verstehen Sinn machen, für mich macht es keinen Sinn.
 
Naja mit Tutorials sich durch Programmiersprachen zu hangeln, geht selten gut, weil dadurch oftmals Zusammenhänge unklar bleiben. Man sollte schon ein gutes Handbucg nehmen, das einem Schritt für Schritt durch die Sprahspezifikation führt und genau erklärt, was wo wie bedeutet. Bei einem Tutorial fehlen einfach zu viele Informationen.
 
Das habe ich früher auch so gemacht, habe es aber wegen der Deadlocks aufgegeben. Dann lieber Gefuddel mit Feldvergleichen und Rollbacks.
Deadlocks kann man mit clientseitig getaktetem Reminder unterbinden. Entweder per Ajax oder bei einer Client-App per Hintergrund-Request. Ein Lock ist bei mir meist nur 3 Minuten gültig. Es sei denn, der Client befindet sich noch in der Bearbeitung und meldet dies alle 2 Minuten. Wenn er dies tut, wird der Timestamp der Sperre mit dem aktuellen überschrieben. Wird die Bearbeitung beendet, ohne den Vorgang abzuschließen oder abzubrechen (was der Grund für Deadlocks ist), wird bei einem nächsten Reinigungslauf die Locks entfernt, die älter als 3 Minuten sind. Dieser Vorgang kann zum Beispiel immer dann ausgelöst werden, wenn eine neue Bearbeitung eingeleitet wird (dabei ist es sogar egal, ob es sich um Unterschiedliche Datensatztypen handelt oder nur bei einem Formular für Locks dieses Formulars). Eine einfache Delete-Anweisung mit der WHERE-Klausel, die auf alle Timestamps älter 3 Minuten matcht schmeißt dann die Deadlocks raus. In Intranetumgebungen kann man sogar die Zeiten deutlich reduzieren, da geringere Latenzen und höhere Bandbreiten verfügbar sind.

Nennenswerte Probleme mit Deadlocks habe ich früher nie gehabt.
 
Würde das das aber nicht bedeuten, wenn ich einen komplexeren Datensatz bearbeite, ich dann abgelenkt werde für > 3min und den Rechner stehen lassen muss, die ganzen Änderungen weg sind?

Erkläre mir bitte, wie Du folgendes Szenario mir Record Locking gelöst hast:
Mitarbeiter A erstellt eine Rechnung mit Artikelnummer 1, 3, 5 … 99 (ich übertreibe, ich weiß )
Mitarbeiter B erstellt eine Rechnung mit Artikelnummer 2, 4, 6 … 100.
Die Ganzen Artikel sind gelockt (weil ich ja den aktuellen Warenbestand steuern möchte), Deine App meldet auch brav alle 3 min, der User ist noch am Arbeiten, alles fein soweit. Jetzt möchte der Benutzer A die Artikelnummer 2 zu der Rechnung hinzufügen, bekommt aber die Meldung: Ist in Benutzung versuche es später wieder. In der Zwischenzeit versucht der Benutzer B die Artikelnummer 1 hinzuzufügen, mit ähnlichem Erfolg. Jetzt warten beide und nichts geht mehr.

Meiner bescheidenen Meinung nach, ist Recordlocking ein Relikt aus den 80er/90er Jahren, hat in der modernen Softwarearchitektur nichts zu suchen.
 
Würde das das aber nicht bedeuten, wenn ich einen komplexeren Datensatz bearbeite, ich dann abgelenkt werde für > 3min und den Rechner stehen lassen muss, die ganzen Änderungen weg sind?
Nein es bedeutet, das der Datensatz so lange gesperrt bleibt, bis du die Bearbeitung abbrichst, abspeicherst oder das Fenster schließt und der Timeout abgelaufen ist. Der Client aktualisiert nur den Timestamp.

Erkläre mir bitte, wie Du folgendes Szenario mir Record Locking gelöst hast:
Mitarbeiter A erstellt eine Rechnung mit Artikelnummer 1, 3, 5 … 99 (ich übertreibe, ich weiß )
Mitarbeiter B erstellt eine Rechnung mit Artikelnummer 2, 4, 6 … 100.
Die Ganzen Artikel sind gelockt (weil ich ja den aktuellen Warenbestand steuern möchte), Deine App meldet auch brav alle 3 min, der User ist noch am Arbeiten, alles fein soweit. Jetzt möchte der Benutzer A die Artikelnummer 2 zu der Rechnung hinzufügen, bekommt aber die Meldung: Ist in Benutzung versuche es später wieder. In der Zwischenzeit versucht der Benutzer B die Artikelnummer 1 hinzuzufügen, mit ähnlichem Erfolg. Jetzt warten beide und nichts geht mehr.
Das Problem bekommt man damit nicht gelöst. Denn hier läuft schon vom Grundsatz her etwas komisch. Aus welchem Grund soll ich Artikel-Stammdatensätze bei der Erstellung einer Rechnung sperren?
1. Der Zugriff auf diese Datensätze erfolgt lesend. Einzig bei der Behandlung von Beständen wird geschrieben. Und da würde ich zuerst bei der Aufnahme des Artikels die Menge reservieren und erst bei endgültigen Abschluss vom Ist-Bestand abziehen. Beide Vorgänge dauern keine Sekunde. Ein solcher Lock ist also vertretbar. Und bei so kurzen Sperrzeiten kann man das Skript einfach anweisen, es noch ein paar mal zu versuchen und in der Regel wird dazwischen auch der Datensatz wieder frei. Und wenn der Verkauf des Bestands die Reservierung berücksichtigt, kann es auch nicht zum Überverkauf kommen.
2. Eine Sperre zur Bearbeitung eines Stammdatensatzes muss den lesenden Zugriff nicht zwingend beeinflussen. Ein solcher Stammdatensatz wird aber auch in der Regel selten geändert. Es sei denn es handelt sich um etwas, das tagesaktuell kalkuliert wird.
3. Rechungsspezifische Rabattierungen/Sonderkonditionen sind wie gesagt rechnungsspezifisch und haben mit den Artikelstammdaten auch nichts zu tun.

Recordlock ist auch heute noch verbreitet und es gibt wenig, was dagegen spricht. Ich halte in bestimmten Situationen sogar die Methode mit den Feldvergleichen inkonsequenter. Da sich in der Zwischenzeit durch die Bearbeitung anderer die Rahmenbedingung für eine Anpassung ändern kann ist das Potenzial höher, nacharbeiten zu müssen.

Aber eigentlich sind wir in dem Thread nicht für eine Grundsatzdiskussion. Denn das ist von PHP sowie Node unabhängig.
 
Zurück