Причём подвело не то, над чем мы так старательно работали. Сюрприз пришёл со стороны инфраструктуры — той самой, которая вроде бы просто должна была обеспечивать работу приложения. Но, как выяснилось, у неё тоже имелась творческая программа на вечер.
Всё было готово к розыгрышу
Задача выглядела понятной: сделать приложение для розыгрыша призов на мероприятии.
Участник регистрируется, получает персональный QR-код, отмечается на площадке и попадает в список участников розыгрыша. Затем запускается барабан, определяется победитель — и дальше наступает та приятная часть, ради которой всё затевалось: призы, улыбки, аплодисменты.
Для организаторов — админпанель. Для участников — простой сценарий без лишних действий. Для разработчиков — удовольствие от системы, в которой всё наконец-то работает как задумано.
Приложение получилось качественным и отлаженным. Регистрация, учёт участников, административная часть, колесо розыгрыша — всё работало как часы.
Для размещения взяли сервер с заявленными характеристиками:
- 20 ГБ NVMe.
- 2 ГБ RAM.
- 2 CPU.
На этапе подготовки проблем не возникало. Приложение отвечало, страницы открывались, механика розыгрыша работала.
Барабан крутился. Ничто не предвещало, что следующим начнут крутиться разработчики.
Праздник начинается, регистрация заканчивается
В день мероприятия главная страница регистрации вдруг перестала загружаться.
Не выдала понятную ошибку. Не сообщила, что ей тяжело. Просто зависла в браузере — с той невозмутимостью, которая особенно раздражает, когда рядом стоят люди и ждут.
Участники приходят, сканируют QR-код для перехода к регистрации, открывают страницу. И дальше ничего.
Время идёт. Сценарий мероприятия тоже. Только браузер решил остаться в моменте.
Перезагрузка сервера помогала, но ненадолго. Приложение оживало, давало надежду — и снова переставало нормально отвечать. Получился незапланированный аттракцион: «Успей зарегистрироваться между перезагрузками».
При разборе ситуации обнаружилось неприятное расхождение. По результатам проверки на сервере было доступно около 1,3 ГБ RAM и 1 CPU вместо заявленных 2 ГБ и 2 CPU.
Здесь важно отделять наблюдение от окончательного технического диагноза: одного такого замера недостаточно, чтобы доказать причину зависаний или намеренную экономию провайдера. Но в момент аварии практическая проблема была очевидна: рассчитывали на одну конфигурацию, а увидели другую. И работающего решения на этой площадке получить не удавалось.
Обратились в поддержку хостинга. Объяснили, что идёт мероприятие, регистрация не работает, нужна помощь. Были готовы оплатить дополнительные ресурсы или подходящий вариант усиления сервера.
Ответ свёлся к тому, что у нас полный доступ к серверу, а значит, разбираться с его работой мы должны самостоятельно.
Полный доступ — прекрасная вещь. Особенно когда вместе с ним тебе торжественно передают полную ответственность и больше ничего.
Переезд посреди мероприятия
Стало понятно: ждать больше нельзя. Нужно переносить приложение на другой сервер — прямо сейчас, пока мероприятие продолжается.
Это совсем не тот переезд, который заранее планируют на тихий вечер. Здесь нельзя спокойно предупредить пользователей, выделить окно обслуживания и обстоятельно выпить чай.
Нужно сохранить уже собранные регистрации, развернуть приложение на другом сервере, восстановить доступ и всё-таки провести розыгрыши, которые уже выбились из сценария.
Сказать, что это был стресс, — примерно как назвать пожар небольшим изменением температурного режима.
Самое неприятное — контраст. Ты знаешь, сколько работы вложено в приложение. Знаешь, что механика продумана и всё отлажено. Но для человека перед зависшей страницей это не имеет значения.
Он видит только одно: зарегистрироваться нельзя.
Пользователь не обязан разбираться, где закончился код и начался хостинг. Для него всё это — один сервис, который сейчас не работает. И хорошо сделанное приложение внезапно превращается в очень публичный момент неловкости.
В итоге приложение удалось перенести на сервер с другой конфигурацией:
- 400 ГБ NVMe.
- 24 ГБ RAM.
- 16 CPU.
После переноса всё заработало. Регистрации сохранили, работу приложения восстановили, розыгрыши удалось провести.
Это не означает, что для любого призового барабана обязательно нужны 16 CPU и 24 ГБ памяти. Просто в аварийной ситуации приоритет был другим: не подобрать самую экономичную конфигурацию, а вернуть работающий сервис с большим запасом ресурсов.
Оптимизацию бюджета можно обсудить потом. Участники уже стоят у входа.
Что осталось после приключения
Главный вывод: даже отличное приложение не существует отдельно от среды, в которой оно работает. Можно тщательно продумать пользовательский сценарий и отладить каждую кнопку, а неприятность получить на уровне, который казался самым скучным и надёжным.
Для массовых мероприятий теперь стоит отдельно закладывать несколько вещей.
- Запас ресурсов. Не «в спокойном режиме вроде хватает», а резерв под одновременный приход участников. Экономия на площадке выглядит особенно скромно на фоне стоимости сорванного сценария.
- Проверку реальной конфигурации. Характеристики в тарифе — повод проверить, что именно доступно приложению после развёртывания.
- Нагрузочную репетицию. Проверять не только одну успешную регистрацию, но и массовое открытие страниц, отправку форм и работу админпанели в это же время.
- Подготовленную резервную площадку. План Б полезнее, когда для него уже есть доступы и понятный порядок развёртывания.
- Продуманный перенос данных. Недостаточно запустить пустую копию приложения: нужно сохранить участников и не потерять новые регистрации при переключении.
- Понимание границ поддержки. До мероприятия стоит выяснить, кто помогает при аварии, что входит в обслуживание и можно ли оперативно увеличить ресурсы.
И ещё один вывод — уже не про серверы.
Сохранять лицо в такой ситуации не значит делать вид, что всё прекрасно. Когда регистрация висит, этот спектакль всё равно никто не оценит.
Сохранять лицо — значит спокойно признать проблему, объяснить организаторам, что происходит, и предложить конкретные действия. Не искать виноватого раньше, чем найден способ восстановить работу. Не обещать «ещё две минуты», если для этого нет оснований. Делать то, что действительно приближает решение.
У этой истории нашлись и плюсы. Не такие, ради которых хочется специально повторить опыт, но вполне полезные.
Мы получили реальный опыт аварийного переноса: приложение удалось восстановить на другой площадке с сохранением регистраций. Увидели слабое место не в теории, а в работе всей системы. И получили очень убедительный аргумент в пользу резерва, проверок и плана Б — без долгой презентации о том, почему это важно.
А ещё стало ясно: ценность разработчика не заканчивается на хорошо написанном коде. Иногда она проявляется в тот момент, когда всё пошло не по плану, а человек не исчез, не ушёл в объяснения и довёл ситуацию до работающего результата.
Лучше, конечно, проверять это без зрителей.
Но если уж технический сюрприз вышел на сцену, главное — не отдавать ему всё мероприятие. Барабан должен крутиться в приложении, а не в голове у разработчика.