Наша дискуссия перегружена из-за кастомного плагина. Пожалуйста, помогите

О, Роберт,
Мы мигрировали на новый VPS с 4 ядрами (Ryzen 9 5950x),
но загрузка процессора всё ещё почти 100%. Я действительно не понимаю, в чём проблема.



Я думал, вы собирались перейти на сервер Scaleway с 8 ядрами?

Какая заявленная пропускная способность у этого сервера? Неужели низкая пропускная способность может стать узким местом, вызывая медленные подключения или разрывы?

У Scaleway есть VPS с пропускной способностью в сотни мегабит в секунду, а не 30.

Мне кажется, 30 — это крайне мало.

Это спецификация.

4096 МБ DDR3 ECC RAM
4 виртуальных ядра CPU (3,4+ ГГц E3-1231 v3/1241 v3/1240 v5)
200 ГБ HDD-хранилище в RAID 10
5 ТБ трафика @ 1 Гбит/с (после исчерпания лимита скорость ограничивается до 5 Мбит/с)
1 IPv4, /64 IPv6
Защита от DDoS: 20 Гбит/с по TCP, доступна апгрейд до 200 Гбит/с
Сиэтл, штат Вашингтон, США
Панель управления Virtualizor
Не управляется

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

Кстати, вывод htop:


Использование CPU на 100 % — это ненормально. :fearful:
Всё в порядке, кроме нагрузки и использования процессора.

Что-то необычное в логах доступа?

Теперь, кажется, всё успокаивается.


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

Да, именно так!

Хм, тебе стоит ориентироваться на SSD.

Отлично подмечено, Бенджамин!

У Scaleway и других есть NVMe SSD. Это гораздо лучше!

ЦП мог ожидать завершения операций на диске.

Ой, извините, я просто вставил неправильную спецификацию.
Спецификация следующая:

4096 МБ DDR4 ECC ОЗУ
4 vCPU ядра (3.4 ГГц AMD Ryzen 5950X)
100 ГБ RAID NVMe SSD накопитель
5 ТБ трафика @ 10 Гбит/с (скорость ограничена 5 Мбит/с после исчерпания квоты)
1 IPv4, /64 IPv6
Защита от DDoS 20 Гбит/с по TCP, доступно обновление до 200 Гбит/с
Сиэтл, штат Вашингтон, США
Панель управления Virtualizor
Неуправляемый

Это NVMe. :flushed:

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

add_to_class(:user, :total_earned_points) do
    self.user_points.sum(:reward_points)
  end

  add_to_class(:user, :available_points) do
    self.total_earned_points - self.user_rewards.sum(:points)
  end

  add_to_class(:user, :rewards) do
    DiscourseRewards::Reward.where(created_by_id: self.id)
  end

  add_to_serializer(:basic_user, :total_earned_points) do
    user&.total_earned_points
  end

  add_to_serializer(:basic_user, :available_points) do
    user&.available_points
  end

  add_to_serializer(:current_user, :total_earned_points) do
    scope.user.total_earned_points
  end

  add_to_serializer(:current_user, :available_points) do
    scope.user.available_points
  end

  add_to_serializer(:current_user, :user_rewards) do
    scope.user.user_rewards
  end

  add_to_serializer(:current_user, :rewards) do
    scope.user.rewards
  end

Я думал, вы сказали, что удалили все плагины, и поведение осталось прежним?

Есть ли у этого индекс?

Сколько строк в таблице user_rewards? Интересно, что разделение по пользователям здесь не учитывается… (но я предполагаю, что на более низком уровне это как-то реализовано).

Ох, боюсь, что индекс не устанавливается.
Модель показана ниже.

module DiscourseRewards
  class Reward < ActiveRecord::Base
    self.table_name = 'discourse_rewards_rewards'

    has_many :user_rewards
    belongs_to :created_by, class_name: 'User'

    default_scope { where(deleted_at: nil) }
  end
end
module DiscourseRewards
  class UserPoint < ActiveRecord::Base
    self.table_name = 'discourse_rewards_user_points'

    belongs_to :user
    belongs_to :user_badge
    belongs_to :user_points_category

    def self.user_total_points(user)
      UserPoint.where(user_id: user.id).sum(:reward_points)
    end
  end
end
module DiscourseRewards
  class UserReward < ActiveRecord::Base
    self.table_name = 'discourse_rewards_user_rewards'

    belongs_to :user
    belongs_to :reward

    enum status: [:applied, :granted]
  end
end

Я отключил все плагины в безопасном режиме. Однако, как вы знаете, база данных не изменилась. :smiling_face_with_tear:

Думаю, это стоит обсудить с автором.

Кажется, проблема может быть в масштабировании из-за большого количества ваших пользователей?

Возможно, вам потребуется пересобрать систему без плагина. Это будет хорошим сравнением и, возможно, подтвердит, вызваны ли проблемы плагином или нет.

Наличие таблиц не имеет значения, если запросы не выполняются.

discourse_rewards_user_points | 233525 | 27 МБ | 5152 КБ | 32 МБ
discourse_rewards_user_rewards | 61 | 16 КБ | 16 КБ | 32 КБ
discourse_rewards_user_points_categories | 9 | 16 КБ | 16 КБ | 32 КБ
discourse_rewards_rewards | 4 | 16 КБ | 16 КБ | 32 КБ

Таблица discourse_rewards_user_points огромна.

Полностью удалите его (из сборки, таблицы удалять не нужно), посмотрите, что произойдет.

Спасибо, я сейчас же попробую.

О, Роберт, я пересобрал без плагина: время отклика для страниц маршрута обнаружения сократилось с 2–3 секунд до менее 200 мс. :fearful:

Вот и всё. Я бы обсудил оптимизацию с автором или, если у вас есть навыки, отправил бы pull request?

Я прошу помощи у нашего друга, который разбирается в базах данных.
Но он работает на Java. Думаю, это займёт некоторое время.