Serverless и полтора программиста


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


Архитектура


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


Второе решение было — не хочу ничего менеджить собственными силами, цена devopsов сейчас слишком высока, одной зарплатой можно оплатить год managed-решений в облаках.


Третье, пожалуй самое безрассудное и на грани «слабоумия и отваги», рискнуть пойти на новорожденное решение от MongoDB, которое в тот момент называлось Stitch, а сейчас называется Realm (но это не совсем тот самый Realm, а ядреная смесь из Stitch и Realm, которая получилась после приобретения последнего MongoDB, Inc в конце 2019 года)


Backend


В результате серверная сторона вышла вот такой:



Node и Redis в ней появились только для реализации Server Side Rendering и кэширования (ну и для того, чтобы не кормить Atlas лишними платными запросами), для тех кто не решает задачи SEO-оптимизации их можно легко выкинуть.


В результате бэк масштабируется в пару кликов до практически любого размера. И самое главное стоит копейки, за счет того, что платный computed-runtime по большей части потребляется один раз на измененные данные и сохраняется в кеше.


Frontend


Клиентская часть классическая: React + Redux + Redux-Saga + TypeScript



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


Аутентификация и авторизация


Ну а теперь самое интересно, для чего вообще нужно было все это мракобесие с Mongo.Realm. Вместе с лямбдами мы получаем полноценную интеграцию из коробки с ворохом способов аутентификации (Google, Apple, Facebook, Email/Password и прочими) и механизмом авторизации операций до уровня полей в коллекциях:



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


Прочие радости


Также облачная монга нам из коробки дает sync наборов данных с клиентом, push-уведомления, хранилище секретов, триггеры (на события базы, аутентификация, работу по расписанию), вебхуки, хорошие логи и еще много чего. То есть снаружи оно обслуживается и воспринимается как полноценный сервис, при этом не приходится решать вопросы масштабирования и переноса между датацентрами, бекапов, мониторинга и кучи других задач.


Ну, а для самых безбашенных, есть возможность работы через GraphQL.


Как все это работает



В случае если попали в кэш, при 100 RPS на один экземпляр (в конфигурации по одному ядру и одному гигабайту на один экземпляр Node.js под управлением PM2), время ответа укладывается в 200 мс, в противном случае вместе со всеми запросами к Mongo серверный рендер отрабатывает до 500 мс.


В работе с Mongo.Realm есть нюансы, которые никак не отражены в документации, но проявляются во всех недорогих инстансах с разделяемой памятью (M1, M2, M5): если запросы выполняются от имени клиента, то, видимо в качестве защиты от перегрузок, периодически время ответа на какой-нибудь aggregation-pipeline может резко вырасти до 5-10 секунд на запрос. При этом, если вызывается серверная функция (с тем же самым aggregation-pipeline), которая выполняется от имени системного пользователя, то таких трюков не наблюдается.
Возможно дело именно в типе кластера, и со временем это исправят или все решится переходом на М10 и выше, но сейчас для некоторых сложных запросов пришлось пойти на рискованный шаг и для чтения данных анонимными пользователями сделать несколько функций исполняемых от имени системного пользователя, в этом случае правила авторизации для доступа к данным игнорируются, и за безопасностью надо следить уже самим в коде.



В случае аутентифицированного доступа Server Side Rendering не нужен, все работает прямо на клиенте.


Выводы


В заголовок вынесен ресурс потраченный на разработку, а именно полтора программиста (1 фронтендер и ½ бэкендера). Ровно столько и 5 месяцев работы, понадобилось для вывода в прод довольно развесистого портала с собственной системой управления контентом, интеграцией с несколькими поставщиками данных включая нечеткие сопоставления, оптимизированного под самые суровые требования по SEO и c поддержкой мобильный браузеров как first class citizen.


Весь мой предыдущий, более чем 16-летний опыт управления разработкой говорил, что ресурсоемкость этого проекта будет раза в 4 выше.


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

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

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

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

    +4
    Я тот самый девопс )).
    Из текста не очень ясно, я так понимаю, что у вас весь бэкенд находится в mongo? А где тогда хоститься клиент?
    Я тут небольшую програмку писал, но я выбрал google firebase. Но у меня конечно всё маленькое получилось — пара таблиц и с десяток функций.

    Честно сказать serverless замечательная вещь, жаль что не везде можно использовать.
      0

      Какая проблема раздать клиента из s3 клаудфронтом?

        0
        В самом простом случае (если не нужен SSR) у Mongo.Atlas есть встроенный хостинг статики с поддержкой CDN. В нашем случае пришлось немножко поизголяться и взять виртуалку у Google Cloud и CDN у G-core.
          0

          Firebase для средних и больших проектов крайне не советую — периодически безбожно тупит и иногда вылетает. Для 99.9 точно не подойдёт.

            0
            И еще один серьезный минус в историях с Firebase — в момент, когда появляется более-менее внеямый объем запросов, ценник становится заоблачным. У монги в этом отношении пока все намного лучше.
          0
          Интересное решение, но, как то боязно, конкуренты организуют лёгкий DDOS и все, продавай квартиру, просто повышенный интерес пользователей (я так понимаю именно поэтому не приведена ссылка на ресурс) — хабраэффект — плати, я понимаю зачем такой подход облачным провайдерам, но владельцу ресурса выгода только на стадии роста посещаемости, этакий MVP, пока неизвестно взлетит/не взлетит. Толстый мобильный фронтенд так себе решение, не так много пользователей обладают мощными устройствами за 1000$, чтобы с комфортом пользоваться ресурсом. В общем с технической стороны решение интересное, а с практической так себе. Возможно я не прав, буду рад выслушать контраргументы.
            0
            Вот именно ради таких комментариев я и написал эту статью, спасибо большое!

            Да риски есть, я об этом тоже размышлял, но думаю от DDOS эффективнее защищаться другими способами. У того же GCore есть сервис для отсеивания атак и на сетевом и на прикладном уровнях. Из «плюсов» Mongo, то что computed-runtime рассчитывается месячными лимитами, и в худшем случае конкурент положит нам бэк, до тех пор пока мы не разбермся, что происходит, при этом пользователи будут по прежнему получать готовые страницы из кэша. Правда данные какое-то время не будут актуализироваться, поскольку лягут все триггеры синхронизации с внешними API и мы не сможем наполнять контент. Но для нашей модели в пределах суток-двух это не критично, потому что информация о будущих событиях собирается заранее на несколько дней вперед, дополняется описанием авторов и попадает в кэш в виде готовых страниц.

            На сейчас я исхожу из следующих соображений:
            1) Размер пока такой, что конкурентам не интересно тратиться на DDOS
            2) Если размер станет большой, взаимодействие с Mongo.Realm перетащим от клиента в промежуточный бэк и повесим защиты от DDOS
            3) Если все-таки кто-то начнет мочить до этих мероприятий, то цена потерь не велика, в худшем случае пару дней данные будут не самые актуальные, но при этом для поисковиков и для клиентов мы будем выглядеть условно живыми.

            Но это в теории, проверять не хочется пока, поэтому и ссылку не стал давать.

            Про толщину мобильного клиента, он развесистый, но не настолько чтобы не работать на устройствах за 100$. Единственная проблема, что на мобилах первая полная загрузка занимает до 5-10 секунд, но сервис предполагает большой ретеншен, так что второй раз все возьмется из кэша.
            0
            Оно работает ровно до тех пор пока это MVP, а как посещаемость начнёт расти нужно будет всё переделывать. Вообщем скупой платит дважды, но это не проблема если это учитывалось изначально, ведь количество свободных денег тоже должно вырасти.
              0
              Все так, все так! Но гипотезы надо проверять как можно быстрее и дешевле. И я изначально старался проектировать так, чтобы этот переход был не очень больным и дорогим.

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

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