Cómo escalar más (2+ millones de publicaciones, +80k por mes)

Me gustaría aprovechar su experiencia sobre cómo continuar escalando nuestro hardware.

Aquí están nuestros datos fundamentales:

2.2 millones de publicaciones, creciendo actualmente ~80k por mes
35k usuarios, creciendo ~1.5k por mes

Actualmente estamos funcionando en una VM de Hetzner con 8 núcleos exclusivos y 32G de RAM. Comenzamos a ver limitaciones en diciembre con las conexiones de trabajadores de Nginx primero y las aumentamos de 768 por defecto a 1536. Ayer volvimos a alcanzar ese límite y las aumentamos a 3072. Después de estos cambios, las cosas funcionan sin problemas nuevamente, pero nos acercamos a un límite de utilización del servidor del 100%.

db_work_mem está configurado en 80 MB, db_shared_buffers en 8192 MB. No estamos utilizando en absoluto la memoria disponible, pero no estoy seguro de si hay margen para usar más y beneficiarnos de ello. ¿Opiniones?

#~\u003e free -m

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

La próxima opción de escalado fácil con Hetzner serían 16 núcleos y 64 GB de RAM, lo cual está bien para nosotros en términos de costos, pero me pregunto si todavía tendría sentido escalar verticalmente. Estaba pensando si separar la aplicación y la base de datos en servidores diferentes no tendría mucho más sentido o si introduce muchas más dificultades.

¿Quién ha hecho eso? ¿Cuáles son sus experiencias?

¿Por qué buscas escalar? ¿Se están degradando las métricas de tiempo de respuesta de tu API?

¿A qué recurso te refieres aquí? ¿CPU? ¿Espacio en disco? ¿Memoria?

2 Me gusta

¿Cuántas visitas a la página estás teniendo?

Ignora todos los consejos que encuentres en internet y configúralo al 40-50% de tu memoria.

¿Puedes compartir alguna salida de sar?

2 Me gusta

Porque estoy planificando con anticipación. Puede que no necesitemos escalar ahora mismo, pero viendo el crecimiento que vemos y la creciente necesidad de recursos que vimos en el pasado, estoy planificando con anticipación para pensar en los posibles próximos pasos.

Principalmente CPU: después de la actualización de hoy, volvemos de una carga de ~8-9 en horas pico a lo que parece ~6ish ahora.

12M por mes, creció desde 6.5M por mes hace un año.

Volveré a la salida de sar más tarde, no la estaba ejecutando.

Querrás investigar qué está usando exactamente esa CPU. Puede ser:

  • Trabajadores web de Unicorn
  • PostgreSQL
  • Sidekiq, como trabajos en segundo plano de optimización de imágenes
  • Redis
  • nginx (poco probable)

Dependiendo del culpable, podemos sugerir formas de descargarlo.

5 Me gusta

Mirando el tiempo de CPU, diría que son principalmente trabajadores de unicornio:

1 me gusta

¿Quizás deberías descartar lo de la CPU dedicada y usar esta oferta de aquí?

Suena como algo más apropiado para tus necesidades.

2 Me gusta

Ya estaba pensando en esa opción. Utilizamos las CPU no dedicadas anteriormente y la “actualización” a las dedicadas no nos avanzó mucho.

1 me gusta

No estoy seguro de si la CPU es tu cuello de botella. ¿Tienes alguna salida de sar para compartir mientras tanto?

Sí, pero todavía no son horas pico. Tendré eso para mañana.

El uso de la CPU definitivamente se redujo desde que aumenté las conexiones de trabajadores ayer, aunque no estoy seguro de cuánto.

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 me gusta

¿Qué estadísticas útiles de sar se deberían considerar?

Sospeché que Postgres no estaba recibiendo suficiente memoria, lo que resultaría en un %iowait alto.
Pero dado que la salida de sar anterior no indica un sistema sobrecargado, tendremos que esperar nuevas estadísticas.

Estoy intentando ayudar a otra persona con problemas de rendimiento. Aumentamos el tamaño del búfer de postgres. Creo que ayudó un poco, pero el mini profiler todavía muestra más de 300 ms. El uso de la CPU es de aproximadamente el 30% para 16 cpus.

1 me gusta

Parece que eso no va a cambiar. Lo he observado durante dos noches y no he obtenido un mayor uso de CPU. Tu suposición sobre Postgres podría ser correcta.

En cuanto al mini profiler: ¿a qué números queremos apuntar? Estamos alrededor de los 300 ms en este momento. Hemos estado en 500 ms antes.

3 Me gusta

Creo que si logramos menos de 50 ms en todos los casos, independientemente de las horas pico de tráfico, lo llamaría un tiempo de respuesta rápido del servidor. El resto del sitio será más rápido ya que todo depende del tiempo de respuesta inicial del servidor.

Y sería súper ideal si se mantiene por debajo de los 50 ms para todos los usuarios geográficos y se mantiene consistente. Por ahora, sigue saltando y es mayormente más alto, y ese parece ser el gran problema de la lentitud.

Como una pequeña revisión de los últimos días, las cosas han ido bien, excepto durante aproximadamente media hora esta tarde. No estuve en el servidor en ese momento, pero tuvimos Timeouts del Backend reportados en el log de nginx. sar muestra una utilización del sistema ligeramente mayor, pero sin una carga general de CPU alta. No estoy seguro de qué fue, pero aparentemente impidió que unicorn/redis/postgres funcionaran sin problemas.

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

Son las líneas marcadas con >.

No veo ningún tráfico alto en ese momento, así que no tengo idea de qué fue, pero realmente solo sucedió en esa media hora.

En general, al observar el tiempo de CPU, Redis ha tomado la delantera y generalmente utiliza una buena parte de la CPU. No estoy seguro de si hay algo que se pueda hacer al respecto. Normalmente está alrededor del 20-25%, alcanzando picos del 35% aquí y allá.

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 carga general promedia 5 a largo plazo, pero todavía la veo subir a 8 o 9 de vez en cuando.

2 Me gusta

En cuanto al mini profiler. Estaba hablando del tiempo de carga general. El tiempo de respuesta del servidor (solicitud inicial) suele ser inferior a 10 ms de nuestro lado. A veces un poco más, pero no he visto >20 ms en mis últimas comprobaciones. El tiempo de carga general llega a ser de hasta 800 ms a veces, muy raramente por encima de 1000 ms.

Solo miramos una región geográfica ya que no tenemos un número significativo de usuarios fuera de esa región.

Recomiendo investigar DISCOURSE_ENABLE_PERFORMANCE_HTTP_HEADERS lo que también debería darte una idea de dónde puedes mejorar el rendimiento.

4 Me gusta