Wie der Fragentitel andeutet, fällt es mir schwer herauszufinden, was an meiner Anwendung verbessert (oder im Betriebssystem Ubuntu optimiert) werden kann, um eine akzeptable Leistung zu erzielen. Aber zuerst erkläre ich die Architektur:
Der Front-End-Server ist ein 8-Core-Computer mit 8 GB RAM unter Ubuntu 12.04. Die Anwendung ist vollständig in Javascript geschrieben und wird in node.js v 0.8.22 ausgeführt (da einige Module sich über neuere Versionen von Node zu beschweren scheinen). Ich verwende Nginx 1.4, um den HTTP-Verkehr von Port 80 und 443 auf 8 verwaltete Node Worker zu übertragen und begann mit der Verwendung der Node Cluster API. Ich verwende die neueste Version von socket.io 0.9.14, um die Websocket-Verbindungen zu verarbeiten, für die ich nur Websockets und Xhr-Polling als verfügbare Transporte aktiviert habe. Auf diesem Computer führe ich auch eine Instanz von Redis (2.2) aus.
Ich speichere persistente Daten (wie Benutzer und Scores) auf einem zweiten Server auf Mongodb (3.6) mit 4 GB RAM und 2 Kernen.
Die App ist seit einigen Monaten in Produktion (sie wurde bis vor einigen Wochen auf einer einzigen Box ausgeführt) und wird von rund 18.000 Benutzern pro Tag verwendet. Abgesehen von einem Hauptproblem hat es immer sehr gut funktioniert: Leistungsabfall. Mit der Verwendung wächst die Menge an CPU, die von jedem Prozess verwendet wird, bis der Worker staturiert wird (was keine Anforderungen mehr erfüllt). Ich habe es vorübergehend gelöst, indem ich die von jedem Mitarbeiter verwendete CPU jede Minute überprüfe und neu starte, wenn sie 98% erreicht. Das Problem hier ist also hauptsächlich die CPU und nicht der Arbeitsspeicher. Der Arbeitsspeicher ist kein Problem mehr, da ich auf socket.io 0.9.14 aktualisiert habe (die frühere Version hat Speicher verloren), daher bezweifle ich, dass es sich um ein Problem mit Speicherverlusten handelt, insbesondere weil jetzt die CPU ziemlich schnell wächst ( Ich muss jeden Arbeiter ungefähr 10-12 mal am Tag neu starten!). Der verwendete Arbeitsspeicher wächst ebenfalls, um ehrlich zu sein. aber sehr langsam, 1 Gig alle 2-3 Tage, und das Seltsame ist, dass es nicht freigegeben wird, selbst wenn ich die gesamte Anwendung komplett neu starte. Es wird nur freigegeben, wenn ich den Server neu starte! das kann ich nicht wirklich verstehen ...
Ich habe jetzt Nodefly entdeckt, was erstaunlich ist, sodass ich endlich sehen kann, was auf meinem Produktionsserver passiert, und ich sammle seit ein paar Tagen Daten. Wenn jemand die Diagramme sehen möchte, kann ich Ihnen Zugriff gewähren, aber im Grunde kann ich sehen, dass ich zwischen 80 und 200 gleichzeitige Verbindungen habe! Ich hatte erwartet, dass node.js Tausende und nicht Hunderte von Anfragen verarbeitet. Auch die durchschnittliche Antwortzeit für http-Verkehr liegt zwischen 500 und 1500 Millisekunden, was meiner Meinung nach sehr viel ist. In diesem Moment, in dem 1300 Benutzer online sind, ist dies die Ausgabe von "ss -s":
Total: 5013 (kernel 5533)
TCP: 8047 (estab 4788, closed 3097, orphaned 139, synrecv 0, timewait 3097/0), ports 0
Transport Total IP IPv6
* 5533 - -
RAW 0 0 0
UDP 0 0 0
TCP 4950 4948 2
INET 4950 4948 2
FRAG 0 0 0
Das zeigt, dass ich in Timewait viele geschlossene Verbindungen habe. Ich habe die maximale Anzahl offener Dateien auf 999999 erhöht. Hier ist die Ausgabe von ulimit -a:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 63724
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 63724
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Daher dachte ich, das Problem könnte im http-Verkehr liegen, der aus bestimmten Gründen die verfügbaren Ports / Sockets (?) Sättigt, aber eines macht für mich keinen Sinn: Warum, wenn ich die Worker neu starte und alle Clients innerhalb weniger Sekunden wieder eine Verbindung herstellen? Die Belastung der CPU des Arbeitnehmers sinkt auf 1% und kann Anforderungen ordnungsgemäß bearbeiten, bis sie nach etwa 1 Stunde (zur Spitzenzeit) gesättigt ist.
Ich bin hauptsächlich ein Javascript-Programmierer, kein Systemadministrator, daher weiß ich nicht, wie viel Last ich mit meinen Servern erwarten soll, aber es funktioniert sicherlich nicht so, wie es sollte. Die Anwendung ist ansonsten stabil und dieses letzte Problem hindert mich daran, die mobilen Versionen der App zu versenden, die fertig sind, da sie offensichtlich mehr Last bringen und schließlich das Ganze zum Absturz bringen werden!
Hoffentlich gibt es etwas Offensichtliches, das ich falsch mache, und jemand wird helfen, es zu erkennen ... Sie können mich gerne um weitere Informationen bitten, und es tut mir leid für die Länge der Frage, aber ich glaube, es war notwendig ... Danke im Voraus!
top
wenn die CPU-Auslastung nahezu 100% beträgt?