Изначально были откинуты однопоточные системы. Выбирать пришлось между 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)
Vadem
11.02.2019 19:29+10И ещё вопрос.
Почему вы считаете представленную архитектуру удачной?
(хотя мне кажется, что это не архитектура вовсе, а просто набор технологий)rumatakira Автор
12.02.2019 16:00а что по вашему IT архитектура, если не набор технологий — картинка с домом?))
Regis
12.02.2019 16:53+1Часто под архитектурой системы подразумевает разбиение всей системы на компоненты, определение правил взаимодействия между компонентами. Выбор конкретной технологии для реализации компонентов и связей — тоже часть архитектуры, но это уже второй шаг (хоть и тесно связан с первым).
Если проводить аналогию со строительством, то вы вместо плана здания составили список возможных материалов для использования.
Фактически вы взяли уже готовую архитектуру проекта Billingolang и заменили в ней используемые части. Исследование интересное, но как-то неправильно называть это «созданием архитектуры».flamefork
12.02.2019 20:09Скорее соглашусь, но и здесь описаны детали и в аналогии со строительством есть «типовые» для материалов подходы и архитектуры: кирпичный дом vs панельный vs современный мейнстрим (железобетонный каркас + кирпичные стены): материалы определяют архитектуру и походы.
rumatakira Автор
12.02.2019 16:08почему удачной — потому что она быстрее из всех других перепробованных 6 моделей. И не дорога как в создании, так и в обслуживании.
werklop
11.02.2019 20:11+6Архитектура — это не про перечисление используемых языков/фреймворков, а про взаимосвязь компонентов. Компонентами могут быть как элементы бизнес-процессов в общем виде, так и модули/интерфейсы в более конкретном виде.
rumatakira Автор
12.02.2019 16:02-2частично соглашусь. Архитектура — это и компоненты и взаимосвязи между ними. Но при таком наборе компонентов — взаимосвязи очевидны.
andreyons
12.02.2019 16:06Кому? Мне, как читателю, не совсем понятно. Был бы рад почитать какие именно проблемы вы решали и как. Дело бы было :)
alemiks
11.02.2019 20:54+8откуда в стартапе 1млн сообщений в секунду? На то он и стартап, что его ещё нету (0 сообщений в секунду).
это ведет к краху проекта
имхо, к краху проекта ведёт его бесполезность для пользователей, а не какой-нибудь выбор Python vs Go
Рекомендую Getting Real, в общем :)
smarthomeblog
11.02.2019 21:00+3На самом деле, это просто наметки какие-то, а не архитектура. И да, к краху стартапа ведет прежде всего бизнесовые просчеты — неспособность продать пусть даже невостребованный сервис, или неспособность найти инвесторов. А технические проблемы будут в любом случае. Как бы не продумывали архитектуру.
berezuev
11.02.2019 21:23+4Символичнее всего то, что при всех технических наворотах в репозитории нет ни строчки кода.
Болтать — не мешки ворочить…rumatakira Автор
12.02.2019 15:48Это не opensource проект. Код лежит там где ему положено лежать — подальше от чужих глаз.
crmMaster
11.02.2019 21:23+1Мускуль, lxc контейнеры, масштабирование горутинами. Не знаю, какая у вас нагрузка, но когда она станет действительно высокой, вас ждут сюрпризы. Хотя один с горутинами вы уже обнаружили.
KirEv
11.02.2019 23:02+2стартап на то и стартап, чтобы быстро начать, реализовать первые фичи, и т.п… пока все обдумается и архитектура построится — идея станет не актуальной, или ктото перед вами займет этот стул…
Обычная и самая распространенная ошибка новых стартапов ...
… не стартапом единым… а вообще, самая распространенная ошибка — решать проблемы которых не существует…
На предыдущей работе была задача сделать последовательную очередь обработки данных (golang):
1. массив структур через канал заполняется данными одной горутиной
2. другая горутина постепенно выбырает данные по таймауту
3. самому главному программисту\со-овнеру показалось, что это класическая очередь, начали городить сначала Redis + RabbitMQ, потом уговорил их что редиса достаточно (хотя по факту ни то ни другое не нужно)
4. основной аргумент главного в пользу редиса+ребита, внимание: мы не хотим показаться лохами, нужно заюзать крутые технологии… (дословно из чата)… понятно да?
5. самое интересное, чуть позже кейс изменился, из пачки данных (то что в стеке), нужно было выбрать сначала самые свежие… и все что строилось пришлось выбросить и сделать как полагалось изначально: тупая структура с 3мя методами (читать, писать, взять первый), на ребит, в пустую, ушло 2 недели (!!!)… потому что решали выдуманые задачи…
так и с масштабированием или предвременной оптимизацией бывает…
PS: а архитектуры в статье так и не увидел… вы бы потрудились хотя бы на схеме проиллюстрировать.rumatakira Автор
12.02.2019 15:54-2Не обижайтесь, но я не виноват, что ваш мозг в основном использует визуальное мышление, а мой звуковое. Архитектура там вся перечислена, некоторые взаимосвязи просто логически вытекают из этого перечисления. Попробуйте ПРОЧИТАТЬ, а не ВЗГЛЯНУТЬ.
LooMaclin
12.02.2019 11:31+1Rust, же не смотря на формальное отсутствие состояния гонки, все-таки более подходит не для написания приложений, но драйверов и операционных систем.
Не совсем понимаю, почему вы так считаете. Аргументируйте это пожалуйста. Потому что на мой взгляд это не так и вот почему:
1) Rust подходит для разработки во многих других областях, помимо написание драйверов и операционных систем. Для того, чтобы убедиться в этом, можно взглянуть, какие компании используют его: https://www.rust-lang.org/production/users. У него есть все необходимые инструменты для этого.
2) Хорошая статья с более подробной аргументацией: https://habr.com/en/post/434200/
Просто оставлю здесь цитату:
Концепции раста очень мощные, и отлично работают на уровне прикладных приложений, которые не задумываются о производительности, но скорее только о продуктивности разработчиков, скорости внедрения новых фич и простоты поддержки. Очень грустно наблюдать, что такой отличный во всех отношениях язык всё больше получает клеймо "странного и сложного языка для низкоуровневых гиковских задач". Надеюсь, я немного пошатнул этот вредный миф, и в мире станет на сколько-то более продуктивных и счастливых разработиков больше.
3) В нашей компании успешно используется Rust в продакшене, и это не разработка ОС и драйверов. И используется не в стиле "написали утилиту небольшую", это огромнейший кусок серверной части.
rumatakira Автор
12.02.2019 15:43+2На самом деле — вы правы. Rust даже мне изначально легче заходил. И написать на нем можно все. Но для стартапа приложения — выгоднее использовать Golang. Больше инфраструктура, больше программистов, ниже себестоимость процесса.
danyanya
12.02.2019 15:43+1Изначально были откинуты однопоточные системы. Выбирать пришлось между Erlang, Golang и Rust.
1. Это не системы, а языки
2. Выбирать пришлось явно не из-за ограниченности остальных ЯПов. Можно было сразу написать — проект написан на Golang
otetz
12.02.2019 15:49+1рутинг будет переделан на kataras/muxie — он в два раза быстрее.
Обратите внимание на минимальное значение вертикальной оси на графиках. Не в 2 раза быстрее, а примерно на 5-10%.
Vadem
А можно узнать есть ли у вас какя-то статистика на этот счёт?
Я в вопросе не очень разбираюсь, но неоднократно слышал, что причны провала стартапов не технические. Например, направильное понимание рынка, решение несуществующих проблем, плохоая модель монетизации и т.д.
Т.е. архитектура проекта — это, конечно, хорошо, но на успех или неуспех стартапа влияет слабо.
crmMaster
Более того, оверинжиринг (хороший пример показан в статье) зачастую приводит к тому, что разработка mvp затягивается на какие — то неадекватные сроки из-за необходимости поддерживать все эти навороты.
flamefork
При том, что я сильно на стороне бизнеса (в противоположной от архитектурных стронафтов), не увидел в статье явного overengineering. Нормальная архитектура, не сильно сложнее ХХИВП, но заметно стабильнее.
crmMaster
Хотя на ровном месте, мускуль кластер, lxc вместо докера, выбор компонентов исходя из производительности, а не удобства, решение несуществующих проблем, введение технологий по принципу «чтобы было». Как это все вы называете? по мне так это классический оверинжиринг, — код писать ещё не начал, а инфраструктуру уже поддерживать надо.
flamefork
> мускуль кластер
это что, сложно?
> lxc вместо докера
честно говоря, я под lxc подразумевал докер. если нет — зря
> выбор компонентов исходя из производительности, а не удобства
где?
> решение несуществующих проблем, введение технологий по принципу «чтобы было»
детали плз
crmMaster
> это что, сложно?
Проблема не в кластере, проблема в мускуле. Вы выбрали базу, потому что у нее есть воркбенч. Выбирать базу исходя из инструментария, а не из из схемы хранения — считаете допустимо для «высоконагруженных» ситстем?
> я под lxc подразумевал докер
lxc != docker. Докер — это инструментарий для управления контейнерами. lxc — это технология, на которой не только докер основан. И вы что, автор чтобы что-то там подразумевать?
> выбор компонентов исходя из производительности, а не удобства
тут
> решение несуществующих проблем
решается конфигом композера
А вот и конкретное обозначение проблемы, решение которой в рамках поставленной задачи не требуется, более того далее по статье предполагается разнесение по разным машинам контейнеров, а значит вся эта работа — в помойку.
flamefork
> Вы выбрали базу
Я?
> считаете допустимо для «высоконагруженных» ситстем
Возможно я излишне вольно трактую посыл автора статьи, но мне кажется нормальным выбрать достаточно универсальное мейнстримное решение на этапе, когда специфика проекта еще не выявлена. Я трактую примерно в духе «взять что-то, что в среднесрочной перспективе не доставит геморроя, при этом не тратя на это много времени». Честно не понимаю, где тут люди видят сложность и перенавороченность предлагаемого набора.
> lxc != docker
Я это прекрасно понимаю.
> И вы что, автор чтобы что-то там подразумевать?
Подразумевал при прочтении. Если автор имеет в виду именно голый LXC — соглашусь, зря он так.
> выбор компонентов исходя из производительности, а не удобства
> Да и кластеризуется он быстрее и легче чем RabbitMQ.
Ээээ
crmMaster
> мне кажется нормальным выбрать достаточно универсальное мейнстримное решение на этапе, когда специфика проекта еще не выявлена.
Ну если вам кажется что базу надо выбирать исходя из «универсальности» и «мейнстримности», а не исходя из организации хранения, миграций, надежности, необходимых типов данных и прочих технических требований к нагруженным системам, то пусть кажется дальше. Только не лезьте, пожалуйста в вопросы в которых вы не компетентны.
> Ээээ
Что эээ? Вы привели цитату где человек решает несуществующую проблему. Как это опровергает мою цитату, поясните, пожалуйста.
flamefork
> и прочих технических требований к нагруженным системам
Обычно на начальном этапе _технических_ требований почти никаких, и надо чтобы оно просто работало и не создавало геморрой.
> Только не лезьте, пожалуйста в вопросы в которых вы не компетентны.
Хехе, забавный вывод, оставлю без комментариев.
> разработка mvp затягивается на какие — то неадекватные сроки
> выбор компонентов исходя из производительности, а не удобства
а теперь вы мне доказываете что на этапе mvp надо выбирать исходя из производительности? где логика? и где логика в том, что вы критикуете выбор NATS как выбор исходя из производительности, при том, что автор указал, что и по удобству ему NATS кажется более предпочтительным
rumatakira Автор
чтобы нам понять друг друга, надо ввести временные, а еще точнее этапные горизонты. На горизонте стартапа — вы правы однозначно. А вот на горизонте, когда это уже проект в продакшене — я видел прекрасные проекты, которые умирали из-за архитектуры. Становились не рентабельны и легко обходились конкурентами.
crmMaster
Так может потому и становились нерентабельны, из-за того, что там, где мог бы справиться один программист нужно было держать армию девопсов и системщиков, чтобы поддерживать оверинжирнутую архитектуру?