Техническая сторона Supl.biz

    Добрый день. Меня зовут Алексей Красноперов и я являюсь основателем и техническим директором проекта Supl.biz — торговой площадки для малого и среднего бизнеса. Хочу рассказать, как устроен проект изнутри.

    Общая архитектура проекта


    Техническая сторона Supl.biz


    В основе проекта используются популярные фреймворки Django и AngularJS. Причём, чтобы добавить проекту остроты, фронтенд реализован как Single Page Application, на сервере использован python 3.4, а вся статика выложена в CDN.

    Как ни странно, такой выбор технологий не добавил проблем при использовании сайта. Для индексации поисковиками применяется генерация страниц на сервере через PhantomJS. В результате и Google, и Яндекс отлично индексируют проект.

    В качестве основного хранилища данных используется PostgreSQL 9.4. Также данные выгружаются в ElasticSearch для быстрого поиска и построения статистических отчётов.

    За отправку писем отвечает отдельный пул Postfix серверов. Для нормальной доставляемости писем потребовалось настроить почтовые домены: SPF/DKIM/PTR, а также правильно оформлять технические заголовки писем. В результате есть возможность отслеживать статус доставки каждого отдельного письма и чистить рассылку от неактивных пользователей.

    Триггерная рассылка писем на основе поведения пользователей реализована с помощью Mixpanel. Это позволило увеличить вовлечённость аудитории, не тратя времени на разработку сложного функционала.

    Сервисы Postmaster@mail.ru и Яндекс.Почтовый офис предоставляют статистику о почтовых рассылках. А Feedback Loop позволяет узнавать, какие письма пользователи отправляют в спам и делать выводы.

    Инфраструктура


    Проект развёрнут в облаке Selectel в Санкт-Петербурге. Используются как облачные серверы, так и CDN для статики и пользовательских файлов. Облачная основа проекта позволяет вводить в строй новые серверы и масштабировать проект под текущую нагрузку.

    На данный момент сайт размещается на одном сервере, этого достаточно для обработки 400 000 посещений в день.

    Selectel, кроме прочего, предоставляет детальные отчёты по потребляемым ресурсам. Нет необходимости настраивать собственный мониторинг.

    Для управления серверами используется Ansible: развёртывание, введение в строй новых серверов и обновление проекта — автоматизированы и запускаются в одну команду.

    Разработка


    Окружение разработчика максимально приближено к реальному окружению, в котором работает сайт. Для этого миниатюрная копия проекта развёрнута в виртуальной машине Vagrant. Это сводит к минимуму проблемы от различия окружений. К тому же нового разработчика можно ввести в проект всего за один час.

    Для разработки применяется Git Workflow. Исходный код хранится в Git на Bitbucket. Новый функционал реализуется и тестируется в отдельных ветках, затем сливается в основную ветвь проекта.

    На проекте настроен Continuous Deployment: каждый релиз автоматически публикуется и тестируется в песочнице. Если всё отлично — запускается публикация на рабочий сайт. В день, незаметно для пользователей, публикуется порядка пяти изменений сайта.

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

    Развитие


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

    Ведутся работы по локализации сайта и выводу проекта за пределы России и СНГ.

    Планируется запуск мобильного приложения: сайт AngularJS отлично запаковывается в приложение с помощью PhoneGap. Практическая возможность проверена, остаётся поправить UI для отображения на небольших экранах и можно запускать.

    P.S.


    Проект был реализован и запущен моими силами. С ноября 2014 г. к разработке присоединилась замечательный разработчик Татьяна и уже успела внести свой вклад. Но мне нужны еще светлые головы для дальнейшего развития проекта. Приглашаю присоединиться к нашей команде.
    Supl.biz
    31,00
    Компания
    Поделиться публикацией

    Похожие публикации

    Комментарии 30

      +3
      А при помощи чего вы диаграму рисовали?
      +2
      Здравствуйте) просто небольшой совет к вашему сайту: оберните вызов отображения прогрессбара ajax-загрузки страницы в setTimeout, чтобы он появлялся только тогда, когда сайт простаивает в ожидании данных больше, скажем, секунды, или двух секунд. Чтобы постоянно эта полоска загрузки не появлялась, при каждом клике, и не раздражала пользователей) По большей части, этот прогресс бар вообще не нужен, если сайт отвечает достаточно быстро. А вот когда сайт вдруг начнёт долго ждать ответа, то логично будет показать ему эту полосу загрузки.
        0
        Спасибо. Я полностью с Вами согласен. Рано или поздно это будет реализовано.

        Но тут важно понимать как мы расставляем приоритеты задач: мы задаём вопрос «Как это влияет на основные показатели?»
        В итоге в первую очередь реализуем то, что требуется для роста проекта и его монетизации. Lean startup в чистом виде.

          +1
          Вот так это сделано в одном моём проекте: gist.github.com/believer-ufa/5eb9feb93c1298f48eb3
          У меня анимация включается через 800 миллисекунд, большинство запросов отрабатывает меньше этого времени, и обычно прогресс-бар не появляется)
            +1
            на сайте используется ангулар-модуль ngProgressLite (https://github.com/voronianski/ngprogress-lite). Не знаю насчет кастомизации, документация не выглядит достаточно полной.

            Мы используем практически везде angular-loading-bar (https://github.com/chieffancypants/angular-loading-bar). Он сам запускается при http-запросах после 100 мс. Можно задать и большую границу при конфигурации приложения, все очень удобно.
        +1
        Вот если бы не хабр — я бы про вас не узнал...)
          +1
          Расскажите про celery немного — профиль использования, ваши «best practices» по проблемам?
            0
            Кратко:
            1. В стандартной поставке celery уже хорош. Я доволен и не ищу «легковесных» альтернатив.
            2. Обязательно нужен веб-мониторинг celery flower. Когда какая-нибудь задача сходит с ума и забивает все рабочие процессы — только так можно быстро всё наладить.
            3. Приоритетов задач в celery нет, но они нужны. Помогает запуск нескольких сервисов celery с различными очередями. Приоритетные и важные задачи отправляются в одну очередь, медленные и неприоритетные — в другую. В результате задачи не блокируют друг друга.
            4. В качестве очереди задач в теории можно использовать Redis, но стабильно у меня работает только RabbitMQ.
            +2
            Какая симпатичная у вас разработчик! ;-)
              +3
              Вы бы слышали как она поёт джаз :)
              www.youtube.com/watch?v=ktqe9ZoDl7E
                +2
                Не, так не бывает
                  0
                  Передам Татьяне, что её не существует :)
              +3
              А про RabbittMQ расскажите плиз для человека, ничего в этом не понимающего — чем подробнее, тем лучше. Интересно реальное применение таких штук.
                0
                При текущей нагрузке проекта — RabbitMQ не более чем клей между django и celery. Настраивается однажды по документации, обслуживания не требует.

                Если возникают проблемы с выполнением фоновых задач, то они в самих задачах, а не в транспорте нескольких сообщений между серверами.
                +1
                Очень интересует, как вы так часто обновляете проект на рабочем сервере и пользователи этого не замечают? Насколько мне известно, после обновления рабочей копии сервера его нужно перезапустить, а это автоматом отключает всех пользователей на время перезапуска. Это для вас приемлемо или вы как-то по-другому решаете эту проблему?
                  0
                  На проекте настроено обновление с нулевым простоем серверов. Детально расписывать — получится отдельная статья. Если кратко:

                  1. Пока перезапускается процесс uwsgi — запросы ждут в очереди, либо уходят на другой сервер
                  2. Версия кода на сервере строго связана с версией скриптов и стилей (чтобы не получилась новая разметка со старыми стилями)
                  3. Так как миграция схемы БД выполняется до перезапуска сервера, то старый код должен уметь работать с новой версией схемы БД.


                  Не все изменения можно выложить на проект при таком подходе. В таких случаях — обновление производится по ночам или субботам с остановкой работы проекта.
                    +1
                    Спасибо, как-то даже не задумывался о перенаправлении запросов на другой сервер)
                    +1
                    Так как я деплою django проекты через uwsgi, могу порекомендовать к прочтению это — там описано несколько различных способов.
                      +1
                      Пресного благодарен, полезная статья
                        +1
                        По этой статье и сделано
                      +1
                      почему memcached в качестве кеша не выбрали?
                        0
                        Memcached никогда не освобождает занятую память, в отличии от Redis. В облачном окружении это превращается в финасовые потери на пустом месте.

                        Выбор делал достаточно давно — с тех пор что-то могло поменяться.
                        +2
                        А почему не использовали полнотекстный поиск из Postgres? Он ещё быстрее, при стандартных usecase не надо отдельно стучаться в другую БД, можно делать join с результатами поиска и т.д.
                          0
                          Просто полнотекстового поиска недостаточно. Нужен полнотекстовый префиксный поиск с учётом морфологии.
                          Так же требуется агрегировать данные для отчётов (например, нам интересно знать динамику размещения и выполнения заказов по рубрикам и регионам)

                          Всё это можно сделать на PostgreSQL. Первое решение как раз было реализовано на PostgreSQL, но работало достаточно медленно и серьёзно нагружало CPU. Можно основательно разобраться в документации, правильно настроить индексы и написать оптимальные запросы. Но сколько это займёт времени и будет ли результат — мне сложно сказать.

                          С другой стороны — в ElasticSearch достаточно просто выгрузить данные и тут же получить результат. Что и было сделано.
                          +1
                          Да, мне тоже лишним показался Эластик. В свое время отказались от него, в пользу больших плоских таблиц в БД. Меньше компонентов, меньше рисков, прозрачней архитектура, и java эта, оххххх, сколько же она жралаааа ram.
                          Еще я бы postfix на exim4 заменил, он шибко быстрей и стабильней.

                          А так всё круто. Схемку себе утащил, сам подобные периодически в draw.io калякаю, буду активно размышлять над ней. У мну правда стек технологий другой (backbone.js / jquery / php-fpm / percona db / memcached / nginx).

                          Не поделитесь инфой, сколько все это дело жрет под нагрузкой ram, какая нагрузка, сколько весит БД, сколько платите «за свет» )
                          Надеюсь, не сильно обнаглел ?)
                          0
                          optio можно попросить вас не красить блоки в оранжевый при наведении? Просто при длительном просмотре сайта от этого начинает болеть голова(

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое