Цель — создание нового высоконагруженного стартапа в современных условиях. Создание архитектуры будем рассматривать на примере Billingolang — проект универсального биллинга, общего назначения, написанный на golang. Проект включает в себя доступ через API, сайт, интеграцию в бухгалтерские системы, отчеты и графики.

Изначально были откинуты однопоточные системы. Выбирать пришлось между Erlang, Golang и Rust. Основным языком программирования был выбран Golang, потому что найти программистов на Erlang сложно, хотя устойчивость и горячая замена кода шли в плюс Erlang. Rust, же не смотря на формальное отсутствие состояния гонки, все-таки более подходит не для написания приложений, но драйверов и операционных систем.

Обмен сообщениями между компонентами системы происходит не на классическом RabbitMQ, а на NATS — последний показал бенчмарки на сервере который сейчас используется, 1M сообщений (+360К при кластеризации) в секунду против 40К у зайца. Да и кластеризуется он быстрее и легче чем RabbitMQ.

База данных: MySQL InnoDB Сluster 7.6 (MySQL server 8.0). Шикарно верстается и отлаживается комьюнити средством MySQL Workbench.

API — пишется на Swagger (OpenAPI 2.0). Это позволяет избежать ошибок разными программистами, генерируется чистый хорошо документированный код и документация по API. К сожалению Swagger по умолчанию использует для рутинга gorilla/mux, но после генерации всего API, рутинг будет переделан на kataras/muxie — он быстрее.

Фронтенд: из доступных фреймворков: Iris, Beego и Revel — выбран Revel. Медленнее чем Iris, но все есть из коробки, включая интеграцию с графиками. Основную нагрузку все равно будет нести API.

Масштабирование: все компоненты системы собраны в LXC контейнерах, пока перед которыми стоит балансер HAProxy. Идея масштабирования сводится к тому, чтобы по мере увеличения клиентов последовательно переходить на более мощные сервера с сохранением структуры контейнеров, а в последствии разнести контейнера на отдельные сервера, заменив HAProxy на NATS. Кроме классического масштабирования «железом» всегда остается возможность внутри контейнеров-обработчиков запросов к API и сайту увеличивать количество goroutine. Хотя и этот процесс, как показала практика, имеет логические ограничения.

Вообще, основная мысль статьи и мое глубокое убеждение заключается в том, что начальную архитектуру высоконагруженных проектов, в современных условиях бессмысленно строить на однопоточных системах, несмотря на их годами развитую инфраструктуру и наличие большого количества доступных программистов. И всю схему проекта необходимо создавать изначально закладывая легкий перенос на более мощное и распределенное оборудование. Это позволит в будущем легко найти баланс между масштабированием «железом» и кодом, не увеличивая кратно расходы.

Обычная и самая распространенная ошибка новых стартапов — плохая начальная проработка архитектуры. По-принципу — «быстренько начнем писать, а потом разберемся». Как правило в последствии — это ведет к краху проекта.

Как говорится — «90% успеха — это подготовка». Не бойтесь потратится изначально на создание грамотной, продуманной архитектуры — это окупится сторицей.

Удачи!

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


  1. Vadem
    11.02.2019 19:24
    +12

    Обычная и самая распространенная ошибка новых стартапов — плохая начальная проработка архитектуры. По-принципу — «быстренько начнем писать, а потом разберемся». Как правило в последствии — это ведет к краху проекта.

    А можно узнать есть ли у вас какя-то статистика на этот счёт?
    Я в вопросе не очень разбираюсь, но неоднократно слышал, что причны провала стартапов не технические. Например, направильное понимание рынка, решение несуществующих проблем, плохоая модель монетизации и т.д.
    Т.е. архитектура проекта — это, конечно, хорошо, но на успех или неуспех стартапа влияет слабо.


    1. crmMaster
      11.02.2019 21:10
      +5

      Более того, оверинжиринг (хороший пример показан в статье) зачастую приводит к тому, что разработка mvp затягивается на какие — то неадекватные сроки из-за необходимости поддерживать все эти навороты.


      1. flamefork
        12.02.2019 20:03

        При том, что я сильно на стороне бизнеса (в противоположной от архитектурных стронафтов), не увидел в статье явного overengineering. Нормальная архитектура, не сильно сложнее ХХИВП, но заметно стабильнее.


        1. crmMaster
          12.02.2019 21:07

          Хотя на ровном месте, мускуль кластер, lxc вместо докера, выбор компонентов исходя из производительности, а не удобства, решение несуществующих проблем, введение технологий по принципу «чтобы было». Как это все вы называете? по мне так это классический оверинжиринг, — код писать ещё не начал, а инфраструктуру уже поддерживать надо.


          1. flamefork
            12.02.2019 21:49

            > мускуль кластер
            это что, сложно?

            > lxc вместо докера
            честно говоря, я под lxc подразумевал докер. если нет — зря

            > выбор компонентов исходя из производительности, а не удобства
            где?

            > решение несуществующих проблем, введение технологий по принципу «чтобы было»
            детали плз


            1. crmMaster
              13.02.2019 03:15

              > это что, сложно?
              Проблема не в кластере, проблема в мускуле. Вы выбрали базу, потому что у нее есть воркбенч. Выбирать базу исходя из инструментария, а не из из схемы хранения — считаете допустимо для «высоконагруженных» ситстем?

              > я под lxc подразумевал докер
              lxc != docker. Докер — это инструментарий для управления контейнерами. lxc — это технология, на которой не только докер основан. И вы что, автор чтобы что-то там подразумевать?

              > выбор компонентов исходя из производительности, а не удобства
              тут

              Обмен сообщениями между компонентами системы происходит не на классическом RabbitMQ, а на NATS — последний показал бенчмарки на сервере который сейчас используется, 1M сообщений (+360К при кластеризации) в секунду против 40К у зайца. Да и кластеризуется он быстрее и легче чем RabbitMQ.


              > решение несуществующих проблем
              Масштабирование: все компоненты системы собраны в LXC контейнерах, пока перед которыми стоит балансер HAProxy.

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

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


              1. flamefork
                13.02.2019 09:07

                > Вы выбрали базу
                Я?

                > считаете допустимо для «высоконагруженных» ситстем
                Возможно я излишне вольно трактую посыл автора статьи, но мне кажется нормальным выбрать достаточно универсальное мейнстримное решение на этапе, когда специфика проекта еще не выявлена. Я трактую примерно в духе «взять что-то, что в среднесрочной перспективе не доставит геморроя, при этом не тратя на это много времени». Честно не понимаю, где тут люди видят сложность и перенавороченность предлагаемого набора.

                > lxc != docker
                Я это прекрасно понимаю.

                > И вы что, автор чтобы что-то там подразумевать?
                Подразумевал при прочтении. Если автор имеет в виду именно голый LXC — соглашусь, зря он так.

                > выбор компонентов исходя из производительности, а не удобства
                > Да и кластеризуется он быстрее и легче чем RabbitMQ.
                Ээээ


                1. crmMaster
                  13.02.2019 12:21

                  > мне кажется нормальным выбрать достаточно универсальное мейнстримное решение на этапе, когда специфика проекта еще не выявлена.

                  Ну если вам кажется что базу надо выбирать исходя из «универсальности» и «мейнстримности», а не исходя из организации хранения, миграций, надежности, необходимых типов данных и прочих технических требований к нагруженным системам, то пусть кажется дальше. Только не лезьте, пожалуйста в вопросы в которых вы не компетентны.

                  > Ээээ
                  Что эээ? Вы привели цитату где человек решает несуществующую проблему. Как это опровергает мою цитату, поясните, пожалуйста.


                  1. flamefork
                    13.02.2019 14:09

                    > и прочих технических требований к нагруженным системам
                    Обычно на начальном этапе _технических_ требований почти никаких, и надо чтобы оно просто работало и не создавало геморрой.

                    > Только не лезьте, пожалуйста в вопросы в которых вы не компетентны.
                    Хехе, забавный вывод, оставлю без комментариев.

                    > разработка mvp затягивается на какие — то неадекватные сроки
                    > выбор компонентов исходя из производительности, а не удобства
                    а теперь вы мне доказываете что на этапе mvp надо выбирать исходя из производительности? где логика? и где логика в том, что вы критикуете выбор NATS как выбор исходя из производительности, при том, что автор указал, что и по удобству ему NATS кажется более предпочтительным


    1. rumatakira Автор
      12.02.2019 15:59

      чтобы нам понять друг друга, надо ввести временные, а еще точнее этапные горизонты. На горизонте стартапа — вы правы однозначно. А вот на горизонте, когда это уже проект в продакшене — я видел прекрасные проекты, которые умирали из-за архитектуры. Становились не рентабельны и легко обходились конкурентами.


      1. crmMaster
        13.02.2019 12:39

        Так может потому и становились нерентабельны, из-за того, что там, где мог бы справиться один программист нужно было держать армию девопсов и системщиков, чтобы поддерживать оверинжирнутую архитектуру?


  1. Vadem
    11.02.2019 19:29
    +10

    И ещё вопрос.
    Почему вы считаете представленную архитектуру удачной?
    (хотя мне кажется, что это не архитектура вовсе, а просто набор технологий)


    1. rumatakira Автор
      12.02.2019 16:00

      а что по вашему IT архитектура, если не набор технологий — картинка с домом?))


      1. Regis
        12.02.2019 16:53
        +1

        Часто под архитектурой системы подразумевает разбиение всей системы на компоненты, определение правил взаимодействия между компонентами. Выбор конкретной технологии для реализации компонентов и связей — тоже часть архитектуры, но это уже второй шаг (хоть и тесно связан с первым).

        Если проводить аналогию со строительством, то вы вместо плана здания составили список возможных материалов для использования.

        Фактически вы взяли уже готовую архитектуру проекта Billingolang и заменили в ней используемые части. Исследование интересное, но как-то неправильно называть это «созданием архитектуры».


        1. flamefork
          12.02.2019 20:09

          Скорее соглашусь, но и здесь описаны детали и в аналогии со строительством есть «типовые» для материалов подходы и архитектуры: кирпичный дом vs панельный vs современный мейнстрим (железобетонный каркас + кирпичные стены): материалы определяют архитектуру и походы.


    1. rumatakira Автор
      12.02.2019 16:08

      почему удачной — потому что она быстрее из всех других перепробованных 6 моделей. И не дорога как в создании, так и в обслуживании.


  1. werklop
    11.02.2019 20:11
    +6

    Архитектура — это не про перечисление используемых языков/фреймворков, а про взаимосвязь компонентов. Компонентами могут быть как элементы бизнес-процессов в общем виде, так и модули/интерфейсы в более конкретном виде.


    1. rumatakira Автор
      12.02.2019 16:02
      -2

      частично соглашусь. Архитектура — это и компоненты и взаимосвязи между ними. Но при таком наборе компонентов — взаимосвязи очевидны.


      1. andreyons
        12.02.2019 16:06

        Кому? Мне, как читателю, не совсем понятно. Был бы рад почитать какие именно проблемы вы решали и как. Дело бы было :)


  1. alemiks
    11.02.2019 20:54
    +8

    откуда в стартапе 1млн сообщений в секунду? На то он и стартап, что его ещё нету (0 сообщений в секунду).

    это ведет к краху проекта

    имхо, к краху проекта ведёт его бесполезность для пользователей, а не какой-нибудь выбор Python vs Go

    Рекомендую Getting Real, в общем :)


  1. smarthomeblog
    11.02.2019 21:00
    +3

    На самом деле, это просто наметки какие-то, а не архитектура. И да, к краху стартапа ведет прежде всего бизнесовые просчеты — неспособность продать пусть даже невостребованный сервис, или неспособность найти инвесторов. А технические проблемы будут в любом случае. Как бы не продумывали архитектуру.


  1. berezuev
    11.02.2019 21:23
    +4

    Символичнее всего то, что при всех технических наворотах в репозитории нет ни строчки кода.
    Болтать — не мешки ворочить…


    1. rumatakira Автор
      12.02.2019 15:48

      Это не opensource проект. Код лежит там где ему положено лежать — подальше от чужих глаз.


  1. crmMaster
    11.02.2019 21:23
    +1

    Мускуль, lxc контейнеры, масштабирование горутинами. Не знаю, какая у вас нагрузка, но когда она станет действительно высокой, вас ждут сюрпризы. Хотя один с горутинами вы уже обнаружили.


  1. KirEv
    11.02.2019 23:02
    +2

    стартап на то и стартап, чтобы быстро начать, реализовать первые фичи, и т.п… пока все обдумается и архитектура построится — идея станет не актуальной, или ктото перед вами займет этот стул…

    Обычная и самая распространенная ошибка новых стартапов ...

    … не стартапом единым… а вообще, самая распространенная ошибка — решать проблемы которых не существует…
    На предыдущей работе была задача сделать последовательную очередь обработки данных (golang):
    1. массив структур через канал заполняется данными одной горутиной
    2. другая горутина постепенно выбырает данные по таймауту
    3. самому главному программисту\со-овнеру показалось, что это класическая очередь, начали городить сначала Redis + RabbitMQ, потом уговорил их что редиса достаточно (хотя по факту ни то ни другое не нужно)
    4. основной аргумент главного в пользу редиса+ребита, внимание: мы не хотим показаться лохами, нужно заюзать крутые технологии… (дословно из чата)… понятно да?
    5. самое интересное, чуть позже кейс изменился, из пачки данных (то что в стеке), нужно было выбрать сначала самые свежие… и все что строилось пришлось выбросить и сделать как полагалось изначально: тупая структура с 3мя методами (читать, писать, взять первый), на ребит, в пустую, ушло 2 недели (!!!)… потому что решали выдуманые задачи…

    так и с масштабированием или предвременной оптимизацией бывает…

    PS: а архитектуры в статье так и не увидел… вы бы потрудились хотя бы на схеме проиллюстрировать.


    1. rumatakira Автор
      12.02.2019 15:54
      -2

      Не обижайтесь, но я не виноват, что ваш мозг в основном использует визуальное мышление, а мой звуковое. Архитектура там вся перечислена, некоторые взаимосвязи просто логически вытекают из этого перечисления. Попробуйте ПРОЧИТАТЬ, а не ВЗГЛЯНУТЬ.


  1. LooMaclin
    12.02.2019 11:31
    +1

    Rust, же не смотря на формальное отсутствие состояния гонки, все-таки более подходит не для написания приложений, но драйверов и операционных систем.

    Не совсем понимаю, почему вы так считаете. Аргументируйте это пожалуйста. Потому что на мой взгляд это не так и вот почему:
    1) Rust подходит для разработки во многих других областях, помимо написание драйверов и операционных систем. Для того, чтобы убедиться в этом, можно взглянуть, какие компании используют его: https://www.rust-lang.org/production/users. У него есть все необходимые инструменты для этого.
    2) Хорошая статья с более подробной аргументацией: https://habr.com/en/post/434200/
    Просто оставлю здесь цитату:


    Концепции раста очень мощные, и отлично работают на уровне прикладных приложений, которые не задумываются о производительности, но скорее только о продуктивности разработчиков, скорости внедрения новых фич и простоты поддержки. Очень грустно наблюдать, что такой отличный во всех отношениях язык всё больше получает клеймо "странного и сложного языка для низкоуровневых гиковских задач". Надеюсь, я немного пошатнул этот вредный миф, и в мире станет на сколько-то более продуктивных и счастливых разработиков больше.

    3) В нашей компании успешно используется Rust в продакшене, и это не разработка ОС и драйверов. И используется не в стиле "написали утилиту небольшую", это огромнейший кусок серверной части.


    1. rumatakira Автор
      12.02.2019 15:43
      +2

      На самом деле — вы правы. Rust даже мне изначально легче заходил. И написать на нем можно все. Но для стартапа приложения — выгоднее использовать Golang. Больше инфраструктура, больше программистов, ниже себестоимость процесса.


  1. danyanya
    12.02.2019 15:43
    +1

    Изначально были откинуты однопоточные системы. Выбирать пришлось между Erlang, Golang и Rust.


    1. Это не системы, а языки
    2. Выбирать пришлось явно не из-за ограниченности остальных ЯПов. Можно было сразу написать — проект написан на Golang


    1. rumatakira Автор
      12.02.2019 15:56

      язык + инфраструктура = система


  1. otetz
    12.02.2019 15:49
    +1

    рутинг будет переделан на kataras/muxie — он в два раза быстрее.
    Обратите внимание на минимальное значение вертикальной оси на графиках. Не в 2 раза быстрее, а примерно на 5-10%.


    1. rumatakira Автор
      12.02.2019 16:04

      да вы правы — My mistake…