Wie man weiter skaliert (2+ Mio. Beiträge, +80.000 pro Monat)

Ich würde gerne Ihre Erfahrungen nutzen, wie wir unsere Hardware weiter skalieren können.

Hier sind unsere Eckdaten:

2,2 Millionen Beiträge, aktuell wächst um ca. 80.000 pro Monat
35.000 Benutzer, wächst um ca. 1.500 pro Monat

Wir laufen derzeit auf einer Hetzner VM mit 8 exklusiven Kernen und 32 GB RAM. Wir begannen im Dezember, Einschränkungen bei den Nginx-Worker-Verbindungen zu bemerken, und erhöhten diese von den Standard-768 auf 1536. Gestern stießen wir wieder an diese Grenze und erhöhten sie nun auf 3072. Nach diesen Änderungen läuft alles wieder reibungslos, aber wir nähern uns einer Serverauslastungsgrenze von 100 %.

db_work_mem ist auf 80 MB eingestellt, db_shared_buffers auf 8192 MB. Wir nutzen unseren verfügbaren Arbeitsspeicher überhaupt nicht aus, aber ich bin mir nicht sicher, ob es Raum gibt, mehr zu nutzen und davon zu profitieren. Gedanken dazu?

#~> free -m

              total        used        free      shared  buff/cache   available
Mem:          31360        6105        1241        8423       24013       16412

Die nächste einfache Skalierungsoption bei Hetzner wären 16 Kerne und 64 GB RAM, was für uns kostentechnisch in Ordnung ist, aber ich frage mich, ob es noch sinnvoll wäre, vertikal zu skalieren. Ich habe überlegt, ob es nicht viel mehr Sinn machen würde, Anwendung und Datenbank auf verschiedene Server aufzuteilen, oder ob dies viel mehr Schwierigkeiten mit sich bringt.

Wer hat das schon gemacht? Was sind Ihre Erfahrungen?

Warum möchten Sie skalieren? Verschlechtern sich die Metriken Ihrer API-Antwortzeit?

Auf welche Ressource beziehen Sie sich hier? CPU? Speicherplatz? Arbeitsspeicher?

2 „Gefällt mir“

Wie viele Seitenaufrufe haben Sie?

Ignorieren Sie allen Rat, den Sie im Internet finden, und stellen Sie ihn auf 40-50 % Ihres Speichers ein.

Können Sie einige sar-Ausgaben teilen?

2 „Gefällt mir“

Weil ich vorausplane. Wir brauchen vielleicht gerade nicht zu skalieren, aber wenn ich mir das Wachstum ansehe, das wir sehen, und den wachsenden Ressourcenbedarf, den wir in der Vergangenheit gesehen haben, plane ich gerade voraus, um über mögliche nächste Schritte nachzudenken.

Hauptsächlich CPU – nach dem heutigen Update kommen wir von einer Auslastung von ~8-9 in Spitzenzeiten zurück auf etwa ~6.

12 Mio. pro Monat, gewachsen von 6,5 Mio. pro Monat vor einem Jahr.

Ich werde später auf die sar-Ausgabe zurückkommen, ich hatte sie nicht laufen.

Sie sollten untersuchen, was genau diese CPU verwendet. Es kann sein:

  • Unicorn-Webworker
  • PostgreSQL
  • Sidekiq, wie Hintergrundjobs zur Bildoptimierung
  • Redis
  • nginx (unwahrscheinlich)

Abhängig vom Schuldigen können wir Wege vorschlagen, dies zu entlasten.

5 „Gefällt mir“

Anhand der CPU-Zeit würde ich sagen, dass es sich hauptsächlich um Unicorn-Worker handelt:

1 „Gefällt mir“

Vielleicht sollten Sie die dedizierte CPU-Sache aufgeben und stattdessen dieses Angebot hier nutzen?

Das klingt nach etwas, das besser für Ihre Bedürfnisse geeignet ist.

2 „Gefällt mir“

Ich habe bereits über diese Option nachgedacht. Wir haben zuvor nicht dedizierte CPUs verwendet, und das „Upgrade“ auf dedizierte hat uns nicht viel weitergebracht.

1 „Gefällt mir“

Ich bin mir nicht sicher, ob die CPU Ihr Engpass ist. Haben Sie inzwischen sar-Ausgaben zum Teilen?

Ja, das tue ich, aber noch nicht zu den Stoßzeiten. Bis morgen werden diese verfügbar sein.

Die CPU-Auslastung ist definitiv gesunken, seit ich gestern die Worker-Verbindungen erhöht habe – ich weiß aber nicht genau, wie stark.

12:00:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle

08:45:01 AM     all     40.22      2.21      7.44      0.27      0.00     49.86
08:55:01 AM     all     42.84      2.89      8.02      0.16      0.00     46.09
09:05:01 AM     all     38.81      0.86      7.68      0.12      0.00     52.53
09:15:01 AM     all     38.80      0.70      7.66      0.10      0.00     52.73
09:25:01 AM     all     38.71      2.14      7.88      0.12      0.00     51.16
09:35:01 AM     all     38.74      0.84      7.86      0.09      0.00     52.47
09:45:01 AM     all     40.31      1.07      7.95      0.10      0.00     50.57
09:55:01 AM     all     40.03      1.37      7.90      0.08      0.00     50.62
10:05:01 AM     all     39.00      1.29      7.90      0.09      0.00     51.72
10:15:01 AM     all     40.26      2.68      8.07      0.09      0.00     48.91
10:25:01 AM     all     41.59      0.93      8.31      0.08      0.00     49.09
10:35:01 AM     all     40.39      1.55      8.25      0.07      0.00     49.73
10:45:01 AM     all     45.44      2.37      9.08      0.08      0.00     43.03
10:55:01 AM     all     50.56      2.20      9.23      0.06      0.00     37.95
11:05:01 AM     all     41.82      1.54      8.55      0.08      0.00     48.02
11:15:01 AM     all     38.74      1.54      8.11      0.10      0.00     51.50
11:25:01 AM     all     45.41      1.59      9.27      0.19      0.00     43.55
11:35:01 AM     all     38.45      1.78      8.20      0.11      0.00     51.45
11:45:01 AM     all     41.03      1.60      8.48      0.14      0.00     48.75
11:55:01 AM     all     40.65      1.17      8.36      0.15      0.00     49.67
12:05:01 PM     all     40.03      1.29      8.40      0.13      0.00     50.15
12:15:01 PM     all     40.47      1.10      8.19      0.11      0.00     50.13
1 „Gefällt mir“

Welche nützlichen sar-Statistiken sollte man berücksichtigen?

Ich vermutete, dass Postgres nicht genug Speicher bekam, was zu einem hohen %iowait führen würde.
Da die obige sar-Ausgabe jedoch kein überlastetes System anzeigt, müssen wir auf neue Statistiken warten.

Ich versuche, jemand anderem bei Leistungsproblemen zu helfen. Wir haben die Größe des PostgreSQL-Puffers erhöht. Ich glaube, es hat ein wenig geholfen, aber der Mini-Profiler zeigt immer noch über 300 ms an. Die CPU-Auslastung beträgt etwa 30 % für 16 CPUs.

1 „Gefällt mir“

Es sieht so aus, als würde sich das nicht ändern. Ich habe es jetzt über zwei Abende beobachtet und keine höhere CPU-Auslastung festgestellt. Ihre Annahme bezüglich Postgres könnte richtig sein.

Bezüglich des Mini-Profilers: Welche Zahlen wollen wir dort anstreben? Wir liegen derzeit bei etwa 300 ms. Zuvor waren es etwa 500 ms.

3 „Gefällt mir“

Ich denke, wenn wir unter 50 ms in allen Fällen erreichen, unabhängig von Spitzenverkehrszeiten, würde ich es als schnelle Serverantwortzeit bezeichnen. Der Rest der Website wird schneller sein, da alles von der anfänglichen Serverantwortzeit abhängt.

Und es wäre super ideal, wenn es für alle Geo-Benutzer unter 50 ms bleibt und konsistent ist. Derzeit springt es ständig und ist meistens höher, und das scheint das große Problem für die Langsamkeit zu sein.

Als kleine Rückschau auf die letzten Tage lief alles reibungslos, bis auf etwa eine halbe Stunde heute Nachmittag. Ich war zu dieser Zeit nicht selbst am Server, aber wir hatten Timeouts vom Backend im Nginx-Log gemeldet. sar zeigt eine etwas höhere Systemauslastung, aber keine allgemeine hohe CPU-Last. Ich bin mir nicht sicher, was das war, aber es schien Unicorn/Redis/Postgres daran zu hindern, reibungslos zu funktionieren.

03:55:01 PM     all     34.99      1.87      6.67      0.12      0.00     56.35
04:05:01 PM     all     33.99      0.35      6.52      0.31      0.00     58.82
04:15:01 PM     all     35.24      1.17      7.14      0.13      0.00     56.31
04:25:02 PM     all     36.45      0.63      7.15      0.13      0.00     55.65

> 04:35:01 PM     all     39.09      0.71     16.78      0.11      0.00     43.32
> 04:45:01 PM     all     35.53      0.95     20.16      0.08      0.00     43.27
> 04:55:01 PM     all     41.64      4.29     15.44      0.24      0.00     38.39
05:05:01 PM     all     36.75      2.47      7.78      0.13      0.00     52.87
05:15:01 PM     all     35.96      1.29      7.81      0.10      0.00     54.85
05:25:01 PM     all     38.69      1.35      8.00      0.09      0.00     51.87
05:35:01 PM     all     37.01      4.53      7.92      0.07      0.00     50.46

Es sind die mit “>” markierten Zeilen.

Ich kann zu dieser Zeit keinen hohen Traffic erkennen, daher bin ich mir nicht sicher, was es war, aber es passierte wirklich nur in dieser halben Stunde.

Insgesamt hat Redis die Führung übernommen und verbraucht generell einen guten Teil der CPU. Ich bin mir nicht sicher, ob man etwas dagegen tun kann. Normalerweise liegt er bei etwa 20-25%, mit Spitzen von 35% hier und da.

1721566 uuidd      20   0 2035M 1458M  1952 S 16.1  4.6 16h22:37 /usr/bin/redis-server *:6379
1721578 www-data   20   0  108M 69100 12516 S  6.7  0.2  6h32:27 nginx: worker process
2853756 1000       20   0 1355M  444M 19356 R 63.7  1.4  2h38:10 unicorn worker[0] -E production -c config/unicorn.conf.rb
2854380 1000       20   0 1267M  409M 18768 S 41.6  1.3  2h19:45 unicorn worker[4] -E production -c config/unicorn.conf.rb
1721598 1000       20   0  592M  285M  5192 S  1.3  0.9  2h08:53 unicorn master -E production -c config/unicorn.conf.rb
    575 root       20   0 1747M 20468  5040 S  0.7  0.1  2h01:02 /usr/bin/containerd
2854731 1000       20   0 1280M  399M 17880 S 36.9  1.3  1h57:52 unicorn worker[7] -E production -c config/unicorn.conf.rb
1721841 1000       20   0  592M  285M  5192 S  0.7  0.9  1h49:49 unicorn master -E production -c config/unicorn.conf.rb
2855284 1000       20   0 1287M  425M 18396 S 18.8  1.4  1h35:02 unicorn worker[3] -E production -c config/unicorn.conf.rb
2856414 1000       20   0 1223M  391M 19268 S 13.4  1.2  1h14:50 unicorn worker[2] -E production -c config/unicorn.conf.rb
2856478 1000       20   0 1207M  401M 21120 S  5.4  1.3 58:42.50 unicorn worker[5] -E production -c config/unicorn.conf.rb
2856503 1000       20   0 1215M  389M 18980 S  4.7  1.2 47:22.95 unicorn worker[1] -E production -c config/unicorn.conf.rb
1721581 www-data   20   0 69888 28636 13368 S  0.0  0.1 44:49.50 nginx: worker process
2857467 1000       20   0 1199M  385M 18112 S  4.0  1.2 39:23.87 unicorn worker[6] -E production -c config/unicorn.conf.rb
1721594 _apt       20   0 8479M 20036 18128 S  1.3  0.1 32:55.29 postgres: 13/main: walwriter
    580 root       20   0 1747M 20468  5040 S  0.0  0.1 32:15.27 /usr/bin/containerd

Die Last liegt insgesamt im Durchschnitt bei 5 auf lange Sicht, aber ich sehe immer noch, dass sie von Zeit zu Zeit auf 8 oder 9 ansteigt.

2 „Gefällt mir“

Bezüglich des Mini-Profilers. Ich sprach von der gesamten Ladezeit. Die Serverantwortzeit (erste Anfrage) liegt normalerweise unter 10 ms auf unserer Seite. Manchmal etwas darüber, aber ich habe bei meinen letzten Überprüfungen nichts über 20 ms gesehen. Die gesamte Ladezeit steigt manchmal bis zu 800 ms, sehr selten über 1000 ms.

Wir betrachten nur eine geografische Region, da wir keine signifikante Anzahl von Benutzern außerhalb dieser Region haben.

Ich empfehle, sich mit DISCOURSE_ENABLE_PERFORMANCE_HTTP_HEADERS zu befassen, was Ihnen auch Einblicke geben sollte, wo Sie die Leistung verbessern können.

4 „Gefällt mir“