SSE Problem schnelles refreshen von Browser

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Ich nutze Server Sent Events in Kombination mit POSTGRES SQL um die GUI aller Clients gleichzeitig upzudaten. Das funktioniert soweit auch.

Durch Zufall habe ich entdeckt, dass wenn man im Browser die Seite mehrfach - im Dauerfeuer sozusagen aktualisiert, hängt sich der Server auf.

Kann mir wer spontan sagen, womit das zusammenhängen kann? Ich meine ich habe von diversen Browser Restriktionen gelesen was die Anzahl der Verbindungen anbelangt. Aber warum dann der Server abschmiert, ist mir schleierhaft.

Bei Bedarf kann ich gerne den Code posten. Aber im groben ist es so:
Clientside: Eventsource die an einer speziellen Flaskroute lauscht
Servers: Die Methode die etwas an die Clients sendet, sobald ein Ereignis in der Db getriggert wird.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich würde erstmal eine so minimale Variante wie möglich bauen, ohne weiteren anwendungscode. Quasi hello world auf SSEisch. Und dann wieder probieren, ob’s geht. Wenn nicht, ist es ein flask Problem. Wenn doch, dann eines von dir.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei wenn's nicht geht eventuell auch noch der Server das Problem sein könnte. Da wurde ja nix drüber gesagt was da genau verwendet wird.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Ich möchte noch erwähnen, dass ich Gunicorn nutze.

Als ich die Anzahl der Worker und Threads erhöht habe, hängt sich zumindest nicht mehr alles auf. Dennoch erkenne ich an der GUI, dass es dennoch nicht 100% rund läuft.

Es geht auf jeden Fall in die richtige Richtung.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du kannst bei gunicorn mit sync worker nur workers * threads viele Requests gleichzeitig verarbeiten. Was wahrscheinlich passiert, ist dass du dieses Limit erreichst und dann kann gunicorn keine weiteren Requests entgegen nehmen.

Deine Beobachtung dass dies passiert wenn du die Webseite mehrfach neulädst, wird wahrscheinlich daran liegen dass es unter Umständen einen Moment dauert bis die SSE Verbindung geschlossen wird.

Du solltest außerdem bedenken dass eine Verbindung zu Postgres ziemlich teuer ist und wesentlich mehr Verbindungen zu Postgres zu haben als der Server CPU Cores hat, sich negativ auf die Performance auswirkt. Sollten diese Verbindungen sogar Transaktionen über einen längeren Zeitraum offen halten, besteht auch das Risiko dass VACUUM keinen nennenswerten Fortschritt erzielen kann.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Was bedeutet denn "der Server hängt sich auf"?
Ist er nur langsam? Gibt es Verbindungsprobleme? Ist das Dauerhaft? Gibt es Fehlermeldung? Wenn ja, welche?
Sternenregen
User
Beiträge: 39
Registriert: Mittwoch 13. Januar 2021, 16:17

Sirius3 hat geschrieben: Donnerstag 3. Juni 2021, 16:36 Was bedeutet denn "der Server hängt sich auf"?
Ist er nur langsam? Gibt es Verbindungsprobleme? Ist das Dauerhaft? Gibt es Fehlermeldung? Wenn ja, welche?
Es gibt keine Fehlermeldung, nichts. Er freezed so gesehen. Tritt dieser Zustand ein, kann ich die Seite auch von einem anderen Browser nicht mehr laden.

DasIch hat geschrieben: Donnerstag 3. Juni 2021, 14:27 Du kannst bei gunicorn mit sync worker nur workers * threads viele Requests gleichzeitig verarbeiten. Was wahrscheinlich passiert, ist dass du dieses Limit erreichst und dann kann gunicorn keine weiteren Requests entgegen nehmen.

Deine Beobachtung dass dies passiert wenn du die Webseite mehrfach neulädst, wird wahrscheinlich daran liegen dass es unter Umständen einen Moment dauert bis die SSE Verbindung geschlossen wird.

Du solltest außerdem bedenken dass eine Verbindung zu Postgres ziemlich teuer ist und wesentlich mehr Verbindungen zu Postgres zu haben als der Server CPU Cores hat, sich negativ auf die Performance auswirkt. Sollten diese Verbindungen sogar Transaktionen über einen längeren Zeitraum offen halten, besteht auch das Risiko dass VACUUM keinen nennenswerten Fortschritt erzielen kann.
Ja, das deckt sich mit meinen Beobachtungen. Als ich die Anzahl der Threads erhöht hatte, freezed der Browser zumindest nicht mehr. Aktuell habe ich 16 Threads eingestellt. Trotzdem scheint sich der Server, nach einer "Anfrageflut" danach nicht mehr zu erholen bzw die SSE funktionieren nicht mehr richtig.

Könnte ich denn da was einbauen, was dem entgegenwirkt? Außer die Anzahl der Threads zu erhöhen?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Ich würde erwarten dass der Server (also gunicorn) die Verbindung von sich aus schliesst, wenn klar wird dass die Gegenseite nicht mehr existiert. Es könnte allerdings sein dass es eine Weile dauert bis so ein timeout erreicht ist. Ich würde aber erwarten dass sowas innerhalb von 1min passiert.

Wenn dass nicht so ist, könnte es daran liegen dass man da was an der Konfiguration ändern muss. Es könnte auch sein dass dies mit einer der Gründe ist aus denen empfohlen wird gunicorn hinter einem reverse-proxy with nginx laufen zu lassen und die Annahme ist dass sich z.b. nginx darum schon kümmert.
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

Sternenregen hat geschrieben: Donnerstag 3. Juni 2021, 12:19 Ich nutze Server Sent Events in Kombination mit POSTGRES SQL um die GUI aller Clients gleichzeitig upzudaten. Das funktioniert soweit auch.

Durch Zufall habe ich entdeckt, dass wenn man im Browser die Seite mehrfach - im Dauerfeuer sozusagen aktualisiert, hängt sich der Server auf.

Kann mir wer spontan sagen, womit das zusammenhängen kann? Ich meine ich habe von diversen Browser Restriktionen gelesen was die Anzahl der Verbindungen anbelangt. Aber warum dann der Server abschmiert, ist mir schleierhaft.
Vorweg: ich kenne mich mit SSE nicht aus. Aber so ganz grundsätzlich haben Betriebssysteme gewisse Grenzen, die von vielen Faktoren abhängen: der Hardware, der Konfiguration des Systems und der Anwendungssoftware, der Rechenlast, der Arbeitsspeicherauslastung, und -- was manche Kollegen leider gerne vergessen -- etwas, das sich etwas verallgemeinert Input-Output oder I/O nennt. So einen I/O gibt es bei vielen Ressourcen: beim Arbeitsspeicher, zum Beispiel, oder beim Persistenzmedium (Festplatte / SSD / NVMe...). Im Kern könnte man sogar die Verarbeitungspipeline der CPU als eine Art von I/O betrachten: wenn Du mehr hinein steckst, als herauskommen kann, ist die Veranstaltung quasi... "verstopft". Da hilft dann oft -- gerade unter Python -- eine Parallelisierung. Blöderweise haben einige Python-Interpreter das Global Interpreter Lock (GIL), das sich vor allem beim Multithreading gerne sehr unschön bemerkbar macht. Dann -- um nochmal aufs System zurück zu kommen -- gibt es da noch diese Scheduler. Die entscheiden, wann Dein Prozeß oder Thread einen Zeitabschnitt (time slice) auf den Ressourcen Deines Rechners bekommt. Und da kommt dann (auch) diese Sache mit dem Multithreading ins Bild...(und dann noch viel mehr, aber das vergessen wir erstmal.)

So ein Thread ist in der Regel billiger als ein Prozeß, weil die Threads eines Prozesses sich (meistens) denselben Speicherraum teilen. Das verführt manche Entwickler leider dazu, für jeden Mist neue Threads zu starten, vor allem bei den Java-Kollegen war das nicht selten, hin und wieder habe ich mehr als 100k Threads gesehen -- keine Frage, auf fetten Maschinen, aber... Und da kommt wieder dieses Betriebssystem ins Spiel: mit Ausnahme des Speicherraums sind Threads einem Prozeß sehr ähnlich, und der Prozeßscheduler des Betriebssystems muß halt die Prozessorzeit verwalten, und je mehr Prozesse und Threads so ein Kernel verwalten und abwägen muß, desto langsamer wird die Veranstaltung. Ähnliches gilt für etliche andere Systemressourcen: wenn Du sie überlastest, sind sie saturiert. Vor einigen Jahren habe ich mal meinen Chef überzeugt, Redis anstelle von Apache Cassandra zu nutzen, aber bei meinen Tests war Redis erst gar nicht performanter?! Howcome? Genau: bei etwas über 930 Transaktionen pro Sekunde mit je 128 Kilobyte war das Gigabit Ethernet saturiert. Hm.

Und dann ist da noch so ein Ding: PostgreSQL. PostgreSQL kann ein ziemlich dickes Monster sein, wenn man es ausreizt, aber... das ist halt nicht der Regelfall. Üblicherweise wird PostgreSQL mit einer sehr konservativen Standardkonfiguration ausgeliefert, und häufig drehen die DBAs oder DevOps nicht daran... aber mit 2 GB work_mem auf einer Büchse mit 64 GB RAM kommst Du nicht weit, um nur ein Beispiel zu nennen. Meinen gerne und ausführlichen Rant über Entwickler, Administratoren und Architekten, die außer klassischen SQL-Datenbanken nichts kennen, erspare ich uns mal. Wie dem auch sei: an Deiner Stelle würde erstmal aufs System gucken. Unter verschiedenen UNIXioden gibt es da den "System Activity Reporter" (SAR), der -- richtig konfiguriert -- in periodischen Abständen die Performancecounter des Systemkernels liest und speichert, kann man schon ziemlich genau sehen, was das System macht... Unter UNIXioden gibt es oft auch so Pakete wie "pacct" oder "acct", mit denen Du noch genauer verfolgen kannst, was Dein System macht.

HTH, YMMV -- LukeM ;-)
Antworten