HTTP-Fehler 503. Dienst nicht verfügbar: Ein Fall im Hosting-Support

Die Arbeit im Hosting-Support ist im Grunde die gleiche, die meisten Anfragen von Kunden werden nach einem gut entwickelten Schema gelöst, aber manchmal müssen Sie immer noch mit nicht trivialen Problemen konfrontiert werden. Dann besteht die Hauptaufgabe des Ingenieurs darin, den einen zu finden - den einzig richtigen Weg, der zu seiner Lösung führt. In diesem Artikel möchte ich darüber sprechen, wie wir auf unserem gemeinsam genutzten Hosting auf den schwebenden Fehler "HTTP-Fehler 503. Dienst nicht verfügbar" gestoßen sind, wie wir versucht haben, ihn abzufangen, zu diagnostizieren und ein unerwartetes Ende zu erreichen.



Anfang



Das Hosting bietet Benutzern einen typischen Linux + Apache + MySQL + PHP-Stack und einen Management Wrapper. In unserem Fall handelt es sich um ein ISP Manager 5-Geschäft, das auf Centos 7 mit Konvertierung in CloudLinux basiert. Auf administrativer Seite bietet CloudLinux Tools zum Verwalten von Limits sowie einen PHP-Selektor mit verschiedenen Betriebsmodi (CGI, FastCGI, LSAPI).



Diesmal hat uns ein Kunde mit folgendem Problem kontaktiert. Seine Site auf der Wordpress-Engine gab regelmäßig 503 Fehler aus, über die er uns informierte.



Antwortcodes, die mit 50x beginnen, beziehen sich auf serverseitige Probleme. Dies können Probleme sowohl der Site selbst als auch des Webservers sein, der sie bedient.



Typische Situationen, in denen folgende Fehler auftreten:



  • 500 Interner Serverfehler - häufig wird er entweder mit Syntaxfehlern im Site-Code oder mit fehlenden Bibliotheken / nicht unterstützten PHP-Versionen in Verbindung gebracht. Möglicherweise gibt es auch Probleme beim Herstellen einer Verbindung zur Site-Datenbank oder falsche Berechtigungen für Dateien / Verzeichnisse
  • 502 Bad Gateway - Zum Beispiel, wenn Nginx auf den falschen Apache-Webserver-Port verweist oder der Apache-Prozess aus irgendeinem Grund nicht mehr funktioniert
  • 504 Gateway Timeout - Die Antwort von Apache wurde nicht innerhalb der in der Webserverkonfiguration angegebenen Zeit empfangen
  • 508 Ressourcenlimit erreicht - Das dem Benutzer zugewiesene Ressourcenlimit wurde überschritten


Diese Liste enthält nur einige der häufigsten Fälle. Es ist auch erwähnenswert, dass der Benutzer bei Überschreiten der Grenzwerte sowohl 500 als auch 503 Fehler erhalten kann.



Bei der Diagnose dieser Fehler besteht der erste Schritt darin, die Webserverprotokolle zu überprüfen. Dies reicht normalerweise aus, um den Täter zu identifizieren und das Problem zu beheben.



In Bezug auf den 503-Fehler in unserem Fall haben wir einen Eintrag in den Protokollen gesehen:

[lsapi: error] [pid 49817] [client xxxx: 6801] [host XXX.XX] Fehler beim Senden der Anforderung (GET /index.php HTTP / 1.0); uri (/index.php) content-length (0): ReceiveAckHdr: nichts vom Backend zu lesen (LVE ID 8514), überprüfen Sie docs.cloudlinux.com/mod_lsapi_troubleshooting.html
Anhand dieses Protokolls konnte das Problem möglicherweise nicht ermittelt werden.



Primärdiagnose



Zunächst haben wir die Statistiken der Benutzer überprüft, die die Grenzwerte überschritten haben. In den vorangegangenen Tagen wurden geringfügige Überschüsse verzeichnet, aber die Fehler in den Protokollen waren frisch. Außerdem wurden sie in Intervallen von einer bis mehreren Minuten im Protokoll angezeigt.



Wir haben auch die CloudLinux-Empfehlungen unter Verwendung des in den Fehlerprotokollen angegebenen Links untersucht.

Das Ändern von Parametern brachte keine Ergebnisse.



Die Site verwendete eine Datenbank auf einem MySQL 5.7-Server, der auf demselben Server in einem Docker-Container ausgeführt wird. Die Containerprotokolle enthielten Nachrichten:



[Note] Aborted connection 555 to db: 'dbname' user: 'username' host: 'x.x.x.x' (Got an error reading communication packets)


Nur unter diesen Nachrichten befanden sich Nachrichten über die unterbrochene Verbindung der untersuchten Site. Dies ergab die Annahme, dass die Verbindung zum DBMS nicht korrekt ausgeführt wird. Zur Überprüfung haben wir eine Kopie der Site in einer Testdomäne bereitgestellt und die Site-Datenbank in die native Version des DBMS 5.5.65-MariaDB in Centos 7 konvertiert. Auf dem Testgelände wurden mehrere hundert Anforderungen mit dem Curl-Dienstprogramm ausgeführt. Der Fehler konnte nicht reproduziert werden. Dieses Ergebnis war jedoch vorläufig und nach der Konvertierung der Datenbank auf dem Produktionsstandort blieb das Problem bestehen.



Somit wurde das Problem einer falschen Verbindung zum DBMS beseitigt.



Der nächste Vorschlag war zu überprüfen, ob es Probleme mit der Site selbst gab. Zu diesem Zweck haben wir einen separaten virtuellen Server eingerichtet und darauf die ähnlichste Umgebung erstellt. Der einzige signifikante Unterschied ist das Fehlen von CloudLinux. Das Problem konnte auf dem Testserver nicht reproduziert werden. Wir haben also festgestellt, dass im Site-Code alles in Ordnung ist. Wir haben jedoch versucht, Wordpress-Plugins auf die gleiche Weise zu deaktivieren, aber das Problem blieb bestehen.



Infolgedessen kamen wir zu dem Schluss, dass das Problem bei unserem Hosting liegt.



Nach der Analyse der Protokolle anderer Sites wurde festgestellt, dass das Problem bei vielen von ihnen beobachtet wird. Über 100 Stück zum Zeitpunkt der Überprüfung:



/var/www/httpd-logs# grep -Rl "ReceiveAckHdr: nothing to read from backend" ./ | wc -l
99


Während des Tests stellten wir fest, dass das frisch installierte saubere CMS Wordpress auch regelmäßig den Fehler 503 ausgibt.



Ungefähr 2 Monate zuvor haben wir an der Modernisierung des Servers gearbeitet, insbesondere den Apache-Betriebsmodus von Worker auf Prefork geändert, um PHP in verwenden zu können LSAPI statt langsames CGI. Es wurde angenommen, dass dies Auswirkungen haben könnte oder dass einige zusätzliche Apache-Einstellungen erforderlich sind, aber wir konnten den Worker-Modus nicht zurückgeben. Während der Änderung des Apache-Betriebsmodus werden alle Site-Konfigurationen geändert, der Prozess ist nicht schnell und nicht alles könnte reibungslos verlaufen.



Die Korrektur der Apache-Einstellungen ergab ebenfalls nicht das gewünschte Ergebnis.



Unterwegs haben wir nach ähnlichen Problemen in Suchmaschinen gesucht. In einem der Foren argumentierten die Teilnehmer, dass der Hoster ein Problem hat und geändert werden muss, wenn das Problem nicht gelöst wird. Es klingt nicht sehr optimistisch, wenn Sie auf der anderen Seite sind, aber Sie können den Kunden verstehen. Warum braucht er nicht funktionierendes Hosting?



Zu diesem Zeitpunkt haben wir die verfügbaren Informationen und die Ergebnisse der durchgeführten Arbeiten gesammelt. Sie wurden kontaktiert, um CloudLinux zu unterstützen.



Detaillierte Diagnose



Mehrere Tage lang beschäftigten sich die Mitarbeiter des CloudLinux-Supports mit dem Problem. Grundsätzlich betrafen die Empfehlungen die festgelegten Benutzerlimits. Wir haben auch diese Frage geprüft. Bei deaktivierten Grenzwerten (CageFS-Option für den Benutzer) und bei aktivierten Grenzwerten im PHP-Modus als Apache-Modul wurde das Problem nicht beobachtet. Auf dieser Grundlage wurde vermutet, dass CloudLinux in irgendeiner Weise Einfluss hat. Infolgedessen wurde die Anfrage bis Ende der Woche auf die 3. Supportstufe eskaliert, es gab jedoch noch keine Lösung.



Unterwegs haben wir die Apache-Dokumentation zu den CGI- und LSAPI-Modi untersucht, eine zweite Apache-Instanz auf dem Hosting-Server an einem anderen Port mit einer Test-Site eingerichtet, den Einfluss von Nginx beseitigt, indem Anforderungen direkt an Apache gesendet und dieselben Fehlercodes empfangen wurden.



Die LSAPI-Dokumentation hat dazu beigetragen, nur bei der Diagnose von 503-Fehlern Fuß zu fassen:

www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki : php: 503-Fehler

Im Abschnitt Erweiterte Fehlerbehebung wird vorgeschlagen, die im System gefundenen Prozesse zu verfolgen:



while true; do if mypid=`ps aux | grep $USERNAME | grep lsphp | grep $SCRIPTNAME | grep -v grep | awk '{print $2; }' | tail -1`; then strace -tt -T -f -p $mypid; fi ; done


Der Befehl wurde verfeinert, um alle Prozesse in Dateien mit ihren Bezeichnern aufzuzeichnen.



Wenn wir uns die Trace-Dateien ansehen, sehen wir einige der gleichen Zeilen:



cat trace.* | tail
...
47307 21:33:04.137893 --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=42053, si_uid=0} ---
47307 21:33:04.140728 +++ killed by SIGHUP +++
...


Wenn wir uns die Beschreibung der Struktur von Signalen ansehen, die von Prozessen gesendet werden, werden wir das sehen



pid_t    si_pid;       /* Sending process ID */


Gibt die Kennung des Prozesses an, der das Signal gesendet hat.



Zum Zeitpunkt der Untersuchung der Traces befindet sich der Prozess mit PID 42053 nicht mehr im System. Daher haben wir uns beim Erfassen von Traces entschlossen, auch die Prozesse zu überwachen, die das SIGHUP-Signal gesendet haben.

Unter dem Spoiler werden Aktionen beschrieben, die es ermöglichten, zu bestimmen, um welche Art von Prozess es sich handelt, sowie dessen Ablaufverfolgung und zusätzliche Informationen darüber zu erhalten, an welche Prozesse das SIGHUP-Signal gesendet wird.



Trace-Technik
Konsole 1.



tail -f /var/www/httpd-logs/sitename.error.log


2.



while true; do if mypid=`ps aux | grep $USERNAME | grep lsphp | grep "sitename" | grep -v grep | awk '{print $2; }' | tail -1`; then strace -tt -T -f -p $mypid -o /tmp/strace/trace.$mypid; fi ; done


3.



while true; do if mypid=`cat /tmp/strace/trace.* | grep si_pid | cut -d '{' -f 2 | cut -d'=' -f 4 | cut -d',' -f 1`; then ps -aux | grep $mypid; fi; done;


4.



seq 1 10000 | xargs -i sh -c "curl -I http://sitename/"


1 , 4 503, 4.



Als Ergebnis erhielten wir den Namen des Prozesses. /opt/alt/python37/bin/python3.7 -sbb /usr/sbin/cagefsctl --rebuild-alt-php-ini



Dieser Prozess wurde einmal pro Minute im System ausgeführt.



Wir verfolgen mehrere cagefsctl-Prozesse, um mindestens einen von Anfang bis Ende zu verfolgen:



for i in `seq 1 100`; do strace -p $(ps ax | grep cagefsctl | grep rebuild-alt-php-ini | grep -v grep | awk '{print $1}') -o /tmp/strace/cagefsctl.trace.$(date +%s); done;


Als nächstes untersuchen wir zum Beispiel, was er getan hat:



cat /tmp/strace/cagefsctl.trace.1593197892 | grep SIGHUP


Es wurden auch Prozess-IDs erhalten, die mit einem SIGHUP-Signal beendet wurden. Die abgebrochenen Prozesse waren die aktuell ausgeführten PHP-Prozesse.



Die empfangenen Daten wurden an den CloudLinux-Support übertragen, um die Rechtmäßigkeit dieses Prozesses zu klären und um festzustellen, ob er mit dieser Häufigkeit funktionieren sollte.



Später erhielten wir die Antwort, dass die Arbeit des Teams /usr/sbin/cagefsctl --rebuild-alt-php-inikorrekt ausgeführt wird. Die einzige Einschränkung ist, dass das Team zu oft ausgeführt wird. Wird normalerweise aufgerufen, wenn sich ein Systemupdate oder PHP-Einstellungen ändern.



In diesem Fall bleibt nur noch zu überprüfen, wer das übergeordnete Element des cagefsctl-Prozesses ist.



Das Ergebnis ließ nicht lange auf sich warten, und was war unsere Überraschung - der übergeordnete Prozess für cagefsctl war der ispmgrnode-Prozess. Es war etwas seltsam, da die Protokollierungsstufe für den ISP-Manager auf das Maximum festgelegt wurde und der Aufruf von cagefsctl in ispmgr.log nicht angezeigt wurde.



Jetzt gab es genügend Daten, um auch den ISP-System-Support zu kontaktieren.



Ergebnis



Das Problem wurde nach einem ISP Manager-Update ausgelöst. Im Allgemeinen ist das Aktualisieren des ISP-Managers eine normale Situation, führte jedoch zum Start des Synchronisierungsprozesses, der mit einem Fehler endete und jede Minute neu gestartet wurde. Der Synchronisationsprozess rief den cagefsctl-Prozess auf, der wiederum die PHP-Prozesse beendete.



Der Grund für das Aufhängen des Synchronisationsprozesses war die Arbeit am Hosting zur Modernisierung der Ausrüstung. Einige Monate vor dem Auftreten des Problems wurde ein PCI-e NVMe-Laufwerk auf dem Server installiert, eine XFS-Partition erstellt und im Verzeichnis / var bereitgestellt. Benutzerdateien wurden ebenfalls darauf übertragen, aber die Festplattenkontingente wurden nicht aktualisiert. Die Mount-Optionen reichten nicht aus, es war auch erforderlich, den Dateisystemtyp in den ISP Manager-Parametern zu ändern, da Es ruft Befehle zum Aktualisieren von Festplattenkontingenten auf. Für Ext4 und XFS sind diese Befehle unterschiedlich.



So machte sich das Problem einige Monate nach der Arbeit bemerkbar.



Schlussfolgerungen



Wir selbst haben das Problem geschaffen, aber es war bis zum letzten Moment nicht klar. Für die Zukunft werden wir versuchen, so viele Nuancen wie möglich zu berücksichtigen. Mit Hilfe von besser ausgebildeten Kollegen aus dem CloudLinux- und ISP-System-Support wurde das Problem behoben. Jetzt ist unser Hosting stabil. Und wir haben Erfahrungen gesammelt, die uns bei zukünftigen Arbeiten nützlich sein werden.



PS: Ich hoffe, Sie waren daran interessiert, den Artikel zu lesen, und er wird jemandem helfen, ein ähnliches Problem schnell zu lösen.



All Articles