Überwachen Sie Python-Webanwendungen mit Prometheus

image.png

In diesem Artikel wird eine einfache [Flasche](http :) unter uWSGI + nginx ausgeführt. //flask.pocoo.org/) Ich zeige Ihnen anhand eines Beispiels, wie die Anwendung bei der Überwachung voll funktionsfähig ist.

Eine kleine Geschichte

Prometheus war ursprünglich ein Überwachungstool, das von [Googles Borgmon] abgeleitet wurde (https://landing.google.com/sre/sre-book/chapters/practical-alerting/).

In einer nativen Umgebung setzt Borgmon auf eine allgegenwärtige und einfache Serviceerkennung. Die überwachten Dienste werden von Borg verwaltet und sollten leicht zu finden sein. Beispielsweise werden alle Jobs in einem Cluster bestimmter Benutzer ausgeführt, oder bei komplexeren Bereitstellungen alle Unteraufgaben, aus denen der Job zusammen besteht.

Jedes dieser Ziele könnte ein einzelnes Ziel für Borgmon sein, um Daten vom Endpunkt `/ varz``` sowie vom Prometheus` /metrics``` abzurufen. Es handelt sich normalerweise um einen Multithread-Server, der in C ++, Java, Go oder (seltener) Python geschrieben ist.

Prometheus erbt viele von Borgmans Annahmen über seine Umwelt. Insbesondere geht die Clientbibliothek davon aus, dass die Metriken aus verschiedenen Bibliotheken und Subsystemen mehrerer Ausführungsthreads stammen, die in einem gemeinsam genutzten Adressraum ausgeführt werden, und auf der Serverseite hat Prometheus ein Ziel. Angenommen, Sie sind (wahrscheinlich) ein Multithread-Programm.

Mach es nicht so

Diese Annahmen wurden in vielen Nicht-Google-Bereitstellungen, insbesondere in der Python-Welt, gebrochen. Hier verteilen wir die Anfrage an mehrere Mitarbeiter (z. B. mit Django oder Flask). WSGI Es ist üblich, auf einem Anwendungsserver ausgeführt zu werden (jeder Worker ist ein Prozess, kein Thread).

Bei einer einfachen Bereitstellung des Prometheus Python-Clients für Flask-Apps, die unter uWSGI ausgeführt werden, trifft jede Anforderung des Prometheus-Servers an `` `/ metrics``` einen anderen Arbeitsprozess mit jeweils einem eigenen Zähler. Exportieren Sie das Histogramm usw. Infolgedessen werden die Überwachungsdaten zu Müll.

Tatsächlich gibt jeder Kratzer auf einem bestimmten Zähler den Wert eines Arbeiters zurück, nicht den gesamten Job. Der Wert sollte herumspringen und Ihnen sagen, dass nichts für die gesamte Anwendung nützlich ist.

Lösung

Amit Saha hat das gleiche Problem und Various Solutions -with-prometheus.html) wird in einem ausführlichen Artikel besprochen. Wie in einem der Artikel beschrieben, enthält der Prometheus Python-Client einen Multiprozessmodus, der diese Situation bewältigen soll. Ein Beispiel für die Motivation von Anwendungsservern ist gunicorn.

Dies funktioniert, indem das Verzeichnis mmap () 'd Wörterbücher zwischen allen Prozessen in der Anwendung geteilt wird. Machen. Jeder Prozess führt dann eine Berechnung durch, um eine gemeinsame Ansicht der anwendungsweiten Metrik zurückzugeben, wenn diese von Prometheus abgekratzt wird.

Dies hat einige "Überschrift" Nachteile in der Dokumentation erwähnt. Beispiele hierfür sind das Fehlen kostenloser Python-Metriken pro Prozess, das Fehlen einer vollständigen Unterstützung für bestimmte Metriktypen und die etwas komplexeren Messgerätetypen.

End-to-End-Konfigurationen sind ebenfalls schwierig. Hier ist, was Sie brauchen und wie Sie jeden Teil in Ihrer Umgebung erreicht haben. Hoffentlich ist dieses vollständige Beispiel für alle nützlich, die in Zukunft ähnliche Arbeiten ausführen.

  1. Das gemeinsam genutzte Verzeichnis muss als Umgebungsvariable `` `prometheus_multiproc_dir``` an den Prozess übergeben werden. Übergeben Sie die Option uWSGI env. Siehe uwsgi.ini.

  2. Das freigegebene Client-Verzeichnis muss nach dem Neustart der Anwendung gelöscht werden. Dies ist etwas schwer zu verstehen, aber in den [Hardcoded Hooks] von uWSGI (https://uwsgi-docs.readthedocs.io/en/latest/Hooks.html#the-hookable-uwsgi-phases) Verwenden Sie eine, `exec-asap```, um das Shell-Skript unmittelbar nach dem Lesen der Konfigurationsdatei und bevor Sie etwas anderes tun (https: //uwsgi-docs.readthedocs) auszuführen. io / de / latest / Hooks.html # exec-run-shell-Befehle). Siehe [uwsgi.ini](https://github.com/hostedgraphite/pandoras_flask/blob/master/conf/uwsgi.ini#L14). Dieses Skript löscht und erstellt das freigegebene Datenverzeichnis des Prometheus-Clients neu (https://github.com/hostedgraphite/pandoras_flask/blob/master/bin/clear_prometheus_multiproc). Um die richtigen Berechtigungen zu überprüfen, führen Sie uwsgi als `root``` unter Supervisor (http://supervisord.org/) aus und entfernen Sie privs in uwsgi (https :: //github.com/hostedgraphite/pandoras_flask/blob/master/conf/uwsgi.ini#L18).

  3. Die Anwendung muss den Multiprozessmodus des Python-Clients festlegen. Dies geschah hauptsächlich über Sahas Post. (https://github.com/prometheus/client_python#multiprocess-mode-gunicorn). Siehe metrik.py. Es enthält auch eine ordentliche Middleware (https://github.com/hostedgraphite/pandoras_flask/blob/master/pandoras_flask/metrics.py#L17), die Prometheus-Metriken für Antwortstatus und Latenz exportiert. Bitte beachte, dass

  4. uWSGI muss die Anwendungsumgebung so konfigurieren, dass die Anwendung nach fork () geladen wird. Standardmäßig versucht uWSGI, Speicher zu speichern, indem die Anwendung und dann `fork ()` geladen werden. Dies hat sicherlich den Vorteil von Copy on Write (https://en.wikipedia.org/wiki/Copy-on-write), wodurch viel Speicherplatz gespart werden kann. Es scheint jedoch den Multi-Prozess-Modus des Clients zu stören. Vielleicht liegt es daran, dass Lock before fork () so angewendet wird. uWSGIs Option für faule Apps Sie können es verwenden, um die Anwendung nach dem Gabeln zu laden, was zu einer saubereren Umgebung führt.

Dadurch können die `` `/ metrics```-Endpunkte von Flask-Apps, die unter uWSGI ausgeführt werden, in der pandoras_flask-Demo funktionieren und voll funktionsfähig sein. Ich denke du kannst es schaffen.

Beachten Sie, dass die Demo den metrischen Endpunkt für einen anderen Port (https://github.com/hostedgraphite/pandoras_flask/blob/master/conf/nginx.conf#L28) für die entsprechende App verfügbar macht. Bitte. Dies macht es einfach, Zugriff auf die Überwachung zu gewähren, ohne dass der Benutzer Zugriff darauf hat.

In Ihrer Bereitstellung sollten Sie in der Lage sein, uwsgi_exporter zu verwenden, um weitere Statistiken von uWSGI selbst abzurufen.

Charakteristisch

In Sahas Blogpost (https://echorand.me/your-options-for-monitoring-multi-process-python-applications-with-prometheus.html) ist die empfohlene Lösung local [statsd]( Es beschreibt eine Reihe von Alternativen, indem Metriken über (https://github.com/etsy/statsd) übertragen werden. So mögen wir es nicht wirklich.

Letztendlich bietet das Ausführen von allem unter einer Container-Orchestrierung wie kubernetes eine native Umgebung, in der Prometheus glänzt, nämlich das vorhandene Python. Dies ist ein großer Schritt, um weitere Vorteile im Anwendungsstapel zu erzielen.

Der vielleicht vielversprechendste Zwischenschritt besteht darin, jeden Teilprozess einzeln als Scraping-Ziel zu registrieren. Dies ist [django-prometheus](https://github.com/korfuri/django-prometheus/blob/master/documentation/exports.md#exporting-metrics-in-a-wsgi-application-with-multiple-processes- Der Ansatz pro Prozess), aber der vorgeschlagene "Port Range" -Ansatz ist etwas komplizierter.

In unserer Umgebung können Sie diese Idee auf folgende Weise implementieren (möglicherweise haben Sie sie noch):

  1. Führen Sie den Webserver im Thread jedes Prozesses aus, überwachen Sie den temporären Port und verarbeiten Sie die Abfrage /metrics.
  2. Registrieren Sie den Webserver und aktualisieren Sie seine Adresse (z. B. Hostname: 32769) regelmäßig mit einem kurzen TTL-Pfad etcd. Ich verwende etcd bereits für die meisten Service Discovery-Anforderungen.
  3. Verwenden Sie in Prometheus dateibasierte Serviceerkennung, um diese Ziele zu identifizieren und als Einzelpersonen zu reiben.

Ich denke nicht, dass dieser Ansatz komplizierter ist als die Verwendung des Multiprozessmodus des Python-Clients, aber er hat seine eigene Komplexität.

Denken Sie daran, dass ein Ziel pro Arbeiter eine Zeitreihenexplosion verursacht. In diesem Fall generiert beispielsweise eine einzelne Standardhistogrammmetrik, die die Antwortzeiten von Python-Clients über acht Worker hinweg verfolgt, etwa 140 einzelne Zeitreihen, bevor sie mit anderen Labels multipliziert wird, um sie einzuschließen. Dies ist kein Problem, mit dem sich Prometheus befasst, aber beachten Sie, dass die Skalierung zunehmen (oder zunehmen) kann.

Zusammenfassung

Derzeit ist das Exportieren von Metriken aus dem Standard-Python-Web-App-Stack nach Prometheus in irgendeiner Weise etwas kompliziert. Wir hoffen, dass dieser Beitrag für alle nützlich ist, die mit der vorhandenen nginx + uwsgi + Flask-App beginnen möchten.

Wenn wir mehr Dienste unter Container-Orchestrierung ausführen (was wir versuchen), erwarten wir, dass es einfacher ist, die Prometheus-Überwachung in diese zu integrieren.

Ein etablierter Benutzer von Prometheus ist [Hosted Prometheus](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Pandora's%20Flask%3A%20Monitoring%20a%20Python% Wir empfehlen Ihnen, sich die Dienste von 20with% 20Prometheus anzusehen. Demo Bitte zögern Sie nicht, es uns zu sagen.

Recommended Posts

Überwachen Sie Python-Webanwendungen mit Prometheus
Überwachen Sie Python-Apps mit dem APM (Flask) von New Relic.
Web Scraping mit Python + JupyterLab
Web-API mit Python + Falcon
Webanwendung mit Python + Flask ② ③
Web Scraping Anfänger mit Python
Optimieren Sie die Websuche mit Python
Webanwendung mit Python + Flask ④
Erste Schritte mit Python-Webanwendungen
Web Scraping mit Python Erster Schritt
Ich habe versucht, WebScraping mit Python.
Überwachen Sie die Leistung von Python-Anwendungen mit Dynatrace ♪
Holen Sie sich Web-Screen-Capture mit Python
Überwachen Sie Mojo-Ausfälle mit Python und Skype
Erste Schritte mit Python Web Scraping Practice
Dämonisieren Sie eine Python-Webanwendung mit Supervisor
Entwickeln Sie Windows-Apps mit Python 3 + Tkinter (Vorbereitung)
[Persönlicher Hinweis] Scraping von Webseiten in Python3
Laden Sie mit Python Dateien im Web herunter
Pferderennseite Web Scraping mit Python
Überwachen Sie Webseitenaktualisierungen mit LINE BOT
[Python] Eine schnelle Webanwendung mit Bottle!
Erste Schritte mit Python Web Scraping Practice
Einfache Web-App mit Python + Flask + Heroku
Führen Sie eine Python-Webanwendung mit Docker aus
Erstellen Sie ein Webframework mit Python! (1)
Üben des Web-Scrapings mit Python und Selen
Einfaches Web-Scraping mit Python und Ruby
Erstellen Sie ein Webframework mit Python! (2)
[Für Anfänger] Versuchen Sie Web Scraping mit Python
FizzBuzz in Python3
Scraping mit Python
Statistik mit Python
Scraping mit Python
Python mit Go
Twilio mit Python
In Python integrieren
Spielen Sie mit 2016-Python
AES256 mit Python
Getestet mit Python
Python beginnt mit ()
mit Syntax (Python)
Bingo mit Python
Zundokokiyoshi mit Python
Excel mit Python
Mikrocomputer mit Python
Mit Python besetzen
Führen Sie das WEB-Scraping regelmäßig mit AWS-Lambda + Python + Cron aus
Python Web Content mit Lolipop billigen Server gemacht
Einführung in Tornado (1): Python Web Framework mit Tornado gestartet
Die Abfrage [Webentwicklung mit Python] wird ebenfalls umgeleitet
Starten Sie mit Docker einen einfachen Python-Webserver
Führen Sie Python-Webanwendungen mit NGINX + NGINX Unit + Flask aus
Entwickeln Sie Windows-Apps mit Python 3 + Tkinter (exe-Datei)
[Python] Mit Metie schnell Webseiten-Metadaten abrufen
[Verbesserte Version] Skript zur Überwachung der CPU mit Python
Starten Sie einen Webserver mit Python und Flask