Фото: Alex Smith | Unsplash
Добрый день!
Меня зовут Виктор Пряжников, я работаю в отделе Features компании Badoo. Основная задача нашего отдела — разработка функционала, который видят пользователи нашего сайта и приложений. Когда мне попалась на глаза статья сооснователя Unsplash Люка Чессера, она заинтриговала меня тем, что им удаётся развивать сравнительно большой проект совсем маленькой командой. Подход автора импонирует мне своей прагматичностью и чем-то напомнил «Вы — не Google», поэтому я решил её перевести.
Одна из самых забавных вещей в разработке Unsplash — большой масштаб и популярность продукта.
В обычный день наш API обрабатывает больше 10 млн. запросов от unsplash.com и тысяч сторонних приложений, через наш пайплайн обработки данных проходят миллионы событий, в наши ленты добавляются 60 млн. обновлений, и мы обслуживаем 60 млн. изображений.
В то же время наша команда сравнительно мала: два дизайнера, три человека, работающих с фронтендом, два — с бекендом и один дата-инженер. У нас нет отдельного DevOps-инженера, и каждый член команды тратит бОльшую часть своего времени на эксперименты и разработку новых фич для обеспечения дальнейшего развития продукта.
Хотя мы уже достигли многого с Unsplash, мы всё ещё находимся в самом начале его пути как продукта и бизнеса. Нам по-прежнему есть что доказывать, и это значит, что нужно, чтобы вся команда была сфокусирована на решении проблем, уникальных для Unsplash, а не тех, которые есть у любой другой компании, вроде организации выкладок, безопасности сети, построения инфраструктуры, управления зависимостями и т. д.
За последние три года мы выработали набор принципов, которые позволяют нам фокусироваться на росте и избегать проблем масштабирования. К сожалению для тех, кто ищет серебряную пулю, здесь её не будет: это просто здравый смысл и набор принципов, который мы заимствовали у других.
1. Используйте скучные очевидные решения
Или будьте прагматичны.
Прежде чем приступить к внедрению нового инструмента, базы данных (RethinkDB, RocksDB и т. д), нового паттерна («функциональное всё!») или новой архитектуры («микросервисы, на помощь!»), перепробуйте все очевидные варианты.
На стороне бекенда совсем немного проблем, которые не могут быть достаточно эффективно решены с использованием стандартных, хорошо известных инструментов и проверенных паттернов вроде кеширования, пакетной обработки, асинхронной обработки и предварительной подготовки необходимых данных.
2. Фокусируйтесь на решении проблем пользователей, а не технологий
Unsplash — это продуктовая, а не технологическая компания. Мы получили кучу денег от инвесторов, чтобы сфокусироваться на решении проблем нашего продукта и рынка, а не пытаться добиться трёхпроцентного снижения операционных расходов на применение общих технологий.
Мы тратим своё время на использование готовых технологий таким образом, который поможет решить проблемы наших пользователей и увеличить сообщество Unsplash. Это задачи, уникальные для Unsplash, и, если мы преуспеем в создании чего-то нового и ценного, мы можем отложить оптимизацию на более поздний срок, когда эти 3% оптимизации смогут стать главным источником роста.
Наших потенциальных коллег, которые слышали о масштабах Unsplash и маленькой команде, использовании изображений и искусственного интеллекта, будущих фичах, может смутить тот факт, что мы используем много работающих «из коробки» технологий, сервисов и фреймворков. Это заставляет нас платить немного больше прямо сейчас, но зато позволяет отложить внутреннюю разработку этих технологий на какое-то время и переложить её на плечи наших будущих коллег.
Процесс выкладки кода, конфигурирование серверов, системные зависимости, обработка и анализ данных, обработка изображений и персонализация — это примеры областей, которые мы выбрали, чтобы не фокусировать на них наши инженерные ресурсы, а использовать вместо этого готовые сторонние сервисы для каждой из них.
3. Тратьте деньги на решение технологических проблем
Обратная сторона фокуса на продуктовых проблемах заключается в дополнительных расходах на доступ к готовым технологиям и сторонним сервисам.
Это стало чем-то вроде шутки внутри нашей команды. Говорят, что моей первой реакцией на любую проблему будет вопрос: «А вы пробовали решить её с помощью денег?». Но это не шутка, а один из моих любимых подходов к решению проблем.
Оптимизация расходов, связанных с инфраструктурой и технологиями, — это настолько общая проблема с простыми и повторяющимися решениями, что ни одна продуктовая компания с инвесторами не должна заботиться о ней до тех пор, пока не почувствует, что рост основной метрики перестал быть её приоритетом.
Когда мы тратим деньги на решение технологических проблем, мы развязываем руки команде, позволяя ей сфокусироваться на неповторяющихся сложных проблемах вроде поиска способа увеличения размера базы пользователей на 40% в текущем квартале.
Итак, это три довольно простых, но абстрактных принципа, которым мы следуем.
Но как они выглядят на практике?
Если вы посмотрите на архитектуру Unsplash, то увидите, что она очень простая и почти что скучная (по крайней мере, по стандартам 2017 года).
Упрощённая схема основных частей, из которых состоит Unsplash
Мы используем Heroku везде, где это возможно, чтобы упрощать выкладку, конфигурирование, тестирование, поддержку и масштабирование наших основных приложений. Heroku — это какая-то магия, которая разделяет части приложения и процесса разработки так, что членам нашей команды не нужно быть знакомыми с ней, чтобы разрабатывать и выкладывать эксперименты.
Мы агрессивно минимизируем объём кода, который пишем для бизнес-логики приложения (фиолетовые области на картинке). При его написании мы активно используем фреймворки, созданные другими людьми, которые, являясь экспертами в своих областях, разработали решения, успешно работающие в 95% наших сценариев использования.
Мы активно используем в продакшене Redis, Elasticsearch и Postgres. В прошлом мы пробовали и другие базы данных, но всегда возвращались к этим трём, поскольку уверены в том, что понимаем, как они ведут себя под нагрузкой.
Также мы активно используем очереди задач, асинхронно обрабатывая множество операций, таких как обновление, агрегация и синхронизация данных между разными источниками.
Для обработки данных мы используем Snowplow, открытый интегрированный фреймворк, написанный на Scala, который избавляет нашу команду от необходимости думать об организации входа и выхода, а не о самой обработке.
Ещё мы используем целый набор облачных сервисов для мониторинга, таких как Datadog, New Relic, Sentry и Logentries, вместо того чтобы разворачивать и поддерживать собственный StatsD или ELK-стек.
Мы записываем все действия наших пользователей в сервис Stream, используя их опыт построения и оптимизации высоконагруженных персональных лент. Stream упрощает для нас обработку миллиардов действий и предоставляет простой API для входа и выхода, который работает с такой производительностью, на создание которой своими силами наша команда потратила бы месяцы, а то и годы.
Мы не тренируем алгоритмы распознавания изображений сами, а вместо этого используем TinEye для обратного поиска изображений и Google Vision для распознавания и классификации изображений.
Мы записываем все поведенческие события в Vero, платформу по работе с уведомлениями и почтовыми рассылками, что позволяет передать работу с ними в руки наших коллег, не являющихся разработчиками. Они сами могут создавать письма с высоким уровнем персонализации, основанном на сложном использовании имеющихся данных о поведении пользователей.
В то же время мы сосредотачиваем усилия на тех частях Unsplash, которые могут обеспечить улучшение нашей основной компетенции.
За последний год мы разделили наше единое приложение, написанное на Ruby on Rails, на Rails API, веб-приложение на Node.js + React и создали отдельное приложение по работе с данными, которое собирает и обрабатывает все наши внутренние и продуктовые метрики.
Это позволило нашей команде создавать функционал, который казался почти невозможным на нашем старом стеке, состоящем только из Rails. Разделив проблемы и технологии наших приложений, наша команда также получила возможность использовать лучшие инструменты в каждой из областей:
- На фронтенде мы используем React и Webpack вместе с небольшим сервером на Express для поддержки серверного рендеринга и проксирования запросов к API. Мы намеренно не стали привязывать инструменты нашей команды фронтенда к бэкенду временными хаками вроде react-rails или webpacker. JavaScript-сообщество, без сомнения, выпускает лучшие инструменты для работы с фронтендом, поэтому работа напрямую с JavaScript позволяет нашей команде быстрее доставлять до пользователей функционал высокого качества.
- На бекенде наша команда продолжает использовать лучший фреймворк для разработки простых web-приложений: Rails. Экосистема Ruby on Rails поставляет лучшие инструменты для функционала на стороне бекенда, и, поскольку этот фреймворк широко используется, любая проблема с ним уже найдена кем-то, документирована, и с большой долей вероятности для неё уже есть решение.
- На стороне работы с данными наша команда использует небольшой сервер на Express для сбора и организации обработки данных. Сама обработка происходит в Snowplow, который работает в кластере AWS, где для него есть готовые образы, упрощающие конфигурирование и развёртывание. Это позволяет нашему единственному дата-инженеру Тиму тратить большую часть времени на передачу данных в Snowplow и получение результатов оттуда таким образом, который делает их лёгкими для понимания и получения инсайтов остальными членами команды.
Мы активно занимаемся написанием тестов, измерением производительности с помощью таких инструментов, как Scientist и Datadog, раскладыванием изменений в виде экспериментов и максимально автоматизируем работу с нашей инфраструктурой.
Мы разрабатываем новый внутренний API на базе GraphQL для ускорения не зависящих друг от друга итераций экспериментов, новых фич и продуктов, так как мы поняли, что наш API на базе REST ломается без высокого уровня координации между командами данных, дизайна, фронтенда и бекенда — лучше мы будем тратить это время на фичи, а не изменения JSON.
Хотя над этими изменениями интересно работать, мы делаем их не потому, что нам хочется утолить свой программистский зуд, а потому, что это решает наши реальные проблемы, мешающие быстро доставлять функционал пользователям и развиваться.
Я думаю, что у большинства людей, дочитавших до этого места, в голове один из трёх выводов:
- Unsplash очень простой, поэтому вы и можете использовать этот подход. То, чем я занимаюсь, гораздо сложнее, поэтому мы вынуждены делать всё по-другому.
- Я разработчик. Это звучит очень скучно — я хочу заниматься созданием новой системы распознавания изображений с высокой нагрузкой!
- Круто! Мне всё равно, просто дайте мне красивые бесплатные фото, которые я могу использовать.
Люди с выводом №1, вы правы: есть компании, которые делают гораздо более сложные вещи, чем мы. Но их не так много. Мы все создаём такие же системы, но сфокусированные на немного других вещах, и это причина, по которой используемые решения могут быть абстрагированы в виде фреймворков и переиспользованы в разных проектах (поэтому большинство постов о найме так похожи друг на друга).
Люди с выводом №2, это зависит от того, что вы находите интересным. Если вам хочется раздвигать границы технологий, то идите работать в компанию, чья миссия — делать это. Их не так много, но большинство других компаний просто не занимается этим.
Людям с выводом №3 я скажу: «Да, совершенно верно!» В конце концов, это то, ради чего мы всё это и делаем.
Нам в Badoo близки принципы, про которые рассказывает автор. Главное отличие заключается в том, что наш проект гораздо больше и использовать внешние сервисы для нас зачастую очень дорого. При этом многие наши решения очень простые и мы стараемся аккуратно подходить к их изменениям, сравнивая стоимость внедрения и эксплуатации новой технологии с той пользой, которую мы от неё получим. Некоторые наши решения достаточно старомодны, поскольку были созданы довольно давно, но переход на аналогичные новые только ради моды не окупит затраченных на него ресурсов. При этом мы готовы внедрять новые технологии, если понимаем, что они способны принести реальную пользу (например, PHP 7, Go, Cassandra, Tarantool, Exasol).
Автор: Виктор