Аватары долго загружаются после переезда на совместимый с S3 R2

Здравствуйте,

Я только что перешел на R2, и все прошло отлично. Все изображения имеют ссылку на S3 CDN. Однако я заметил проблему: аватары загружаются очень долго. В среднем это занимает от 3 до 4 секунд, независимо от того, кликаю ли я на аватар пользователя или просматриваю сообщение. Это нормально?

Хм, я подозреваю, что проблема может быть одной из трёх, но наиболее вероятная — это изменение размера аватаров «на лету».

1. Изменение размера аватаров «на лету»

Когда вы перенесли загрузки в R2, оригинальные изображения были перемещены; однако Discourse использует аватары разных размеров (например, 45 пикселей для сообщений, 120 пикселей для карточки пользователя).

Если эти оптимизированные размеры не мигрировали идеально или ещё не были сгенерированы, Discourse вынужден генерировать их синхронно в момент, когда пользователь нажимает на аватар:

  1. Discourse скачивает оригинальный аватар из R2 на локальный сервер.
  2. Изменяет его размер с помощью ImageMagick.
  3. Загружает новый размер обратно в R2.
  4. Перенаправляет браузер на новый URL, и этот процесс занимает 3–4 секунды.

Для проверки: выполните жёсткую перезагрузку страницы. Если аватар загружается 3–4 секунды при первом открытии, но мгновенно при втором — это именно то, что происходит.

Для исправления: эта проблема решится сама собой по мере того, как пользователи будут просматривать сайт и размеры будут генерироваться. Но вы можете исправить это мгновенно, принудительно сгенерировав все аватары в фоновом режиме, подключившись к серверу по SSH и выполнив:

./launcher enter app
rake avatars:refresh

2. Тайм-аут IPv6 на 3 секунды

Если аватары загружаются 3–4 секунды каждый раз, даже после нескольких перезагрузок, скорее всего, происходит сетевой тайм-аут.

Конечные точки API Cloudflare R2 являются двойными (dual-stack), то есть они используют как IPv4, так и IPv6. Если на вашем сервере (Droplet) назначен адрес IPv6, но шлюз IPv6 хоста настроен неправильно, внутреннее подключение Ruby к хранилищу R2 сначала попытается использовать IPv6, зависнет на 3 секунды (это стандартный тайм-аут TCP в Linux), завершится ошибкой, а затем мгновенно успешно подключится через IPv4.

Для проверки: подключитесь к серверу по SSH и выполните:

curl -I -6 https://cloudflare.com

Если команда зависает на несколько секунд и завершается ошибкой, значит, IPv6 на сервере настроен неправильно, из-за чего каждая внутренняя проверка API S3 испытывает задержку в 3 секунды.

Для исправления: вам нужно либо исправить маршрутизацию IPv6 в панели управления хостом, либо полностью отключить IPv6 на Droplet.

3. Задержки Gravatar

Если ваш сайт настроен на проверку обновлений Gravatar, он может опрашивать внешние серверы Gravatar перед отображением аватара. Если у сервера медленное исходящее подключение (что часто также связано с DNS или IPv6), это может блокировать отображение аватара.

Для проверки: выполните на сервере команду:
curl -I -6 https://gravatar.com
Если она зависает на 3 секунды, значит, IPv6 настроен неправильно (см. выше).

Исправление, связанное с Gravatar: в настройках Discourse перейдите в раздел автоматически загружать граватары, временно отключите эту опцию и посмотрите, поможет ли это. Я не думаю, что это основная проблема, но если это так, вы можете оставить настройку отключённой, исправить маршрутизацию IPv6, как описано в пункте 2 выше, или изменить DNS-резолвер.

Спасибо за быстрый ответ. Кажется, я уже пробовал команду ‘rake avatars:refresh’ ранее, но не уверен в этом на все сто.

Раньше у меня получалось мгновенно открывать аватар, если кликнуть по нему дважды: первый раз — для загрузки, второй — для мгновенного открытия. Но, вероятно, это связано с кэшированием. Я также только что протестировал ваш второй совет, и он возвращает «HTTP/2 301» с несколькими другими строками. То же самое касается третьего совета. Я снова запущу avatars:refresh через пару дней, так как мне нужно было восстановить снимок состояния (snapshot). Ещё раз спасибо!

Gravatar

server: nginx
date: Mon, 22 Jun 2026 19:29:00 GMT
content-type: text/html; charset=utf-8
content-length: 0
content-language: en
expires: Wed, 11 Jan 1984 05:00:00 GMT
cache-control: no-cache, must-revalidate, max-age=0
x-redirect-by: Gravatar
location: https://en.gravatar.com/
alt-svc: h3=":443"; ma=86400
strict-transport-security: max-age=31536000; includeSubdomains; preload

CF

HTTP/2 301
date: Mon, 22 Jun 2026 19:27:00 GMT
content-type: text/html
content-length: 167
location: https://www.cloudflare.com/
cache-control: max-age=3600
expires: Mon, 22 Jun 2026 20:26:59 GMT
set-cookie: __cf_bm=eBP2aJ7Eg30nHPuvMMNxxKrgNtcNwKs0WDgnYyONeus-1782156420-1.0.1.1-sXpW27iuhGDF615cOfwNFybH4IMxgvZy3uA_3X_o..402T_3KSgT7CSymipL5RjdpGe3raWEqsVxQFFLPKRoDjfoT7B.0rqyDt.osbkOF98; path=/; expires=Mon, 22-Jun-26 19:57:00 GMT; domain=.cloudflare.com; HttpOnly; Secure; SameSite=None
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=QfYqSekEDPJHC2k%2BMjHN0cGjz172tmUWe2GSR8EgwNLh3TGjFYkQ0vwPxlzY1NcBcKFOMaAi4FlgjqjhETOOtHf%2BH9KdQSvqN3OME2Uh1i4nHIw%2Fy1qkvSpf4jxDchM7CaDW80tJkjBV4OqF"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
strict-transport-security: max-age=15780000; includeSubDomains
server: cloudflare
cf-ray: a0fda5d8ecd6b26d-LAX
alt-svc: h3=":443"; ma=86400

Да, учитывая ваш ответ, я почти уверен, что проблема в пункте №1, поскольку результаты команды curl для Cloudflare и Gravatar выглядят ожидаемо. Попробуйте выполнить rake avatars:refresh, когда вам будет удобно, и дайте знать, сработало ли это.