Привет, ребята. Меня зовут Павел, я сооснователь сервиса Codesign и отвечаю за его техническую составляющую. Codesign – это веб-сервис для создания и обсуждения обратной связи при работе над веб-сайтами, дизайн-макетами и презентациями. Если вам дизайнеры по-прежнему пишут правки по верстке сплошным текстом в письме, то пора завязывать и переходить на Codesign.

Мы запустили сервис 22 июля 2015 года и с тех пор набрали 3500 зарегистрированных пользователей, пережили запуск на ProductHunt, когда к нам зашло 10 000 человек за 36 часов, получили своих первых платных пользователей и обсуждаем получение финансирования от европейских (я живу в Италии) инвесторов. В этой статье я расскажу, как мы построили архитектуру сервиса и организовали процесс разработки.



Frameworks


При разработке Codesign мы стремились к модульности, посчитав что в этом случае легче будет вносить правки и заменять один блок другим. Первым серьезным решением было полное разделение API и веб-приложения, таким образом, что они работают на разных серверах. Так как у команды был опыт с Python / Django, было решено построить API на основе Django Rest Framework. Веб-приложение мы первоначально планировали писать на AngularJS, но нанятый front-end разработчик убедил нас реализовывать на React. Серверная сторона веб-приложения реализована с использованием фреймворка Express на Node.js.

Deployment


По причине того, что мы хотели как можно меньше времени тратить на настройку серверов и иметь возможность быстро масштабироваться (в случае если мы ожидаем большой скачок трафика, например после публикации на популярном ресурсе) мы решили разворачивать наш код на Heroku. Таким образом на Heroku мы имеем 2 сервера для API (production / development) и 2 сервера для веб-приложения (production / development). В Heroku на бесплатном тарифе сервер засыпает каждый час и должен быть не активным более 6 часов в сутки. У меня было несколько серверов поднятых несколько месяцев до появления новых тарифов, и на них этого ограничения нет. Веб-приложение и API работают на бесплатных серверах, которые мы периодически масштабируем, когда ожидаем наплыв трафика. Основным плюсом Heroku я считаю простоту развертывания и его GIT основу, которая позволяет автоматически деплоить код из Github. Этот процесс более подробно описан ниже.

Database


В Heroku есть большое количество различных подключаемых плагинов, среди которых есть так же системы управления базами данных (СУБД). До релиза 22-го июля у нас был прототип использующий MySQL и мы решили продолжить работать в рамках этой СУБД и подключили ClearDB. Бесплатный тариф имеет ограничение базы данных в 5МБ, таким образом мы сперва перешли на тариф Punch, а далее Drift за $50 в месяц. Сейчас ClearDB самая дорогая составляющая из технологических сервисов (дороже только Intercom, но я не говорю о нем в этой статье) за которые мы платим. Я считал что $50 в месяц это дорого и считал что на Amazon RDS я получу выше производительность за те же деньги. Проведя ряд экспериментов я понял, что это не так, ибо аналогичную скорость выполнения запросов я получал только на RDS инстансах, которые стоят дороже $50, таким образом мы остались с ClearDB.

Storage


Основу Codesign составляют графические файлы, которые пользователи загружают для дальнейшего обсуждения. Здесь мы не вели долгого обсуждения и остановились на Amazon S3, где при нашем трафике и количестве хранимых картинок мы платим $3-4 в месяц. На медленном интернете загрузка картинок свыше 4МБ занимала более 30 секунд и возникала timeout ошибка от Heroku. Чтобы решить эту проблему, мы стали на сервере только генерировать специальную ссылку, по которой можно загружать картинки напрямую в Amazon S3 из браузера. Так проблема была решена.

Notifications


Когда один пользователь внес изменения в борд (коллекцию картинок для обсуждения) на Codesign, то другие участники этого борда получают уведомления. Для реализации этих уведомлений мы используем два сервиса: Heroku task scheduler для инициализации отправки уведомлений каждый час, и Mandrill для отправки писем как таковых.

Monitoring


Django сам по себе позволяет отправлять отчеты об 500-х ошибках возникающих на сервере. Это удобно. Но еще более удобным оказался сервис Opbeat. Он собирает информацию по ошибкам, показывает статистику их возникновения, назначает каждую группу ошибок на человека, который закоммитил код, в котором возникла эта ошибка. Помимо этого Opbeat мониторит запросы к серверу и показывает узкие места с производительностью. Существует много аналогичных сервисов, но Opbeat подкупил своей простотой и бесплатностью до 3х пользователей. Однажды у нас возникла проблема с тем, что endpoint на получение списка бордов в папке выполнялся 4 секунды. Мы не могли понять в чем конкретно проблема. Opbeat показал, что мы очень неоптимально делаем запросы для проверки прав пользователей. Мы оптимизировали код и исполнение endpointа ускорилось в 20 раз.



Development


Наша разработка в настоящий момент полностью построена на GIT:
  1. Сперва разработчик вносит изменения и загружает код в development ветку в Github. В master ветку в Github напрямую пушить код невозможно, это запрещено в настройках репозитория.
  2. В этот момент срабатывает webhook и код репозитория переразворачивается на development сервере Heroku.
  3. Убедившись что код работает адекватно, мы создаем pull request в master ветку, при принятии которого код автоматически отправляется на production сервер Heroku. Если что-то пошло не так и была найдена какая-то ошибка, то Heroku позволяет очень легко делать откаты на предыдущие версии.



Будущее


Далее мы планируем внедрить следующие инструменты:
  • Heroku review apps – для параллельного тестирования разных фич отдельно следуя git flow (сейчас у нас только один development сервер)
  • Travis – для запуска unit тестов при каждом push на Github
  • CodeClimate – для автоматического анализа кода (приведет к высокому качеству кода)
  • Amazon RDS – когда нам не будет хватать тарифов, которые предлагает ClearDB будет необходимо разворачивать более мощные RDS инстансы
  • Firebase – для реализации real time обновления некоторых блоков
  • Stripe – для приема платежей (сейчас используется Gumroad)


Заключение


Данная статья это пример того, как различные сторонние сервисы могут быть интегрированы для упрощения работы над собственным продуктом. К архитектуре, которую вы видите в этой статье мы пришли не сразу, а постепенно – методом проб и ошибок. Мы не претендуем и не агитируем на то, что данная архитектура является идеальной. Мы открыты для обсуждения и будем очень рады услышать обратную связь по архитектуре, которую мы используем.

Если вам нравится Codesign (или не нравится и вы хотите его изменить), приходите работать к нам — у нас открыты 4 удаленные вакансии.

Комментарии (18)


  1. StopDesign
    23.11.2015 12:21
    +1

    Это какой-то тренировочный проект «собрать продукт без единого гвоздя на сервисах»?
    Я не понимаю, чем эта сложная архитектура лучше виртуалки за 5 баксов при такой нагрузке.


    1. pavelk2
      23.11.2015 12:28

      Это не тренеровочный проект. Мы ориентируемся на масштабируемость и пытаемся не создавать свои велосипеды, а использовать существующие зарекомендовавшие себя решения. Запуск «виртуалки» за $5 может в текущем варианте заменить разве что Heroku. При этом Heroku позволяет нам полностью избежать настройки сервером и сфокусироваться на коде. Даже если мы говорим о такой простой вещи как база данных — работа с сервисом, который за нас делает масштабирование, бэкапы и т.д. — очень удобно. Полагаю что ответ на ваш вопрос — это весь контент статьи.


      1. f0rk
        23.11.2015 12:42
        +1

        У heroku есть минус по сравнению с aws elasticbeanstalk, с heroku сложно спрыгнуть, если вам потребуется больше гибкости в настройке инфраструктуры. С EB проще переехать на clouformation, codedeploy, и прочую aws инфраструктуру, т.к. по сути EB — это всего лишь надстройка над этими вещами, а устройство heroku — дело темное.

        PS Ну и цена — тоже немаловажный фактор.


        1. pavelk2
          23.11.2015 12:47

          Спасибо за комментарий и совет. В настоящий момент возможности Heroku + доступных плагинов удовлетворяют нашим потребностям. Главная причина в самом начале при выборе Heroku — был позитивный опыт работы с ним. Буду рад более детально изучить разницу с ElasticBeansTalk.


      1. StopDesign
        23.11.2015 12:53
        -1

        На виртуалке за 5$ есть cron — это ведь как Heroku task scheduler?
        И там можно поставить СУБД, даже не только MySQL. Вопрос с бэкапами в 2015-м году, вроде бы, понятно как решать. Кроме того, восстановление из бэкапов — это в любом случае не так легко, т.к. есть отдельные бэкапы на базу и файлы.
        Django debug toolbar, известный любому Django-разработчику, решает вопрос с отслеживанием таймлайна запросов к БД.
        В качестве журнала ошибок я обычно Sentry использую. Там есть интерфейсы практически для всего (и бэкенд, и фронтенд).

        Да, вы избежали настройки сервера, но получили настройку шести сервисов и зависимость от них. Хотелось бы понять, много ли на этом можно выиграть/проиграть.

        Масштабирование — это хорошо, но вы считали, сколько будет стоить эта инфраструктура при нормальной нагрузке?


        1. pavelk2
          23.11.2015 12:57
          +1

          Начнем с того, что как и указано в заключении — мы не агитируем что подобная архитектура — идеальное решение для всех. В нашем случае было решено, что оплата сервисов + масштабирование обойдутся дешевле чем ЗП devops специалиста.


    1. f0rk
      23.11.2015 12:39
      +1

      Я бы не сказал, что тут совсем уж без гвоздей обошлось. Все таки как минимум два приложения крутится. У меня, кстати, была идея собрать какой-нибудь простенький проект исключительно на сервисах AWS (api, lambda, s3, и т.д.). Мне кажется, неплохая идея для статьи :)


      1. pavelk2
        23.11.2015 12:42

        Совершенно верно. Много современных проектов работают на различных сервисах AWS + сторонние инструменты. Считаю что это вполне адекватная практика!


  1. sergebezborodov
    23.11.2015 16:15
    +3

    молодцы, что разобрались с такой кучей всего
    но 10000 визитов за 36 часов — это 4.62 визита в минуту, это как бы не та нагрузка, чтобы задумываться о масштабировании


    1. pavelk2
      23.11.2015 16:23

      Спасибо! 10 000 визитов за 36 часов пришли не равномерно (поэтому не 4.62 в минуту). В любом случае я полностью согласен что это не серьезный уровень нагрузки. В любом случае тогда у нас возникали ситуации, когда 90 человек одновременно пользовались сайтом и поступало довольно много запросов (при этом все равно конкурентность запросов в секунду была не высока).


      1. sergebezborodov
        23.11.2015 16:29
        +1

        мы тоже активно пользуемся сторонними сервисами в проекте, но главный принцип, база и код — у себя, не потому что там не секурно и проч, а в первую очередь при возникновении каких либо нештатных ситуаций всегда можно зайти под рутом, грепнуть лог рестартануть демон, большая свобода для конфигурирования и экспериментов.
        а все остальное — без проблем, datadoghq.com — для мониторинга серверов, rollbar.com — для мониторинга ошибок, power bi для отчетов и т.п.


        1. pavelk2
          23.11.2015 16:33

          Хороший совет по БД и коду. Спасибо большое за обзор ваших сервисов — смотрю их сейчас. powerbi.microsoft.com — очень интересно — не знал о нем, мы искали подобный ресурс!


  1. Holms
    23.11.2015 21:10

    подскажите как разработчик убедил вас в этом
    «но нанятый front-end разработчик убедил нас реализовывать на React»
    Спасибо


    1. pavelk2
      23.11.2015 21:16

      Технически front-end Codesign.io можно реализовать на Angular, React, Ember или любом другом фреймворке. Наш интерфейс не настолько сложен, что какие-то подошли бы принципиально лучше других. Выбор был между Angular и React. На тот момент готовилась к выходу новая версия Angular, которая значительно отличается от предыдущей что потенциально вело к тому, что для того, чтобы быть на последней версии фреймфорка нам бы пришлось значительно переделать код. У меня были сомнения касательно community — я считал что она больше у Angular, ибо в тот момент я не был сильно знаком с React. Оказалось что community у React не меньше и растет быстрее. Дальнейшие консультации со знакомыми топовыми front-end разработчиками так же сыграли в пользу React.


  1. Jimilian
    23.11.2015 23:34

    Спасибо за статью, я тоже наблюдаю, как всё больше компаний уходит в облака, чтобы не заниматься поддержкой серверов, бэкапов и так далее, а сконцентрироваться только на фичах. Хотя мне это не всегда понятно, т.к. стоимость (в данном случае з/п) установки и интеграции некоторых OpenSource решений вполне сопоставима с годовой стоимостью сервисов. Но с точки зрения индустрии это объяснимо — не всегда есть деньги купить экспертизу или время на выращивание эксперта.

    В связи с этим вопрос, Вы, наверняка, делали какие-то вычисления стоимости использования различных сервисов, в зависимости от базы пользователей, не могли бы поделиться с сообществом?


    1. pavelk2
      24.11.2015 12:26

      Прекрасный вопрос. Мы исходили из идеологии, что нам нужно создать архитектуру, которая поможет проекту выйти на определенный уровень. Мы не надеялись, что текущая архитектура будет актуальна при 1 млн пользователей, но нам было важно, чтобы текущая архитектура позволила нам без больших проблем обслуживать 50 -100 тыс пользователей. При этом в самом начале стоимость сервисов очень не высока — около 50$ за все (для того чтобы начать). В настоящий момент (почти 4000 пользователей) мы тратим на сервисы около 220$. Сейчас у нас пока нет сторонних денег и нам требуется развиваться очень экономно. Далее когда у нас будет 10000 пользователей у нас так же будут сторонние деньги на то, чтобы платить за более дорогие тарифы и наши расходы на сервисы составят 500$+. При 50 000 пользователях расходы будут чуть менее 1000$. Должен уточнить, что эти суммы не напрямую связаны с количеством пользователей а с нашей платежеспособностью. Если сейчас мы пока не платим за Github и пользуемся моим студенческим аккаунтом аспиранта — далее нам придется за него платить. Если сейчас мы не создаем ряда приложений в heroku для тестирования отдельных фич, а имеем только одно приложение для тестирования всего, то позже мы будем готовы расширить нашу инфраструктуру. В будущем нам нужно будет создать реплики серверов в США и Японии для того, чтобы был хороший пинг вне зависимости от того, где находится пользователь. Важно помнить что не все сервисы напрямую связаны с развертыванием. Сейчас половина денег, которую мы платим за сервисы это Intercom — для общения с пользователями.


  1. bytecode_rus
    24.11.2015 07:55
    +2

    Не знаю, насколько это вам поможет, но я прочитал codesign как code-sign, а не как co-design.


    1. pavelk2
      24.11.2015 12:28

      Спасибо. Да у нас есть такая проблема, что те кто ближе к разработке читают название как code-sign. Будем больше знакомить массы с брендом и надеемся что двойственность уйдет + выделение «design» в лого.