Limiter le nombre de licornes, l'utilisation de la mémoire et le swapping

Je fais tourner un petit serveur (1 Go de RAM) ainsi qu’un petit site (installation officielle de Discourse depuis près de 8 ans). Il y a plus d’échange disque que je ne le souhaiterais, j’ai donc commencé à examiner l’utilisation de la mémoire.

J’ai remarqué que j’avais défini le nombre de licornes à seulement 2 il y a quelque temps pour limiter l’utilisation de la mémoire (et réduire l’échange). Je fais tourner la version de Discourse 3.1.0.

Cependant, lorsque j’exécute htop, je vois 20 licornes en cours d’exécution (10 pour le worker 0 et 10 pour le worker 1).

Qu’est-ce qui m’échappe ? Pourquoi ai-je 20 licornes en cours d’exécution alors que app.yml indique 2 ?

Existe-t-il d’autres moyens de réduire l’utilisation de la mémoire (par exemple, si je réduis db_shared_buffers à 128 Mo, y aura-t-il des effets secondaires ?) Puis-je réduire l’utilisation de la mémoire de Sidekiq ?

Voici vmstat 5 5 :
image

free -h :
image

1 « J'aime »

Je soupçonne que htop affiche les threads plutôt que les processus - quoi qu’il en soit, je vois la même chose sur htop que vous, mais seulement deux unicorns selon

ps uaxf|egrep unicorn.?worker

De plus, mon free est comme le vôtre :

# free -h
              total        used        free      shared  buff/cache   available
Mem:           985M        782M         61M         60M        141M         32M
Swap:          2.0G        992M        1.0G

Soit dit en passant, voir un peu de swap utilisé n’est pas un problème en soi. C’est le swapping (paging) réel qui importe. Essayez vmstat 5 5 et regardez les colonnes si et so.

# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 1041832  63176   5716 127408  367  325   601   393    8   10  2  1 95  2  0
 0  0 1041576  60976   5724 127408  399    0   399    21  212  653  1  1 96  2  0
 0  0 1043544  77036   2296 120688  807  803   807   837  404 1144  1  2 94  3  0
 0  0 1043288  65040   3704 129476  254    0  2292     5  255  780  1  1 96  2  0
 0  0 1048736  81936   2916 119016  762 1499   919  1565  470 1171  3  2 90  5  0

Je préférerais ne rien voir au-dessus de 1000 mais je ne suis pas trop inquiet. Une seconde exécution a montré une image beaucoup plus calme :

# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 1048452  82712   2532 120848  367  325   601   393    8   10  2  1 95  2  0
 0  0 1047684  74552   2548 124816  285    0  1049    10  230  655  2  1 95  2  0
 0  0 1046660  66556   3692 129008  196    0  1261    16  219  672  1  1 96  2  0
 1  0 1046404  65812   3700 129284   54    0    97    13  137  364  1  0 98  0  0
 0  0 1046148  65280   3700 129288   50    0    50     3  132  344  1  0 98  0  0

Edit : la touche H dans htop permet de passer des threads aux processus :

  CPU[                                                       0.0%]   Tasks: 66; 1 running
  Mem[||||||||||||||||||||||||||||||||||||||||||||||||||824M/985M]   Load average: 0.19 0.12 0.05
  Swp[||||||||||||||||||||||||||||||                  1015M/2.00G]   Uptime: 52 days, 00:50:42

  PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
13246 1000       20   0  966M  362M  6448 S  0.0 36.8 51:01.52 unicorn worker[0] -E production -c config/unicorn.conf.rb
13237 1000       25   5 1004M  194M  3780 S  0.0 19.8 22:38.19 sidekiq 6.5.9 discourse [0 of 5 busy]
13258 1000       20   0  919M 70176  3632 S  0.0  7.0  5:02.87 unicorn worker[1] -E production -c config/unicorn.conf.rb
12412 systemd-r  20   0  212M 60928 56916 S  0.0  6.0  0:00.23 postgres: 13/main: discourse discourse [local] idle
12818 systemd-r  20   0  212M 39228 34868 S  0.0  3.9  0:00.07 postgres: 13/main: discourse discourse [local] idle
12719 systemd-r  20   0  211M 28400 25336 S  0.0  2.8  0:00.03 postgres: 13/main: discourse discourse [local] idle
13117 1000       20   0  541M 13768  2048 S  0.0  1.4  1:08.11 unicorn master -E production -c config/unicorn.conf.rb

Edit : j’ai défini db_shared_buffers: "128MB" très tôt, et je n’ai pas vu de problème avec cela.

1 « J'aime »

Merci, très utile. Quels sont les inconvénients du passage à un seul worker unicorn ? Cela améliorerait-il le temps de réponse ou l’aggraverait-il (un seul worker unicorn est-il limité à une seule connexion entrante, c’est-à-dire que 2 workers rendraient une seule connexion entrante plus rapide à traiter ?), en supposant que je n’aie que quelques connexions par minute ?

Lorsque je navigue sur le site Web, voici à quoi ressemble vmstat 5 5, des suggestions sur la façon de réduire le swapping (j’ai réglé la swappiness sur 10) ?

EDIT : Y a-t-il un moyen de réduire l’utilisation de la mémoire de sidekiq sans impacter les performances ?

Il semble certainement que votre site serait plus rapide si vous aviez plus de RAM. Mais si le temps de réponse n’est pas un problème, il n’y a pas de problème. Regardez simplement votre équation personnelle coût/bénéfice.

Vous pourriez être intéressé par la lecture de MKJ’s Opinionated Discourse Deployment Configuration. Il y a quelques ajustements du noyau au niveau du système qui sont une bonne idée. Je ne sais pas s’ils feront une différence ou non.

Je ne sais pas, mais je pense que chaque licorne peut gérer une requête. Donc, si vous n’avez qu’une seule licorne et suffisamment de trafic pour qu’une deuxième requête arrive avant que la première ne soit terminée, cette deuxième requête devra attendre. Vous pouvez voir d’après ma sortie htop qu’une licorne a consommé 10 fois plus de temps CPU que l’autre. Je prendrais cela comme indication que mon forum a besoin d’une seule licorne 90% du temps, et que la deuxième licorne est utile 10% du temps. Je ne ressens pas le besoin d’en ajouter une troisième, et cela pourrait ne pas être très important pour les membres de mon forum si je n’en avais qu’une. Mais je ne vois aucune raison de le faire : cela peut utiliser de la mémoire, mais si elle est inactive, elle sera échangée. Pas de gros problème : laissez le système de mémoire virtuelle s’en occuper.

Edit : Je n’ai jamais ajusté la swappiness. Elle semble être à 60. Un échange plus agressif pourrait être utile s’il libère plus de RAM pour les tampons d’E/S. Je ne sais pas.

2 « J'aime »

Si je change db_shared_buffers et UNICORN_WORKERS, y a-t-il un moyen de simplement redémarrer sans reconstruire via ./launcher rebuild app ?