Rake:rebake завершается с ошибками: PG::ConnectionBad: PQsocket

Я перенёс форум с 200 000 постов на новый сервер. Работающий сайт был переведён в режим только для чтения, чтобы избежать простоев.

Я восстановил резервную копию на другом поддомене, чтобы пользователи не видели экраны установки или любые проблемы, которые могли возникнуть во время восстановления — что-то вроде dev.example.com.

Как только восстановление было завершено, я перенаправил DNS на новый сервер и изменил домен в файле app.yml на обычный forum.example.com.

Тогда все смайлики в исходных постах указывали на сервер dev.example.com, поэтому я запустил rake:rebake.

Процесс обрабатывает около 1 000–2 000 постов, после чего падает с ошибками, связанными с подключением к базе данных.

Вот несколько фрагментов:

/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/cli.rb:34:in `dispatch'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/cli.rb:28:in `start'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/exe/bundle:45:in `block in <top (required)>'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/lib/ruby/gems/3.2.0/gems/bundler-2.4.4/exe/bundle:33:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
     1999 / 200968 (  1.0%)
Failed to rebake (topic_id: 78730, post_id: 210607)
PG::ConnectionBad: PQsocket() can't get socket descriptor
/var/www/discourse/lib/tasks/posts.rake:108:in `rebake_posts_all_sites'
/var/www/discourse/lib/tasks/posts.rake:7:in `block in <main>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'

Caused by:
PG::ConnectionBad: PQsocket() can't get socket descriptor

В данный момент я загрузил изображения, перенаправив домен dev.example.com на домен forum.example.com, но это лишь временное решение.

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

Сначала ознакомьтесь со статьей Смена имени домена или переименование вашего Discourse (хотя альтернативным решением может быть создание резервной копии, а затем восстановление с новым именем хоста).

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

Это стандартная установка или вы используете какой-то другой сервер PostgreSQL?

Спасибо за ссылки. Это стандартная установка Docker на дроплет DigitalOcean («Premium AMD», 4 ГБ ОЗУ, 2 vCPU).

Я следовал инструкциям по ссылке, которую вы упомянули. Нашел несколько неверных URL в настройках, исправил их и заново собрал форум на всякий случай.

Затем я выполнил команду вроде этой:

discourse remap dev.example.com forum.example.com

Эта команда завершилась с ошибкой такого рода:

Error: ERROR:  duplicate key value violates unique constraint "unique_post_links"
DETAIL:  Key (topic_id, post_id, url)=(78821, 207117, https://forum.example.com/t/the-slug/78946/7) already exists.

Поэтому я временно удалил сообщение, содержащее ссылку на указанный URL (https://forum.example.com/t/the-slug/78946/7), снова выполнил команду, и она сработала без сбоев.

Затем я снова запустил rake posts:rebake.

Оно не удалось для нескольких сообщений, как показано ниже, но продолжило работу (я вручную восстановил HTML для этих сообщений):

Rebaking post markdown for 'default'
     2273 / 200996 (  1.1%)
Failed to rebake (topic_id: 66586, post_id: 210353)
JavaScript was terminated (either by timeout or explicitly)

В итоге оно завершилось с ошибкой незадолго до достижения 11 000 сообщений с ошибками такого вида:

/usr/local/bin/bundle:25:in `<main>'
    10996 / 200996 (  5.5%)
Failed to rebake (topic_id: 76678, post_id: 200988)
PG::ConnectionBad: PQsocket() can't get socket descriptor
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:69:in `exec_params'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.4.1/lib/active_record/connection_adapters/postgresql_adapter.rb:768:in `block (2 levels) in exec_no_cache'

Весь сервер, похоже, отключился, так как Uptime Robot прислал уведомление о том, что сайт недоступен.

Как вы думаете, сервер недостаточно мощный для выполнения этой команды? :thinking:

Обычно он использует более 80% ОЗУ, а во время выполнения команды достигает 100%. Возможно, он просто исчерпал память.

Если у вас есть локальный диск, вы можете добавить файл подкачки, что позволит избежать исчерпания памяти (независимо от того, является ли это причиной возникшей проблемы). Что показывает команда free? Видите ли вы в выводе dmesg упоминания oom или memory?

В данный момент вывод такой:

               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       2.1Gi       160Mi       1.0Gi       1.6Gi       488Mi
Swap:             0B          0B          0B

Я не вижу oom, но слово memory встречается в нескольких местах, касающихся резервирования и освобождения памяти.

Сервер был создан с 4 ГБ ОЗУ, поэтому Discourse не создал автоматически файл подкачки. Как вы думаете, стоит его добавить?

Если у вас есть место на диске, определенно стоит добавить, скажем, 2 ГБ подкачки.

Еще один шаг — следить за использованием ресурсов во время выполнения большой задачи. Я бы использовал vmstat 5 5 и, возможно, выводил бы данные в файл. Вы надеетесь не увидеть больших значений в столбцах si или so, а также не допустить, чтобы значение в столбце swpd приблизилось к размеру вашей подкачки.

Возможно, стоит посмотреть этот пост:

(Возможно, система базы данных исчерпывает какой-то ресурс, но я ничего об этом не знаю.)

Спасибо, я попробую это сегодня позже. У меня сейчас свободно 50 ГБ.

Я добавил файл подкачки размером 2 ГБ, и, похоже, это решило проблему. Процесс перепекания завершён лишь на 20%, но ошибок пока не возникло, а использование оперативной памяти составляет чуть менее 100%.

Спасибо вам обоим за помощь.

Звучит отлично! Только для справки:

  • вы можете добавить больше swap-памяти, даже пока задача выполняется, если vmstat или free (или top) показывают, что swap исчерпывается.
  • если действовать осторожно, можно выполнить временное и обратимое повышение до экземпляра с большим объёмом ОЗУ. Это немного стоит, но потребуется лишь на несколько часов. Важно не переходить на экземпляр с большим диском, так как это необратимо. (Больше ОЗУ позволит работать на полной скорости, тогда как скромный объём ОЗУ и большой swap могут привести к снижению производительности, и задача завершится дольше.)

Я думал об этом, но мне пришлось бы выключить сервер, а у пользователей уже был неприятный период «только для чтения» и простои при переносе серверов. :sweat:

Вчера вечером я не смог закончить, так как мне пришлось ложиться спать, но сейчас всё снова работает. Уже 30% выполнено, и ошибок пока нет.

Продолжайте следить за процессом с помощью vmstat или аналогичных утилит — это задача, которая выполняется очень долго, и вам не захочется её перезапускать. Для подстраховки, вероятно, стоит добавить ещё 2 ГБ подкачки.

Спасибо, я периодически проверял с помощью vmstat. Я запустил его в сессии tmux, чтобы можно было отключиться и на время закрыть ноутбук. Команда, вероятно, выполнялась 8–9 часов, но всё завершилось без ошибок.