Sehr langsame discobot-Zertifikatgenerierung auf unserem Server

Wir haben unsere neuen Mitglieder dazu gedrängt, das Discobot-Tutorial durchzuführen, und einige stoßen dabei auf ein Problem, das wir bereits in einer früheren (Staging-)Discourse-Instanz erlebt haben: Das Zertifikat im letzten Beitrag benötigt sehr lange, um generiert zu werden und tatsächlich angezeigt zu werden, ohne dass eine Lade- oder Generierungsanzeige vorhanden ist. Mit „sehr lange

Diese Route ist tatsächlich langsam, da sie neu ist.

Anstatt sie zu beschleunigen, könnten wir die Nachricht vielleicht so ändern, dass dem Benutzer mitgeteilt wird, dass Discobot etwas vorbereitet und dies eine Minute dauern wird?

Mir war nicht bewusst, dass es als langsam bekannt ist – wenn nichts anderes, könnte zumindest ein Update im Beitrag, das dies klarstellt, helfen. Dennoch erwarte ich, dass einige Leute aufgeben, wenn die Wartezeit zu lang ist.

Ich muss sagen, dass 10 bis 20 Sekunden zum Generieren ungewöhnlich lang erscheinen, um ein bereits existierendes SVG (vermutlich?) mit etwas Text auszufüllen? Soweit ich das überblicke, scheint dies nicht CPU-bedingt zu sein. Was ist hier der Flaschenhals?

Ich habe überlegt, den Text hier so anzupassen, dass ein Satz wie „Bitte warten, ich generiere etwas Cooles für dich!

Ich glaube, er spricht über die Generierung des Zertifikatsbildes, nicht über den Beitrag.

Ich spreche tatsächlich von der Generierung des Zertifikats — nicht von der Antwortpost, die es einbettet (die ist schnell). Das ist das Problem, das einige unserer Mitglieder betrifft:

Nein, eine t3a.medium ist eine Instanz mittlerer Leistungsklasse, und die Auslastung ist nicht hoch.

Wie gesagt, scheint dies nicht CPU-bedingt zu sein, denn während ich auf eine Anfrage wie /discobot/certificate.svg?date=Oct+28+2020&user_id=123 warte, ist die CPU nicht stärker ausgelastet als zu anderen Zeiten (was ohnehin nicht sehr belastet ist).

Das Problem scheint mit einem Netzwerk-Request zusammenzuhängen, der ein Timeout verursacht:

Das Avatar-Bild auf dem Zertifikat scheint ein data:image/png;base64-Blob zu sein. Soweit ich sehe, wird versucht, ein Avatar herunterzuladen, das ein Timeout verursacht? Vielleicht ist das der Grund für die Verlangsamung?

Zum Kontext: Dies findet in einem Forum mit SSO statt, und Avatare sind HTTPS-URLs, die auf S3 gespeichert sind. Ich habe versucht, einige dieser Avatare innerhalb des Docker-Containers abzurufen, und das funktioniert nahezu sofort — keine Firewall-Probleme usw. Alles andere im Forum läuft schnell, außer bei der Generierung des Zertifikats, was sehr lange dauert.

Gerne würde ich weiter nach dem Fehler suchen, wenn ich Hinweise darauf bekomme, was ich überprüfen soll.

Das Bild erschien bei mir auf try.discourse.org mehr oder weniger sofort. Mir fiel keine spürbare Verzögerung von mehr als vielleicht einer halben Sekunde auf, falls überhaupt? Probier es selbst aus, wenn du mir nicht glaubst!

Also komme ich zurück zu dem, was ich ursprünglich gesagt habe: Warum ist das auf deinem Server so langsam, aber auf try.discourse.org so schnell?

Warum wohl… Genau darum bitte ich um Unterstützung.

Ich verstehe, dass dies ein “es funktioniert auf meinem Rechner”-Szenario ist, das mit Docker eigentlich gar nicht auftreten sollte, aber nun ja, hier sind wir und es scheint, als wäre ich nicht der einzige.

Jegliche Hinweise, wie ich das Problem auf meiner Seite debuggen kann, wären sehr willkommen.

Ich habe mir das etwas genauer angesehen, und das Problem scheint darin zu bestehen, dass der discourse-narrative-bot blockiert, wenn er das Avatar des Benutzers lädt, um es auf dem Zertifikat einzufügen. Hier:

Dieses Forum nutzt SSO, und die Avatare sind Amazon-S3-URLs – diese sind schnell und werden von Amazon nicht gedrosselt. Dennoch ruft diese Funktion eine Avatar-URL im folgenden Format ab:

https://forum.tld/user_avatar/forum.tld/username/240/18705_2.png

Könnten die Timeout-Fehler, die die Zertifikatsgenerierung verlangsamen, darauf zurückzuführen sein, dass irgendwie die Ratenbegrenzung von Discourse ausgelöst wird? Entweder dadurch, dass die Avatare zu schnell von der Discourse-Instanz selbst angefordert werden, oder weil versucht wird, bei Amazon S3 zu schnell zuzugreifen, wenn mehrere Benutzer gleichzeitig das Bot-Tutorial durchlaufen?

Interessant. Wir haben dort ein Base64-Bild inline eingebettet. Ich frage mich, warum wir nicht einfach auf die externe Ressource im image-SVG-Tag verweisen :thinking:

Ich habe die Historie des Plugins bis zu dem Punkt durchsucht, an dem wir dies erstmals hinzugefügt haben:

Und es sieht so aus, als hätten wir Avatare immer als inline eingebettete Base64-Bilder verwendet.

EDIT: Nach einiger Recherche: Wir verwenden Base64, weil das Zertifikat über ein img-HTML-Tag geladen wird. Um günstigere Avatare zu erhalten, müssten wir auf ein object-Tag umsteigen, das in unserer CSP standardmäßig blockiert ist. Oder wir betten das gesamte SVG direkt in den Beitrag ein. Ich schätze, ein iframe ist unsere beste Option.

Ich habe FIX: Make discobot certificate gen faster/non blocking by xfalcox · Pull Request #11344 · discourse/discourse · GitHub für Kommentare von @tgxworld erstellt.

Ich habe angenommen, dass das SVG, das das in Base64 kodierte Avatar-Bild enthält, aus demselben Grund verwendet wurde, aus dem das Logo so gehandelt hat: damit das Zertifikat ein Momentaufnahme sein kann – vielleicht vom Preisträger gespeichert, ohne externe Abhängigkeiten, sodass es später immer noch exakt gleich dargestellt wird.

Der Iframe-Ansatz verhindert, dass es leicht in einem Beitrag geteilt und damit geprahlt werden kann. Ich weiß nicht, wie verbreitet dies auf anderen Foren ist, aber ich habe gesehen, wie einige unserer Benutzer dies tun, indem sie einfach die URL des Bildes kopieren.

Wenn man sich für eine Verlinkung zu etwas Externem entscheidet, würde es hier nicht funktionieren, <image> zu verwenden und so die Notwendigkeit zu vermeiden, allowed_iframes zu ändern?

Genau das macht der oben genannte PR, wenn man ihn liest :grimacing:

Aber wenn du das SVG wie heute mit dem HTML-img-Tag lädst, werden externe Bilder, die in den SVG-image-Tags enthalten sind, nicht geladen. Dafür muss es entweder mit object oder iframe geladen werden.

Offensichtlich weiß ich nicht genug über SVG. Der Iframe-Ansatz verhindert, dass das Zertifikat zitiert/kopiert wird, aber dennoch freue ich mich, dass dies irgendwie angegangen wird, da dies unser Problem löst und auch das fehlende Logo auf dem Zertifikat behebt. :+1:

@mentalstring Ich habe den neuen Code zur Zertifikatsgenerierung gerade zusammengeführt. Es sollte jetzt viel schneller sein.

Toll, dass das hier gemergt wird. :+1:

Wir nutzen stable und habe aktuell keine gute Möglichkeit, das zu testen. Wenn fetch_avatar jedoch nicht mehr verwendet wird, erwarte ich, dass unsere Net::ReadTimeout-Fehler damit verschwinden. Ich markiere das hier als gelöst und öffne den Fall erneut, falls ich beim Update doch wieder auf dasselbe Problem stoße. Danke!