Comment passer à l'échelle supérieure (2+ millions de publications, +80k par mois)

J’aimerais profiter de votre expérience sur la manière de continuer à faire évoluer notre matériel.

Voici nos données fondamentales :

2,2 millions de publications, dont environ 80 000 par mois
35 000 utilisateurs, dont environ 1 500 par mois

Nous fonctionnons actuellement sur une VM Hetzner avec 8 cœurs exclusifs et 32 Go de RAM. Nous avons commencé à rencontrer des limitations en décembre avec les connexions worker Nginx d’abord, et nous les avons augmentées de 768 par défaut à 1536. Nous avons atteint cette limite hier et les avons augmentées à 3072 maintenant. Après ces changements, les choses fonctionnent à nouveau sans problème, mais nous approchons d’une limite d’utilisation du serveur de 100 %.

db_work_mem est réglé sur 80 Mo, db_shared_buffers sur 8192 Mo. Nous n’utilisons pas du tout la mémoire disponible, mais je ne suis pas sûr s’il y a de la place pour en utiliser davantage et en bénéficier. Des idées ?

#~\u003e free -m

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

La prochaine option d’évolution facile avec Hetzner serait de 16 cœurs et 64 Go de RAM, ce qui est acceptable pour nous en termes de coûts, mais je me demande s’il serait toujours judicieux de faire évoluer verticalement. Je me demandais si la séparation de l’application et de la base de données sur des serveurs différents n’aurait pas plus de sens ou si cela n’introduirait pas beaucoup plus de difficultés.

Qui a déjà fait cela ? Quelles sont vos expériences ?

Pourquoi cherchez-vous à augmenter la capacité ? Vos métriques de temps de réponse de l’API se dégradent-elles ?

À quelle ressource faites-vous référence ici ? CPU ? Espace disque ? Mémoire ?

2 « J'aime »

Combien de vues de page avez-vous ?

Ignorez tous les conseils que vous trouvez sur Internet et réglez-le à 40-50 % de votre mémoire.

Pouvez-vous partager une sortie sar ?

2 « J'aime »

Parce que je planifie à l’avance. Nous n’avons peut-être pas besoin d’augmenter la capacité tout de suite, mais compte tenu de la croissance que nous constatons et du besoin croissant de ressources que nous avons observé par le passé, je planifie simplement à l’avance pour réfléchir aux prochaines étapes possibles.

Principalement le CPU - après la mise à jour d’aujourd’hui, nous revenons d’une charge d’environ 8-9 pendant les heures de pointe à ce qui semble être environ 6 maintenant.

12 millions par mois, contre 6,5 millions par mois il y a un an.

Je reviendrai plus tard sur la sortie de sar, je ne l’avais pas en cours d’exécution.

Vous devrez enquêter sur ce qui utilise exactement ce CPU. Il peut s’agir de :

  • Travailleurs web Unicorn
  • PostgreSQL
  • Sidekiq, comme les tâches d’arrière-plan d’optimisation d’images
  • Redis
  • nginx (peu probable)

Selon le coupable, nous pourrons suggérer des moyens de le décharger.

5 « J'aime »

En regardant le temps CPU, je dirais que ce sont principalement des workers unicorn :

1 « J'aime »

Peut-être abandonner l’idée du CPU dédié et utiliser cette offre ici ?

Cela semble plus approprié à vos besoins.

2 « J'aime »

J’avais déjà pensé à cette option. Nous avons utilisé les processeurs non dédiés plus tôt et la « mise à niveau » vers des processeurs dédiés ne nous a pas beaucoup fait progresser.

1 « J'aime »

Je ne suis pas sûr que le CPU soit votre goulot d’étranglement. Avez-vous une sortie sar à partager en attendant ?

Oui, mais pas encore aux heures de pointe. Je les aurai d’ici demain.

L’utilisation du processeur est définitivement réduite depuis que j’ai augmenté les connexions de travail hier - je ne sais pas encore de combien.

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 « J'aime »

Quelles statistiques sar seraient utiles à considérer ?

Je suspectais que Postgres ne recevait pas assez de mémoire, ce qui entraînerait un %iowait élevé.
Mais comme la sortie sar ci-dessus n’indique pas un système surchargé, nous devrons attendre de nouvelles statistiques.

J’essaie d’aider quelqu’un d’autre avec des problèmes de performance. Nous avons augmenté la taille du tampon postgres. Je pense que cela a un peu aidé, mais le mini profiler montre toujours plus de 300 ms. L’utilisation du processeur est d’environ 30 % pour 16 processeurs.

1 « J'aime »

Il semble que cela ne changera pas. Je l’ai observé pendant deux soirées et je n’ai pas obtenu d’utilisation CPU plus élevée. Votre hypothèse concernant Postgres pourrait être correcte.

Concernant le mini profiler : quels sont les chiffres que nous visons ? Nous sommes actuellement autour de 300 ms. Nous étions à environ 500 ms auparavant.

3 « J'aime »

Je pense que si nous atteignons moins de 50 ms dans tous les cas, indépendamment des heures de pointe, j’appellerais cela un temps de réponse serveur rapide. Le reste du site sera plus rapide car tout dépend du temps de réponse initial du serveur.

Et ce serait super idéal si cela restait en dessous de 50 ms pour tous les utilisateurs géographiques et restait constant. Pour le moment, cela continue de sauter et c’est surtout plus élevé, et cela semble être le gros problème de la lenteur.

Pour faire un petit retour sur les derniers jours, les choses se sont déroulées sans problème, à l’exception d’une demi-heure cet après-midi. Je n’étais pas sur le serveur moi-même à ce moment-là, mais nous avons eu des Timeouts du Backend signalés dans le log nginx. sar montre une utilisation système légèrement plus élevée mais pas de charge CPU générale élevée. Je ne suis pas sûr de ce que c’était, mais cela a apparemment empêché unicorn/redis/postgres de fonctionner correctement.

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

Ce sont les lignes marquées par >.

Je ne vois pas de trafic élevé à ce moment-là, donc je suis un peu perplexe quant à ce que c’était, mais cela ne s’est vraiment produit que pendant cette demi-heure.

Globalement, en regardant le temps CPU, Redis a pris la tête et utilise généralement une bonne partie du CPU. Je ne suis pas sûr s’il y a quelque chose à faire à ce sujet. Il est généralement autour de 20-25%, atteignant 35% ici et là.

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

La charge globale est en moyenne de 5 à long terme, mais je la vois toujours monter à 8 ou 9 de temps en temps.

2 « J'aime »

Concernant le mini profiler. Je parlais du temps de chargement global. Le temps de réponse du serveur (requête initiale) est généralement inférieur à 10 ms de notre côté. Parfois un peu plus, mais je n’ai pas vu de >20 ms lors de mes dernières vérifications. Le temps de chargement global monte parfois jusqu’à 800 ms, très rarement au-dessus de 1000 ms.

Nous n’examinons qu’une seule région géographique car nous n’avons pas un nombre significatif d’utilisateurs en dehors de cette région.

Je recommande de jeter un œil à DISCOURSE_ENABLE_PERFORMANCE_HTTP_HEADERS qui devrait également vous donner un aperçu des points où vous pouvez améliorer les performances.

4 « J'aime »