Добавить в корзинуПозвонить
Найти в Дзене
Роман Вахнин

Сервис «лёг» через несколько недель после запуска. И проблема была не в Nginx

Через несколько недель после запуска конвертер.онлайн у нас случилась первая настоящая production-ситуация. Сервис перестал открываться. Снаружи всё выглядело довольно стандартно: 502 Bad Gateway. Первая мысль в такой ситуации почти автоматическая: что-то с Nginx. Это логично. Nginx встречает пользователя снаружи, проксирует запросы дальше и именно через него мы часто видим такие ошибки. Но в этот раз проблема была не в нём. Nginx работал. А вот backend-контейнер падал в цикле и не мог нормально подняться. Когда начали разбираться, выяснилось, что приложение на старте выполняет инициализацию базы данных. В том числе делает изменения в таблицах. И из-за некорректной строки подключения к базе всё упиралось в ошибки ещё на этапе запуска. Сначала приложение попадало в ситуацию с read-only транзакцией. Потом нашлась ещё одна проблема: в строке подключения остались параметры, которые не подходили драйверу, через который backend подключался к базе данных. В итоге сервис падал не из-за одной б
Оглавление
Ошибка Internal Server Error на сервисе, после перезапуска ВМ 502 Bad Gateway
Ошибка Internal Server Error на сервисе, после перезапуска ВМ 502 Bad Gateway

Через несколько недель после запуска конвертер.онлайн у нас случилась первая настоящая production-ситуация.

Сервис перестал открываться. Снаружи всё выглядело довольно стандартно: 502 Bad Gateway. Первая мысль в такой ситуации почти автоматическая: что-то с Nginx. Это логично. Nginx встречает пользователя снаружи, проксирует запросы дальше и именно через него мы часто видим такие ошибки.

Но в этот раз проблема была не в нём. Nginx работал. А вот backend-контейнер падал в цикле и не мог нормально подняться.

Что оказалось внутри

Когда начали разбираться, выяснилось, что приложение на старте выполняет инициализацию базы данных. В том числе делает изменения в таблицах. И из-за некорректной строки подключения к базе всё упиралось в ошибки ещё на этапе запуска. Сначала приложение попадало в ситуацию с read-only транзакцией. Потом нашлась ещё одна проблема: в строке подключения остались параметры, которые не подходили драйверу, через который backend подключался к базе данных.

В итоге сервис падал не из-за одной большой ошибки.

Это была цепочка небольших технических несостыковок:

  • настройки подключения;
  • инициализация базы на старте;
  • параметры, которые не поддерживались нужным драйвером;
  • backend-контейнер, который из-за этого не мог подняться.

После исправления строки подключения и перезапуска контейнера сервис восстановился.

Почему это важно

Эта история хорошо показывает разницу между двумя состояниями продукта.

Первое:

«Проект работает у меня».

Второе:

«Проект живет в production».

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

Сервис должен подниматься после перезапуска.
Контейнеры не должны падать в цикле.
База данных должна быть доступна.
Настройки окружения должны соответствовать реальной инфраструктуре.
Одна ошибка не должна превращать весь сервис в недоступную страницу.

Это не самая эффектная часть создания продукта.

Но она очень настоящая.

Что я понял

После этой ситуации я ещё раз убедился: запуск продукта – это не момент, когда работа заканчивается. Скорее наоборот. До запуска ты строишь систему. После запуска ты начинаешь отвечать за то, чтобы она жила.

И это совсем другой уровень отношения к проекту.

Можно сколько угодно считать, что главное — это функции. Но если сервис не открывается, пользователю уже не важно, какие функции ты сделал. Сначала продукт должен просто работать.

А всё остальное начинается после этого.