Couchbox

Jul. 27th, 2017 03:52 am
ermouth: (Default)

Месяц назад мы запустили публичную бету vezdelegko.ru, сервиса бронирования экскурсий, отелей и транспорта. Сервисы бронирования – сами по себе штука сложная, это как магазин, по которому надо вести учёт ассортимента на каждый день, причём ассортимент день ото дня меняется и цены зависят от дня и количества. Причём в магазине куча отделов, и партнёры сами управляют своим ассортиментом.

Дополнительно, в нашем случае сервис делался с прицелом на очень существенную масштабируемость как по ёмкости, так и по географии. Это автоматом предполагает архитектуру из многих узлов и распределённое хранение/обработку данных с последующей их репликацией и агрегацией. Под такую схему я придумал специальную архитектуру узла, которая потребовала платформы исполнения, это и есть Couchbox.

Снимок экрана 2017-07-27 в 2.26.24

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

Code follows data

Нативная CouchDB хранит в базах не только данные, но и код для predefined map/reduce запросов, по которым строятся высокоэффективные persistent индексы. Этот код, на JS или Erlang, хранится в документах рядом с данными и может распространятся между узлами в тех же потоках репликации, что и сами данные.

Couchbox, наша платформа, расширяет это всё механикой хуков, реагирующих на изменения документов в базе, и эндпоинтов – REST–концов, обрабатывающих входящие запросы через https. То-есть в те же специальные документы, где в обычной CouchDB живёт код функций индексов, для Couchbox-а можно добавить ещё и код функций хуков и внешних REST API эндпоинтов. Получается распределённая платформа приложений.

Особо примечателен факт, что с точки зрения установленного софта узлы не различаются вообще.

Весь специфический код, определяющий функциональную роль узла, приходит через БД. То-есть по мере обновления документов с кодом все обработчики по-горячему аккуратно заменяются на новые версии. Обработчики устроены примерно как амазоновские лямбды, функции без сохранения состояния, поэтому горячая замена вполне возможна.

Файлы – это очень скучно

Важный момент, как именно код функций попадает в БД.

Код лямбд вообще не существует в виде исходных файлов. Он создаётся в специализированной среде разработки, основанной на CloudWall и Ddoc Lab. Выглядит это примерно так:

Снимок экрана 2017-07-27 в 3.52.11

То-есть, сорцы, из которых собираются лямбды, хранятся в PouchDB в браузерах разработчиков, реплицируются в CouchDB на какой-то из узлов, собираются, а затем распространяются по остальным узлам.

Деплой обновлений и скорость разработки

Такая архитектура расслаивается на три части по критерию обслуживания:

  1. Убунта, CouchDB, Redis, node.js и nginx – фундамент со временем между рестартами в месяцы. Для обновления или рестарта фундамента нужен доступ к каждому узлу через терминал.
  2. Couchbox – платформа приложений с временем между обновлениями сейчас в недели, скоро станет в месяцы. Разрабатывается на файловой системе в обычных IDE, для обновления на узлах нужен доступ через терминал.
  3. Код приложений, очень гибкий, может обновляться и дополняться с высокой частотой. Для разработки и отладки как клиентской (UI), так и серверной части (REST API) приложений не нужно ничего, кроме браузера. Код деплоится по узлам автоматом.

Общий объём кода, написанного в браузере для этой системы, перевалил за 100К SLOC и пока всё просто прекрасно. Стартскрин бэкэнда выглядит сейчас вот так:

Снимок-экрана-2017-07-27-в-4.29

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

И да, Couchbox is MIT licensed. Опенсорц наше всё.

ermouth: (ang)
В javascript ES6 появилась новая волшебная фича – прокси-объекты. К фиче не существует вменяемого polyfill-а в ES5, поэтому мы её до последнего времени не юзали. Её нет, например, в IE 11– и node.js 6–.

Фича работает примерно как в Java: выставляет перед объектом перехватчик, который позволяет реализовывать абстрактный интерфейс к объекту. Очень полезный функционал – lazy partial constructors там, контроль доступа к объектам в памяти, когда заранее неизвестно, какой код будет объекты обрабатывать, и всякое такое.

В общем, в конце прошлого года я решил, что время пришло.

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

Собственно, вся эта кухня нагорожена для изоляции лямбд и их горячей замены. Код лямбд хранится в БД и распространяется по узлам в одном потоке репликации с данными, которые он должен обрабатывать. По приходу обновлений лямбд их надо а) заменять по-горячему, б) иметь pre-compiled образ для быстрого старта нескольких инстансов одной лямбды. Erlang inspired architecture.

Контекст (объект this) каждого вызова лямбды состоит из трёх частей, две из них приходят из БД, а третья – lazy плагины с файловой системы. Контекст между лямбдами частично shared. Целиком пересобирать здоровый объект перед каждым вызовом лямбды или дорого, или получается unsafe. Тут и пригодились Proxy-объекты.

По результатам всестороннего облизывания оказалось, что они чрезвычайно упрощают меж-VM-ное взаимодействие и вполне себе в ноде ужé быстрые (были адово медленные когда только появились).

Жаль, IE портит всю малину на клиенте. 
ermouth: (Default)

Отличный материал про промисы, от самого активного контрибутора PouchDB.

http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html

Там хороший разбор, особенно для тех, кто до сих пор по-старинке коллбэками пишет. Куча примеров, ошибки разобраны – в том числе достаточно частые:

Снимок экрана 2015-05-19 в 19.09.24

Вообще, систематическое применение промисов порождает вот такой, например, код:

Снимок экрана 2015-05-18 в 19.08.45

Снимок экрана 2015-05-18 в 19.09.49

Это реальный код из cloudwall.me, слева – старт приложения, справа – старт системы. По читаемости с коллбэками не идёт ни в какое сравнение, конечно. Нельзя сказать то же о скорости и прожорливости, но всё не так плохо.

http://spion.github.io/posts/why-i-am-switching-to-promises.html

Так что да, главная проблема с промисами – что их готовить не умеют. С функционалом всё более-менее устаканилось.

ermouth: (Default)

C целью “потрогать” arrow-функции в ES6 написал вот парсер выражений в польской нотации, простенький. Работает в консоли FireFox или в io.js, больше нигде не работает.

var polish = (function () {
  var ops = "+-/*".split("").reduce((a,b)=>(a[b]=Function("x","return x[0]=x.shift()"+b+"x[0],x"),a),{});
  return (s)=>s.split(/\s+/).reduce((a,b)=>(ops[b]?ops[b](a):!isNaN(b)&&b!=''?(a.unshift(+b),a):a),[]);
})();

polish ("10 1 2 3 + + *") напишет [60].

Пожалуй, я уже хочу стрелки в js. До этого как-то они мне не родными для js казались – ну и зря.

ermouth: (Default)

Наткнулся только что в кейноте по новым предложениям для javascript.

Снимок экрана 2015-04-22 в 3.10.50

Это значит, что мы можем расшаривать данные между workers, со всеми плюшками. То-есть теперь в js есть threads, ну, или совсем скоро будут.

Многопоточность в C++ понимании в JS-мире нужна очень редко (да и в остальных мирах, по-хорошему, тоже) – но зато когда она нужна, без неё туго.

Это, например, вещание потоковых стримов из воркера нескольким (торрент)-слушателям через WebRTC или аналогичные применения. Это разделяемые мемкэши в веб-серверах. Это навороченные игры.

Игры от меня далеко, а вот два других применения – очень даже мне близки.

Обходные манёвры на чистом JS сейчас превращаются или в медленные, или жутко прожорливые решения (а обычно и медленные, и прожорливые). Ну, кажется, теперь всё станет по-другому.

---

Вот хорошо бы ещё пионэры JS-комьюнити смотрели и в сторону Erlang, а не только Emscripten/C++.

Profile

ermouth: (Default)
ermouth

June 2018

S M T W T F S
     12
3 456789
10111213141516
17181920212223
24252627282930

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Apr. 26th, 2019 08:05 am
Powered by Dreamwidth Studios