Parse — популярная платформа для разработки мобильных приложений, изначально созданная на базе Ruby on Rails. За годы своего существования она выросла из небольшого инди-проекта до масштабного сервиса с тысячами клиентов и миллионами запросов в секунду. Однако с ростом числа пользователей и объема трафика в технической архитектуре стали проявляться серьезные проблемы, требующие фундаментального пересмотра подходов к инфраструктуре и языку разработки. В центре изменений оказался ключевой компонент — API сервер Parse, который пришлось переписать с Ruby на Golang, что оказало огромное влияние на стабильность и масштабируемость сервиса. Истоки Parse и выбор Ruby on Rails были естественными: Ruby позволял создавать первые версии API быстро, а большой выбор библиотек и инструментов ускорял разработку и запуск.
Команда использовала хорошо знакомые технологии — Unicorn для HTTP сервера, Capistrano для деплоя и Chef для управления инфраструктурой. Благодаря этому Parse смог быстро выйти на рынок и начать набирать популярность. Однако по мере роста клиентской базы и числа одновременных запросов возникали первые системные ограничения, которые невозможно было игнорировать. Основная сложность Ruby on Rails заключалась в его архитектуре — каждый HTTP-запрос обрабатывался отдельным процессом. При возрастании нагрузки это приводило к блокировкам, так как медленные запросы занимали рабочие процессы и тормозили систему.
Автоматическое масштабирование срабатывало слишком медленно, вызывая деградацию производительности. Постепенно это стало узким местом, особенно когда число API серверов достигло 200 и нагрузка выросла до нескольких тысяч запросов в секунду. Команда Parse осознала, что для дальнейшего роста необходимо перейти на асинхронную модель обработки запросов, которая резко отличается от привычного синхронного подхода Rails. Появилась идея выбрать другой язык программирования, способный поддерживать асинхронность и более эффективное использование ресурсов. Рассматривались разные варианты — от EventMachine в Ruby до JRuby, C++, C# и, наконец, Go.
Опыт с EventMachine был неудачным: из-за отсутствия потокобезопасных библиотек и искажений параллельной обработки он не решал возникавших проблем. JRuby казался логичным решением, но сохранял ограничения Ruby и добавлял сложности с JVM, что не приветствовалось командой. C++ имел недостатки с точки зрения сложности поддержки и отладки, а C# на Linux выглядел как неконкурентоспособный вариант с ограниченной интеграцией в инфраструктуру. Решение встало между Golang и C#. Go оказался предпочтительнее благодаря встроенной легковесной поддержке асинхронности через горутины, отличной библиотеке для работы с MongoDB и общей простоте разработки.
Команда была вдохновлена идеей писать понятный и быстрый код, которым будет легко управлять и развивать. Первая пятно миграции — перезапуск backend-подсистемы push-уведомлений — показала потрясающий прирост производительности. С 250 тысяч подключений на узел удалось перейти к 1,5 миллионам, без изменения ядра ОС и настройки сети. Это ли не доказательство эффективности Go? Основной и самый сложный этап заключался в создании новой версии самого API для api.parse.
com. Нужно было не просто переписать код, но и обеспечить максимальную совместимость с существующими клиентами. В ходе миграции применялась технология live shadowing, когда реальные запросы дублировались на старую и новую систему, и ответы сравнивались на идентичность. Это позволяло выявлять отклонения и подгонять логику, избегая сбоев и потери данных. Особой сложностью стало воспроизведение специфического поведения Rails middleware.
Он отличался либеральностью в обработке нестандартных или даже не соответствующих спецификациям HTTP-запросов. Многие клиенты, намеренно или случайно, отправляли запросы с двойным URL кодированием, нестандартными заголовками или телами там, где их быть не должно. Ruby код скрывал эти проблемы и «чистил» входящие запросы. Чтобы не сломать существующие приложения, пришлось частично портировать подобные особенности в Go и писать трудоемкие обходные решения. Кроме текстовых тонкостей, приходилось учитывать и тонкие различия в поведении кэшей, OAuth-обработке, работе с Unicode и многом другом.
Комментарии в исходном коде нового API зачастую отражали эти нюансы как эмоциональные ремарки программистов, которые «знают о странностях» и вынуждены их поддерживать ради клиентской совместимости. Итоги переписывания оказались впечатляющими. Надежность системы выросла в 10 раз, и команда перестала получать частые инциденты, связанные с API-слоем. Контроль над ошибками и таймаутами стал намного локализованнее, в основном затрагивая отдельные приложения, где запросы были неоптимальными или вызывали нагрузку на подлежащие базы данных. Переход на асинхронную модель позволил собрать широкий комплекс метрик и счетчиков, что ранее было затруднительно из-за блокирующих операций.
Это облегчило диагностику и мониторинг, что положительно сказалось на работе операторов и разработчиков. Производительность возросла настолько, что управлять количеством серверов API стало гораздо проще — требовалось около 10% от предыдущего парка машин. Архитектура избавилась от множества устаревших Rails-серверов, упростилась и стала более прозрачной. Время прогона полного интеграционного тестирования сократилось с 25 минут до 2, а полное развертывание нового API сервера с переразгрузкой — с получаса до 3 минут. Перезапуск новых Go серверов происходил плавно, без лишних действий с балансировщиками, что избавляло команду от стрессов и рисков.
В итоге выбор Golang оправдался не только технологически, но и с точки зрения человеческих ресурсов и эксплуатируемости. Разработчики отмечали, что Go оказался более легким и увлекательным в работе, что давало дополнительный позитивный эффект для команды. Этот опыт является поучительным примером того, как правильный выбор технологии и тщательно продуманная стратегия миграции могут кардинально улучшить продукт. История Parse не просто отражает технический кейс, но и показывает важность понимания ограничений существующих решений и отвагу на серьезные изменения, чтобы идти в ногу с ростом и требованиями сегодняшнего рынка. Ключевые фигуры, внесшие большой вклад в этот переход, получили признание как инициаторы и исполнители, что подчеркивает коллективный характер успеха.
И хотя после закрытия Parse часть документации и блогов затерялась, воспоминания о тяжелейшем, но успешном переписывании живут и служат вдохновением для инженеров по всему миру. Сегодня истории вроде этой учат нас, что технология — лишь инструмент, а настоящая сила в понимании процессов, внимании к деталям и готовности к трудностям ради улучшения качества и масштабируемости продуктов. Взгляд назад на путь Parse позволяет сделать выводы, которые актуальны для любого живого и развивающегося проекта, стремящегося обеспечить отличный опыт своим пользователям.