Создание архитектуры для нового высоконагруженного стартапа в 2019

Цель — создание нового высоконагруженного стартапа в современных условиях. Создание архитектуры будем рассматривать на примере 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% успеха — это подготовка». Не бойтесь потратится изначально на создание грамотной, продуманной архитектуры — это окупится сторицей.

Удачи!
Поделиться публикацией

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

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

    А можно узнать есть ли у вас какя-то статистика на этот счёт?
    Я в вопросе не очень разбираюсь, но неоднократно слышал, что причны провала стартапов не технические. Например, направильное понимание рынка, решение несуществующих проблем, плохоая модель монетизации и т.д.
    Т.е. архитектура проекта — это, конечно, хорошо, но на успех или неуспех стартапа влияет слабо.
      +9
      Более того, оверинжиринг (хороший пример показан в статье) зачастую приводит к тому, что разработка mvp затягивается на какие — то неадекватные сроки из-за необходимости поддерживать все эти навороты.
        0
        При том, что я сильно на стороне бизнеса (в противоположной от архитектурных стронафтов), не увидел в статье явного overengineering. Нормальная архитектура, не сильно сложнее ХХИВП, но заметно стабильнее.
          +1
          Хотя на ровном месте, мускуль кластер, lxc вместо докера, выбор компонентов исходя из производительности, а не удобства, решение несуществующих проблем, введение технологий по принципу «чтобы было». Как это все вы называете? по мне так это классический оверинжиринг, — код писать ещё не начал, а инфраструктуру уже поддерживать надо.
            0
            > мускуль кластер
            это что, сложно?

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

                    > разработка mvp затягивается на какие — то неадекватные сроки
                    > выбор компонентов исходя из производительности, а не удобства
                    а теперь вы мне доказываете что на этапе mvp надо выбирать исходя из производительности? где логика? и где логика в том, что вы критикуете выбор NATS как выбор исходя из производительности, при том, что автор указал, что и по удобству ему NATS кажется более предпочтительным
        –1
        чтобы нам понять друг друга, надо ввести временные, а еще точнее этапные горизонты. На горизонте стартапа — вы правы однозначно. А вот на горизонте, когда это уже проект в продакшене — я видел прекрасные проекты, которые умирали из-за архитектуры. Становились не рентабельны и легко обходились конкурентами.
          +1
          Так может потому и становились нерентабельны, из-за того, что там, где мог бы справиться один программист нужно было держать армию девопсов и системщиков, чтобы поддерживать оверинжирнутую архитектуру?
        +16
        И ещё вопрос.
        Почему вы считаете представленную архитектуру удачной?
        (хотя мне кажется, что это не архитектура вовсе, а просто набор технологий)
          –2
          а что по вашему IT архитектура, если не набор технологий — картинка с домом?))
            +1
            Часто под архитектурой системы подразумевает разбиение всей системы на компоненты, определение правил взаимодействия между компонентами. Выбор конкретной технологии для реализации компонентов и связей — тоже часть архитектуры, но это уже второй шаг (хоть и тесно связан с первым).

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

            Фактически вы взяли уже готовую архитектуру проекта Billingolang и заменили в ней используемые части. Исследование интересное, но как-то неправильно называть это «созданием архитектуры».
              0
              Скорее соглашусь, но и здесь описаны детали и в аналогии со строительством есть «типовые» для материалов подходы и архитектуры: кирпичный дом vs панельный vs современный мейнстрим (железобетонный каркас + кирпичные стены): материалы определяют архитектуру и походы.
            –2
            почему удачной — потому что она быстрее из всех других перепробованных 6 моделей. И не дорога как в создании, так и в обслуживании.
            +9
            Архитектура — это не про перечисление используемых языков/фреймворков, а про взаимосвязь компонентов. Компонентами могут быть как элементы бизнес-процессов в общем виде, так и модули/интерфейсы в более конкретном виде.
              –4
              частично соглашусь. Архитектура — это и компоненты и взаимосвязи между ними. Но при таком наборе компонентов — взаимосвязи очевидны.
                0
                Кому? Мне, как читателю, не совсем понятно. Был бы рад почитать какие именно проблемы вы решали и как. Дело бы было :)
              +15
              откуда в стартапе 1млн сообщений в секунду? На то он и стартап, что его ещё нету (0 сообщений в секунду).

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

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

              Рекомендую Getting Real, в общем :)
                +4
                На самом деле, это просто наметки какие-то, а не архитектура. И да, к краху стартапа ведет прежде всего бизнесовые просчеты — неспособность продать пусть даже невостребованный сервис, или неспособность найти инвесторов. А технические проблемы будут в любом случае. Как бы не продумывали архитектуру.
                  +7
                  Символичнее всего то, что при всех технических наворотах в репозитории нет ни строчки кода.
                  Болтать — не мешки ворочить…
                    –1
                    Это не opensource проект. Код лежит там где ему положено лежать — подальше от чужих глаз.
                    +3
                    Мускуль, lxc контейнеры, масштабирование горутинами. Не знаю, какая у вас нагрузка, но когда она станет действительно высокой, вас ждут сюрпризы. Хотя один с горутинами вы уже обнаружили.
                      +3
                      стартап на то и стартап, чтобы быстро начать, реализовать первые фичи, и т.п… пока все обдумается и архитектура построится — идея станет не актуальной, или ктото перед вами займет этот стул…
                      Обычная и самая распространенная ошибка новых стартапов ...

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

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

                      PS: а архитектуры в статье так и не увидел… вы бы потрудились хотя бы на схеме проиллюстрировать.
                        –4
                        Не обижайтесь, но я не виноват, что ваш мозг в основном использует визуальное мышление, а мой звуковое. Архитектура там вся перечислена, некоторые взаимосвязи просто логически вытекают из этого перечисления. Попробуйте ПРОЧИТАТЬ, а не ВЗГЛЯНУТЬ.
                        +3
                        Rust, же не смотря на формальное отсутствие состояния гонки, все-таки более подходит не для написания приложений, но драйверов и операционных систем.

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


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

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

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


                          1. Это не системы, а языки
                          2. Выбирать пришлось явно не из-за ограниченности остальных ЯПов. Можно было сразу написать — проект написан на Golang
                            –1
                            язык + инфраструктура = система
                            +1
                            рутинг будет переделан на kataras/muxie — он в два раза быстрее.
                            Обратите внимание на минимальное значение вертикальной оси на графиках. Не в 2 раза быстрее, а примерно на 5-10%.
                              0
                              да вы правы — My mistake…
                              0
                              > высоконагруженные системы
                              > MySQL
                              Вы серьёзно? :) В действительно высоконагруженных системах MySQL если и используется, то редко и в связке с кучей других nosql решений для горячих данных.
                              Пассаж про самую распространённую ошибку тоже неверен. Даже с технической точки зрения, самая распространённая ошибка — это плохая коммуникация между бизнесом и техотделом. В итоге первые плохо формулируют хотелки, а вторые их плохо реализуют. Неудачная архитектура лишь одна из частностей. В целом качество кода для успеха проекта сильно переоценено.
                              Ну и да, выше уже написали что архитектура это не технологии, а общая структура решения и взаимодействие между компонентами (гуглить «системное мышление», уже потом — книги по архитектуре IT-проектов)
                                0
                                  0
                                  В Убере наверняка ещё много других решений используется помимо MySQL. Да и в целом я бы не стал приводить в пример компанию, которая за три года до этого перешла с MySQL на PostgreSQL, а теперь делает обратный переход. Ребята просто видимо слабо понимают что им нужно, либо застряли в парадигме прошлого опыта.

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

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