Как масштабироваться дальше (2+ млн постов, +80 тыс. в месяц)

Я хотел бы воспользоваться вашим опытом, чтобы узнать, как масштабировать наше аппаратное обеспечение.

Вот наши ключевые данные:

2,2 миллиона постов, текущий рост — около 80 тысяч в месяц.
35 тысяч пользователей, текущий рост — около 1,5 тысячи в месяц.

Сейчас мы работаем на виртуальной машине Hetzner с 8 выделенными ядрами и 32 ГБ ОЗУ. В декабре мы начали сталкиваться с ограничениями: сначала количество соединений рабочих процессов Nginx достигло предела, поэтому мы увеличили его с 768 (значение по умолчанию) до 1536. Вчера мы снова уперлись в этот предел и подняли значение до 3072. После этих изменений система снова работает стабильно, но мы приближаемся к 100% использованию сервера.

Параметр db_work_mem установлен на 80 МБ, db_shared_buffers — на 8192 МБ. Мы совсем не используем доступную память, но я не уверен, есть ли смысл задействовать её больше и получить от этого выгоду. Что вы думаете?

#~> free -m

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

Следующий простой вариант масштабирования в Hetzner — это 16 ядер и 64 ГБ ОЗУ, что для нас приемлемо по стоимости, но я сомневаюсь, имеет ли смысл продолжать вертикальное масштабирование. Я подумываю, не будет ли гораздо разумнее разделить приложение и базу данных на разные сервера, или это создаст слишком много сложностей.

Кто-нибудь уже делал так? Поделитесь своим опытом.

Почему вы стремитесь к масштабированию? Ухудшаются ли ваши метрики времени отклика API?

О каком ресурсе идёт речь? CPU? Место на диске? Оперативная память?

Сколько у вас просмотров страниц?

Игнорируйте все советы, которые вы найдете в интернете, и установите значение на 40–50% от вашей оперативной памяти.

Можете ли вы поделиться выводом sar?

Потому что я планирую заранее. Возможно, нам сейчас не нужно масштабироваться, но, учитывая наблюдаемый рост и растущую потребность в ресурсах, которую мы видели в прошлом, я просто заранее обдумываю возможные следующие шаги.

В основном CPU — после сегодняшнего обновления пиковая нагрузка снизилась с ~8–9 до ~6.

12 млн в месяц, по сравнению с 6,5 млн в месяц год назад.

Вернусь к выводу sar позже, сейчас он не был запущен.

Вам стоит выяснить, что именно использует процессор. Это может быть:

  • воркеры веб-сервера Unicorn
  • PostgreSQL
  • Sidekiq, например фоновые задачи по оптимизации изображений
  • Redis
  • nginx (маловероятно)

В зависимости от причины мы можем предложить способы снизить нагрузку.

Судя по времени процессора, это в основном воркеры unicorn:

Может, отказаться от идеи с выделенным процессором и воспользоваться этим предложением?

Кажется, это больше подходит под ваши задачи.

Я уже думал об этом варианте. Ранее мы использовали не выделенные процессоры, и «переход» на выделенные не принёс нам особого прогресса.

Не уверен, что узким местом является процессор. Можете ли вы пока поделиться выводом команды sar?

Да, я работаю, но пиковые часы ещё не наступили. Они начнутся завтра.

Загрузка процессора определённо снизилась после того, как я вчера увеличил количество соединений воркеров, хотя точно не знаю, насколько.

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

Какие показатели sar стоит учитывать как полезные?

Я подозревал, что Postgres не получал достаточно памяти, что приводило к высокому значению %iowait.
Но поскольку приведенный выше вывод sar не указывает на перегрузку системы, нам придется подождать новых статистических данных.

Я пытаюсь помочь кому-то с проблемами производительности. Мы увеличили размер буфера PostgreSQL. Думаю, это немного помогло, но MiniProfiler всё ещё показывает более 300 мс. Использование ЦП составляет около 30% для 16 ядер.

Похоже, это не изменится. Я наблюдал за этим в течение двух вечеров, и использование процессора не превысило предыдущих значений. Ваше предположение относительно Postgres, возможно, верно.

Что касается мини-профилировщика: на какие показатели нам стоит ориентироваться? Сейчас у нас около 300 мс. Ранее было около 500 мс.

Я считаю, что если мы достигнем ниже 50 мс во всех случаях, независимо от часов пиковой нагрузки, это будет называться быстрым временем отклика сервера. Остальная часть сайта станет быстрее, так как всё зависит от первоначального времени отклика сервера.

Идеально было бы, если бы время отклика оставалось ниже 50 мс для пользователей из всех географических регионов и было стабильным. На данный момент оно постоянно скачет и чаще всего выше, что, по-видимому, является основной причиной медленной работы.

Краткий обзор последних дней: всё шло гладко, за исключением примерно получаса сегодня днем. Сам я в то время на сервере не был, но в логах nginx были зафиксированы таймауты от бэкенда. Утилита sar показывает немного повышенную системную загрузку, но общей высокой нагрузки на CPU не наблюдается. Не совсем понятно, что именно произошло, но это явно мешало корректной работе Unicorn, Redis и PostgreSQL.

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

Это строки, помеченные символом >.

В это время я не наблюдаю никакого всплеска трафика, поэтому пока не могу понять, что именно произошло, но проблема проявлялась только в течение этого получаса.

В целом, если смотреть на время процессора, Redis вышел на первое место и в целом потребляет значительную часть CPU. Не уверен, можно ли что-то с этим сделать. Обычно его загрузка составляет около 20–25%, иногда достигая пиков в 35%.

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

Общая нагрузка в долгосрочной перспективе в среднем составляет 5, но я всё ещё наблюдаю периодические всплески до 8 или 9.

Что касается мини-профилировщика. Я говорил об общем времени загрузки. Время ответа сервера (первоначальный запрос) у нас обычно составляет менее 10 мс. Иногда немного больше, но в моих последних проверках я не видел значений выше 20 мс. Общее время загрузки иногда достигает 800 мс, очень редко — выше 1000 мс.

Рассматриваем только один географический регион, так как у нас нет значительного числа пользователей за его пределами.

Рекомендую изучить DISCOURSE_ENABLE_PERFORMANCE_HTTP_HEADERS, что также даст вам представление о том, где можно улучшить производительность.