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: (Default)

Чемпионат идёт к завершению, поэтому расскажу как сайт устроен. Вообще это всё чистый couchapp, давно забытая в веках технология.

Couchapp – это когда есть CouchDB, и она для всего, а больше кроме CouchDB ничего и нет. Я в чистом виде так ещё не делал, всегда был node.js ещё как минимум. В этот раз node.js нет, но в архитектуру couchapp добавлено два слоя – JS rewrite на сервере и PouchDB на клиенте.

JS rewrite, только появившийся в CouchDB 2.0 моими и @kxepal трудами, позволяет делать сложный раутинг прямо внутри БД. То-есть кастомные API, access control и тп.

Вторая фича, PouchDB на клиентах бэкэнда, – позволяет делать тяжёлые веб-приложения бэкэнда с отзывчивостью десктопного уровня, ну и работать при плохих соединениях. “Тяжёлые” – это значит ворочать бинарными данными в мегабайты, картинки там обрабатывать, пдф-ки, сложные виджеты инлайнить с данными в реальном времени.

Архитектура одного узла выглядит так (может быть из одной, двух или трёх физ. машин):

Read more... )
ermouth: (Default)

Мне как-то не хватало несколько раз конкретного масштабного примера, для чего используется CouchDB. То-есть, не все знают, что такое npm, например. Нужно было что-то попонятнее.

И тут проявился прекраснейший case – но, как нередко в мире CouchDB, он, скажем, необычный. Заголовочек один чего стоит:

Hackers Breach US Company and Unwittingly Expose
154 Million Voter Records

То-есть, там случилось вот что. Была CouchDB-шная база с контактами 154 миллионов американских избирателей, и была эта база за фаерволом, и потому не защищена паролем.

Фаервол проломили, и база оказалась проэкспонированной наружу. Слив такой базы – дело очень простое, для CouchDB http-запросы – нативный вид выдачи информации.

---

Пример любопытный, потому что в CouchDB встроен непрошибаемый собственный механизм авторизации и разграничения прав – я не знаю ни одного примера взлома.

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

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

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

У меня есть некоторый опыт общения с мэйнтейнерами проектов со стороны заказчиков с высокой текучкой кадров. Все особо выдающиеся случаи рисковых экспериментов я наблюдал как раз в таких организациях.

---

Зато теперь мы знаем, что CouchDB используется для агрегации и анализа данных обо всех избирателях США. Хороший пример.

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

ermouth: (Default)

Внезапно вчера в Архангельске прошла мегаконференция StartupStandup и, хоть меня туда и не приглашали (какой из меня стартапер, ога), один сделанный нами проект там внезапно оказался.

Паче чаяния, проект по итогам голосования был признан лучшим и даже заказчику приз какой-то дали от Ростелекома.

Коль скоро заказчик проекта его официально презентовал, правда, больше с бизнесовой стороны, не вижу причин не расказать о solovki.pro с колокольни разработчика. Несмотря на то, что всё только-только из-под Under construction выведено, за некоторые вещи “уже не стыдно” (с).

Фронтэнд

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

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

Снимок-экрана-2016-03-17-в-19.03

В самом деле это агрегатор, то-есть фактически услуги оказывают разные компании. Агрегатор аккумулирует данные о номенклатуре услуг и их загруженности и отображает это всё пользователю в виде калькулятора.

Capacity, к слову, считается на сервере одним единственным хитрым map/reduce-ом всего на 200- SLOC.

Калькулятор – jQuery.my приложение, 120 с небольшим кб в исходных текстах. Сделан в CloudWall, там же и отлажен. На картинке вот калькулятор исполняется в отладчике, в окошке.

Снимок экрана 2016-03-17 в 19.31.50

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

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

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

Мобильную версию калькулятора пока не делали – заказчик посчитал, что подождёт.

Приложения бэкэнда

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

Веб-приложения бэкэнда с самого начала заточены под работу в сетях с ненадёжной и медленной связью, то-есть они offline-ready. Однажды загруженная вкладка с приложением прекрасно работает и без соединения и заказчивает/скачивает изменения в данных, когда оно появляется. С учётом качества связи в местах экологического туризма это не прихоть.

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

В самом деле приложения даже не знают, с каким набором данных они работают – всю синхронизацию за них делает платформа. Приложение просто делает this.db.get(), this.db.query() или this.db.put().

Например, вот так выглядит диспетчер со старыми тестовыми данными:

Снимок-экрана-2016-03-17-в-19.17

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

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

Естессно, все приложения – манифесты jQuery.my.

Технологии

Особо детально не буду расписывать, потому что есть чувствительные данные в системе.

Серверная часть – node.js, патченная CouchDB и nginx. То-есть, основная часть кода на JS и немножко на Erlang-е. База крутится на SSD. Памяти на инстанс надо немного совсем. В общем, ничего необычного.

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

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

Локальные данные позволяют трюки, которые затруднительны при обычной архитектуре – например, массивные map/reduce запросы. Вообще, серверные мощности бэкэнда очень скромны, потому что основной объём всякой тяжести вынесен в клиентские браузеры.

“Цена” поддержания канала постоянной синхронизации неожиданно невелика – примерно 14Кб в час, если новых данных не поступает/отправляется. Канал, кстати, гарантирует доставку в конечном итоге, сообщения не могут быть потеряны.

На фронтэнде, на заглавной в калькуляторе, конечно никакой живой синхронизации нет, это было бы избыточно.

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

Поглядим, как это всё полетит )

UPD. Хехе, тут вот уже багов накидали. Аккурат на пограничные случаи. Поправили, но чует моё сердце, что это не последние.

ermouth: (Default)

У нас недавно в процессе тестовых прогонов одного проекта нашёлся удивительного свойства баг, такой очень хитрый race. Race этот прожил в глубинах CloudWall-а два года никак не проявляясь ни в тестах, ни в реальной жизни.

Вернее, он, вероятно, проявлялся, но этот race до определённых условий имеет тенденцию саморассасываться, и поэтому может быть незаметен.

История такая.

Мы гоняли репликацию тестового working set-а с бэкэнда на клиент, проверяя как это работает при разных условиях сети и как нагружается бэкэнд фильтрацией потока репликации.

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

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

Дело оказалось вот в чём.

CloudWall устроен так, что не даёт никакой репликации длиться дольше определённого промежутка времени, если она вышла за таймслот, она завершается на той точке, до куда дошла, и через некоторое время рестартует.

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

Так как CloudWall партиционирует локальную базу и может поддерживать связь сразу с несколькими удалёнными БД, такой подход оправдан. Беда только, что он даёт race на медленных каналах – потому что PouchDB старой версии, что используется, иногда не закрывает соединение при отмене репликации.

То-есть оно продолжает качать себе дальше, если там что-то длинное.

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

Пока не наступает одно из пограничных условий (а они довольно искуственные), рэйс так или иначе рассасывается – потому и не заметно было. Тесты то проходят.

Интересно, что починилось в ~10 строк кода, но доставило невообразимо, да.

ermouth: (ang)
Я три недели провозился с CouchDB – писáл одну интересную для меня фичу. В результате фичу я реализовал, но до pull request‘а так и не довёл, плюнул.

Любопытно, что саму фичу и свои тесты к ней я написал за 4 дня, из которых два дня читал книжки по Erlang-у. Получил peer review, что сделал, в общем, не позор – и это радует. А вот большинство остальных впечатлений – не очень.
Read more... )

В общем, CouchDB мы как использовали, так и будем использовать – но на версию 2.0 я не буду переходить точно. 
ermouth: (ang)
Я в прошлую пятницу решил, что мне надо попробовать поконтрибутить в CouchDB кодом. Там есть несколько фич, который не поддерживаются текущими участниками, и которые явно стоило бы развивать.

Дело было за малым:

  1. Подтянуть Эрланг до уровня, чтобы начать на нём писáть (читал я код на Эрланге более-менее и до этого)

  2. Скачать git CouchDB и сделать так, чтобы он собрался и скомпилился

  3. Вкрутить свой функционал

  4. Написать тесты.

Собсно, самый сложный был второй пункт. Как водится в опенсорце, количество зависимостей просто потрясает воображение, и далеко не все ставятся и настраиваются без бубна. Вишенкой на торте была зависимость от TeX (2.5 гига), который нужен только, чтобы сделать парочку PDF-ов документации.

Также, как это обычно принято в опенсорце все инструкции по установке с сорцев или неполны, или неточны, или относятся к другим версиям или платформам. И в коде практически нет комментариев.

Короче просто скомпилить с сорцев, чтобы заработало, заняло у меня три дня о_О. С учётом, что я ненавижу CLI всей душой, не так и много, хотя я думал, что управлюсь за два.

Зато вот третий пункт – написать работающий код – занял всего два дня вместо трёх. Глядя на имеющийся код пишется полегче. Правда, пока производительность того, что написалось, оставляет желать много лучшего, но я работаю. У меня там переключение между процессами (вызов JS VM из Erlang-кода), а это ой дорого.

Такие дела.

Ddoc Lab

Jul. 30th, 2015 11:31 pm
ermouth: (ang)

Зарелизил CloudWall 1.8, в который вошло новое приложение – Ddoc Lab.

Для этого приложения, выведенного стэндэлоном, сделал отдельный сайтик. Сейчас инглиш вычитывается и пытаюсь пофиксить merchant-account на пэйпэле (дичайший гимор). А так всё уже работает в хорошем приближении.

Клик по картинке – на сайт.

Снимок экрана 2015-07-30 в 23.10.38

Софтинка – довольно специализированное IDE, так что уважаемым читателям бложека вряд ли будут интересны подробности. А вот технологии под ним поинтересней.

Софтинка эта написана в полном CloudWall-е, а на сайте работает под его порезанной стэндэлон-версией. То-есть теперь у меня есть такая специальная версия CloudWall, которая поддерживает всего одно приложение и одну открытую БД на вкладку. И есть генератор этой мини-версии из большого CloudWall-а, да.

То-есть это позволяет релизить сингл пэкиджом из одного JSON-файла сразу и приложение, и ОС под ним. Этот JSON можно копипастить как документ в CouchDB – и приложение сразу взлетает на той базе, куда скопипащено.

Ещё заодно пробую “Pay what you want” модель монетизации – Ddoc Lab в виде JSON-а в некоторых случаях может быть просто бесценен ) То-есть это можно приложение поставить себе в CouchDB  в один копипэйст буквально – и заиметь человечий редактор индекс-функций и приложений у себя локально.

Такие дела.

ermouth: (ang)

Текущий набор иконок “публичных” приложений CloudWall выглядит так:

Снимок экрана 2015-07-08 в 10.28.48

Две последних – новое приложение, которое появится в CloudWall 1.8 и будет выложено стэндэлон-сервисом.

Приложение называется DDoc Lab и служит для разработки, линковки и публикации Couchapp-приложений произвольной структуры. То-есть, это специализированная IDE.

В самом деле редактировать и собирать можно не только Couchapps, но и любые сложные документы для CouchDB. Например, следующая версия FEED CMS пересобирается именно в DDoc Lab, и ускорение против работы в обычном IDE не просто кратное, а скорее на порядок. FEED естессно не Couchapp – просто код хранит в CouchDB, не более того.

Все прелести в пакете – инклюд внешних сорцов, сборка, валидация, частичное обновление, проверка целостности и прочая и прочая.

Началось всё вот с этого поста в рассылке CouchDB в мае. Выделить время в мае у меня не получилось, а в июне у меня куча времени выпало из-за боёв с кривизной PouchDB. Ну, в июле – не поздно )

Постановка задачи

В силу того, что CouchDB-документы – это не файл, а JSON плюс набор файловых аттачей, сборка приложений с файловой системы делается либо руками, либо специализированным CLI-тулом (раз, два). Что так, что так – дикий геморрой в самом деле.

Вообще, крива сама идея CLI-тулов, которым нужен или Питон, или node.js, чтобы собирать приложения для БД, которая себя позиционирует как единое решение для веба. В браузере это должно делаться.

Теперь вот делается.

Ну и под занавес скриншотик вот:

Снимок экрана 2015-07-08 в 11.03.41

Скоро на экранах! )

FEED CMS

May. 20th, 2015 09:42 pm
ermouth: (Default)

Оформили в первом приближении нашу новостную CMS в продукт. Вот уж не думал, не гадал. Клик по картинке – на сайт в первой итерации.

Снимок экрана 2015-05-20 в 21.16.31

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

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

FEED специально заточен под такие задачи – организацию высоконагруженного непрерывного потока информации лентами. Под статические сайты он не подходит – будет очень ограничивать и дорого стОит для статики.

Самое старое боевое внедрение FEED за два года отдало 5+Тб страничек и ни разу не упало, чихнуло разве что пару раз. Есть ещё одно внедрение, на котором в течение полугода менялись один за другим студенты и кому ни попадя права админов раздавались. Там такое с системой вытворялось, что даже я был удивлён, как её можно выкрутить – и тоже не разу не упала, но крепко, правда, спотыкалась.

Всё целиком, от первой до последней строчки, javascript. Весь бэкэнд и мобильная версия – jQuery.my-приложения. Исторический эскизик вот, с которого всё началось:

image

Всё немного посложней в жизни вышло, но примерно принцип понятен, как оно работает.

С Днём Рождения, FEED )

ermouth: (Default)

Поучаствовал в небольшой переделке дизайна заглавной CouchDB в части предложения контрибьютить. Слева – как было, справа – как стало.

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

По-моему, на две головы лучше, чем было.

ermouth: (Default)

Перепозиционировал это всё как noBackend OS, с известной долей иронии каэш. Теперь и на гитхабе – https://github.com/ermouth/cloudwall

Снимок-экрана-2015-04-08-в-1.37.50 

Главные фичи

Оно теперь опенсорц. Установить можно на любой статический хостинг прямо из .tgz, там только html + js + json + css.

Исправлено куча багов, апгрейд библиотек сделан, примерчики добавлены, приложения обновлены. Ещё я там на заглавной выложил унылый шестиминутный скринкаст как за час сделать, отладить и задеплоить приложение для организации распределённых дискуссий. Целых 4кБ длиной приложение, ога.

И – тадам – это всё можно форкать и править/пересобирать форк самого CloudWall прямо в браузере. То-есть можно скачать себе в браузер исходники, это примерно так выглядит:

Снимок экрана 2015-04-08 в 1.38.45

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

Important notice

Если кто-то юзал или смотрел cloudwall.me до этого, не забудьте обновить системные приложения. Как войдёте – серая кнопка Check updates в левой панели внизу.

И да, информация о документе и всякие copy/delete теперь – через клик по иконке документа.

Сделано в CloudWall

CloudWall в текущей версии полностью написан и собран в CloudWall, только иконки не в окошке браузера нарисованы. Сам сайт cloudwall.me тоже управляется прямо из CloudWall.

Вообще, у меня лично внутрибраузерная боевая БД перевалила за 400 мегов. Полёт прекрасный.

---

Хвалите, поздравляйте, ставьте, пробуйте. На планшетах кста норм работает, да.

ermouth: (Default)

Недавно MongoDB выкатили третью версию – ну и решили всему миру расхвастаться, что теперь монго всех быстрей.

http://www.mongodb.com/blog/post/high-performance-benchmarking-mongodb-and-nosql-systems

Интересно в этой публикации что она – враньё. Ребята из монго озвезденели настолько, что решили себя посравнивать с Couchbase (не путать с CouchDB). И получилось у них, что монго типа быстрее раз в 25.

Снимок экрана 2015-04-03 в 2.20.19

Любому, кто своими руками сравнивал монго и couchbase (как я), понятно, что это полная херня – потому что монго с любыми ухищрениями многократно медленней.

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

Couchbase не замедлил ответить.

MongoDB performs well when it 1) is limited to a single node, 2) doesn’t store a lot of data, and 3) doesn’t support a lot of users. This is a sweet spot for MongoDB.

http://blog.couchbase.com/mongodb-rules-single-node-deployments

Тут в цитате всё правда. Монго это такая БД, для тех кто уже не хочет MySQL, а хочет по-модному, чтобы JSON – но при этом с запросами, похожими на SQL. Правда, даже в этом случае Postgre куда лучше подходит, чем Монго.

Реальная картинка сравнения Couchbase и Mongo выглядит примерно так:

Снимок экрана 2015-04-03 в 2.25.30

А если начать сравнивать по чуть более сложным запросам, чем ключ-значение, совсем чтоб по честному – получится разница иногда в несколько порядков.

---

Мораль у басни простая. Видите тесты, где что-то посредственное внезапно стало круче рынка в энцать раз – проверяйте. Скорее всего окажется, что это фуфел.

ermouth: (ang)

Год назад я запустил первую версию cloudwall.me. Жэжэшечка у меня тогда была закрыта, так что написал я об этом только в мае и в Medium.

clouds-09

В тот момент cloudwall.me работал на PouchDB 1.4 (это такая локальная NoSQL БД в браузере). Тогда она была дико глючная и медленная. За год PouchDB стараниями комьюнити доросла до 3.3 и стала вполне стабильной. Среда исполнения приложений на jquerymy за год тоже здорово подросла и в плане скорости, и в плане надёжности.

Плюс добавился IDE, плюс ещё всякие редакторы и приложения, плюс я сайт jquerymy переделал.

Короче, сейчас cloudwall.me – простейшая браузерная ОС, которая для работы не требует инет-соединения. Год назад я говорил (и думал), что ОС эта совсем игрушечная – но, похоже, что не такая уж и игрушечная.

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

И контракт этот – на разработку софта на платформе cloudwall.me. Offlline-ready, все дела. Интересно, что контракт сам меня нашёл.

Что дальше

CloudWall система уникальная в том плане, что её исходники не существуют в виде файлов.

Текущая версия CloudWall (платформы) создана внутри него самого, исходники – это JSON-документы в локальной браузерной БД. Синхронизированной, конечно, с удалёнными репликами CouchDB.

Сам сайт cloudwall.me – статически слинкованный – это один документ CouchDB с 32 аттачами. То-есть, чтобы запустить CloudWall у себя, как свой сайт, достаточно поставить CouchDB и скопировать в неё один-единственный документ. Больше ничего делать не надо – оно сразу заработает само.

В общем, я планирую довести это всё до стадии open-source для начала. Это не так и просто – потому что файлов нет, а на гитхаб можно положить только файлы, то-есть нужен трюк.

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

Что-то типа MS Active directory + DFS получается, только в браузере и для запуска js-приложений. Ну и без дикого сопутствующего гимора как в Винде. И клиенты по определению однопользовательские.

Но сначала я раскрою cloudwall. Скоро на гитхабе, да.

CouchDB PR

Mar. 4th, 2015 06:03 pm
ermouth: (ang)

Меня пропиарили ребята из CouchDB. Причём сразу двумя строчками, ога )

Снимок экрана 2015-03-04 в 17.49.06

Сразу и cloudwall.me, и CoverCouch. А я ведь едва не забросил развивать и то, и другое – а тут внезапно такой наплыв. В этой связи я думаю, что пора их converge в одну систему, ну и cloudwall.me опенсорцить.

В общем, понятны следующие шаги – но цель какая-то нереально амбициозная вырисовывается.

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

ermouth: (ang)
Задачка с эмуляцией JS-энджина CouchDB внутри моей волшебной библиотечки решилась в одно соображение. Там суть задачи – воссоздание для JS-функции довольно необычного scope, такого же, как внутри CouchDB. Сложность в том, что часть этого scope – это «системные» функции CouchDB, а часть – итераторы, зависящие от параметров конкретного запроса и результата работы map-функции.

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

А потом я как-то вспомнил про curried constructor в Scala. Сам по себе аналог в js никак специально не называется, но мне подумалось, что если этот концепт немного дополнить, то выходит как раз нужный мне функционал.

В результате получилось, что на каждую reduce-функцию у меня есть наполовину инстанцированный конструктор, в некотором смысле sсope-полуфабрикат. При каждом запросе reduce клиентом я этот полуфабрикат инжектирую итераторы, зависимые от параметров запроса, и исполняю. Такие конструкции V8 прекрасно оптимизирует – сама reduce-функция получается инстанцированной однократно, вызывается часто и оптимизируется в этой связи компилятором по-полной.

Выложил вчера на гитхаб, а сегодня ночью тесты гонял. Летает )
ermouth: (ang)

Нарисовался внезапно изумительной красоты кусочек кода, прокси-сервер на ноде (типа там для обхода CORS-блокировок например):

var app = require('express')(), request = require('request');
app.use("/proxy",function(req,res){req.pipe(request(req.query.url)).pipe(res)});
app.listen(80);

Обожаю за такие штуки javascript.

Появился этот код в процессе работы над прокси-сервером для CouchDB, который обеспечит per-document read ACL. Ну и попутно кучу других всяких рестрикшинов, которых в CouchDB сейчас нет, а очень бы хотелось.

Это всё небесплатно в плане производительности, но у меня получилось на бумажке построить схему, как это сделать всеобъемлющим, без щелей, и даже для reduce, а не только для map или выборки по ключам.

Первый подход к снаряду делался ещё летом под моим недостаточно чутким руководством, но я сам там ни строчки не написал, да и вообще мало внимания уделял. В результате получилось хоть и работающее, но далеко не всеобъмлющее и очень громоздкое решение.

“Не всеобъемлющее” означает, что API CouchDB где-то немного изменена, а где-то обрезана. А “громоздкое” – потому что много сложно связанного кода, и требует дополнительно Redis (это memcache) для кэширования и синхронизации ACL и сессий между потоками.

Это оказался подход тупиковый и меня недавно осенило, как можно обойтись без межпотоковых взаимодействий через временную БД. Картиночка цепей обработки раутером КучДБ-шного API в части GET-запросов в результате выглядит примерно так:

Снимок экрана 2015-01-22 в 19.42.31

То-есть это полное накрытие REST API, при этом получается не так и много разновидностей обработчиков (это которые зелёные и через запятую). Каждый обработчик строк по 30-50, может. Короткие довольно.

Попутно эта штука будет ограничивать к-во запросов, gzip-ить ответы и вести лог. Во всём остальном прикидываясь CouchDB.

Такой подход (per-document read ACL), если брать в общем, разрушает возможность построения колец из реплик, то-есть допустима только звезда. Скажем, есть три базы – главная и две у юзеров. Реплики у юзеров будут различаться – и если они реплицируются друг в друга минуя главную базу, то оба увидят документы друг друга.

Те не менее, жизнь показывает, что колец репликации надо избегать совершенно по другим причинам и в реальных сценариях их возникновение маловероятно. Например, две реплики “главной” БД, помещённые в два разных браузера, напрямую друг с другом соединиться уже не смогут.

Интересно, что общий подход к этой задаче я в обдумывал года два, пока не придумалось. В общем, скоро “смотрите на гитхабе” )

ermouth: (ang)

Прочитал на Хабре про успехи npm и решил написать пост. npm – это пакетный менеджер и публичный репозиторий для node.js, и успехи реально очень впечатляющие.

Снимок экрана 2015-01-10 в 7.04.56

Фишка в том, что этот репозиторий – база CouchDB. Не “веб-сервер плюс БД”, а именно просто БД. Кластер там, с обвесами – но основные функции выполняет CouchDB, вот на её мету прямой выход. И именно CouchDB там используется неспроста.

Доступность

CouchDB имеет сразу после установки уникальный набор фич, связанных с доступностью. По-отдельности они в других БД есть, а вот разом – нет.

По-хорошему, CouchDB сразу после установки становится веб-сервисом. Доступ к БД – только через http(s)-запросы, через REST-интерфейс, то-есть веб-сервер уже встроен в БД. Веб-приложение админки тоже встроено в БД, аж в двух версиях.

Система контроля доступа – простая, но совершенно железобетонная – тоже встроена в БД, как и механика авторизации.

БД умеет синхронизироваться в непрерывном режиме с другими экземплярами через http(s), в тч в режиме “мастер-мастер”. Протокол репликации хорошо документирован и основан на согласовании деревьев ревизий.

Последняя фича, например, значит, что можно иметь полную локальную “живую” копию npm. Можно даже в браузере, без установки CouchDB.

Хранение и запись

Сама по себе, как БД, CouchDB представляет из себя хранилище JSON-документов, но тут тоже есть целый ряд уникальных фич.

Операция записи/обновления – просто POST запрос, например, аяксом. Запись неблокирующая, это называется MVCC, и тут он честный, а не как в табличных БД.

У каждого дока есть ревизия, которая состоит из номера версии и случайного значения (типа 15-12efdab). При каждой записи в док версия инкрементится, а значение меняется. Записать в док можно только отправив значение предыдущей ревизии, причём если сохранённая ревизия не равна отправляемой, запись отменяется.

Запись идёт в режиме “append only”, ничего не пишется поверх. Это значит, что база помнит все ревизии документов до тех пор пока не будет выполнена операция очистки/оптимизации. Также это значит, что база выжимает из SSD-дисков всё, на что они способны – и при этом их бережёт.

И самое главное – к JSON-документам возможны файловые аттачи, примерно как к емэйлам. То-есть это не просто блобы, это блобы с именем и mime-типом.

Выборка по ключу

Нет ничего проще – GET-запрос типа domain/dbname/doc_id – например https://ermouth.couchappy.com/cwmanual/cw-Demo-Controls-4vx1 – сразу отдаст JSON-документ.

В этом документе есть приаттаченный файл – картинка. Она тоже доступна по прямой ссылке https://ermouth.couchappy.com/cwmanual/cw-Demo-Controls-4vx1/turing.jpg. Вот она, отображается прямо из CouchDB.

Выборка запросами

Любая выборка запросом из CouchDB – это выполнение map/reduce и выдача запрошенного диапазона ключей.

Именованные пары map/reduce функций, к которым выполняются запросы, хранятся в самой БД в специальных документах. Документ выглядит примерно так ermouth.couchappy.com/cloudwall/_design/cloudwall. Видно, что функция – javascript.

Снимок экрана 2015-01-10 в 8.50.45

Запрос к этой map/reduce паре (в которой reduce, правда, нет) выглядит примерно так:
ermouth.couchappy.com/cloudwall/_design/cloudwall/_view/info?startkey="cw"&endkey="cwz"

На выходе – краткая информация о документах в базе, подготовленная map-функцией. В диапазоне ключей cw…cwz.

Важнейшее отличие CouchDB от других БД – результаты вычислений map/reduce кэшируются и повторно map-функции не вычисляются, если документ не обновился.

То-есть map/reduce не требует фуллскана каждый раз, как, например, это происходит в Mongo. Фактически map-функции используются для построения индексов.

Валидация записи и частичное обновление

POST-запросы на запись могут проверяться в БД функциями-валидаторами. Они тоже js и тоже хранятся прямо в БД как специальные документы. Например, вот эта функция не даст писать в БД, если вы не авторизованы:

Снимок экрана 2015-01-10 в 9.03.51

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

Ну то-есть например надо обновить в документе только таймстамп. Чтоб не гонять весь док по сети, можно вызвать на сервере сохранённую функцию, которая это сделает “не отходя от кассы”.

Применимость CouchDB

Везде, где reads>>writes и структура хранимых данных – более-менее сложная. Также в силу специфики http и сериализации как читать, так и писать лучше сразу помногу.

Табличка вот по кейсам, 0 – совсем не подходит, 5 – лучше не придумаешь.

Версионированные хранилища доков 5
Распределённые синхронизированные хранилища 4
Хранилища частично нормализованных связанных данных 1-4
Полностью нормализованные данные 0
Быстрые логи 2
Медленные логи / Агрегаторы логов для анализа 5
Вообще большие наборы данных для анализа 5
Необходимость транзакционной целостности 0
Сложные повторяющиеся “фигурные” выборки 4
Выборки сабсетов узлов документов (частей документов) 5
Подключенные клиенты хотят уведомлений, что база обновилась 4
Хранение файлов (типизированных блобов) 4
SSD диски как хранилище 5+++
Синхронизация / репликация по каналам с потерями и обрывами 5+++

CouchDB вместо сервера приложений

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

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

Такая архитектура проста и надёжна, как железный лом – если в ней что-то и ломается (что почти невероятно), то мгновенно понятно что.

Единственное, что приходится делать вне CouchDB – это ограничивать доступ на чтение. Система доступов в самой CouchDB такая, что дать права на чтение пользователю можно только к целому бакету, но не к отдельным документам.

----

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

Есчо, на Винде тоже прекрасно работает.

ermouth: (ang)

Полгода назад morfizm написал хороший пост про то, как работают технологии map/reduce для распараллеливания обработки больших объёмов данных.

Мне есть что к той истории добавить – все системы, что я построил за последний год, используют map/reduce для сортированной/группированной выборки данных из NoSQL БД. В силу целого ряда вкусностей мы используем CouchDB и примеры будут ближе к ней, но в остальных NoSQL БД принцип примерно такой же.

С помощью применения map/reduce практически любая сложная выборка по набору JSON-документов (деревья, не таблица) успешно приводится к простой выборке (цепочке выборок) диапазона ключей. В общем, для этого достаточно только map, про reduce я в следующий раз напишу.

Работает это так.

Пусть у нас есть БД с постами и комментами, то-есть с набором документов примерно такой структуры:


{type:"post", _id:"", author:"", title:"", stamp:0, content""}
{type:"comment", parentId:"", _id:"", author:"", title:"", stamp:0, content""}

Например, мы хотим выбирать сразу посты и комменты к ним за диапазон дат. Для такой выборки достаточно одной map-функции.


function Feed (doc) {
  if (doc.type==="post") {
    emit ([doc.id, 0], doc    );
    emit ( doc.stamp , doc._id);
    //       _↑_        __↑__
    //       key        value
  }
  if (doc.type==="comment") emit ([doc.parentId, 1], doc)
}

Наша map-функция, в зависимости от типа документа, эмитит пары ключ-значение. Для поста мы эмитим сразу две пары, а для коммента – одну.

Заметим, что разные комменты к одному конкретному посту эмитят себя по одинаковому ключу. Также заметим, что ключ может быть не только string, но и array.

Если пройтись этой функцией по нашей БД, мы на выходе получим набор пар ключ-значение со следующими свойствами:


  1. Выбор из этого набора диапазона ключей startStamp … endStamp даст на выходе айдишники постов в этом диапазоне дат.

  2. Выбор потом ключей вида
    [postId1, 0], [postId1, 1], [postId2, 0], [postId2, 1], [postId3, 0], [postId3, 1]…
    отдаст нам сразу и посты, и все комменты к ним.

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

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

CouchDB именно так и делает. Над каждой базой можно создать набор именованных индексов, в которых хранятся результаты вычисления различных предопределённых map-функций. Выбирать из БД можно как по ID документов, так и по ключам результатов работы этих функций.

Индексы хранятся как B-tree, соответственно с рождения заточены под выбор диапазонов.

Чуток усложнив ключи с таймстампом – скажем, до [doc.author, doc.stamp], мы сможем выбирать посты конкретного автора. Диапазоны выборки ключей для первого запроса будут выглядеть тогда примерно так:  ["ermouth", 1420000000000] … ["ermouth", 1420014425025].

К такой схеме выборки после SQL пришлось некоторое время привыкать – но когда к ней приспособишься, оказывается, что она куда богаче SQL по возможностям одного только map.

На этой прекрасной ноте заканчиваю 2014 год.

Всем счастья, радости и приятных ништячков в 2015! Ушёл готовить оливье.

ermouth: (ang)

Открыли публичную бета-версию обновлённого портала областного правительства, в продолжение их пресс-центра (ровно год прошёл, да). Сначала скриншотики, кликабельны

2
1

Теперь чем оно всё круто.

0. Скорость

Вся система целиком, до последней строчки – javascript, и при этом практически любая страница после первого захода видна менее чем через секунду после клика (в России, в 120мс пинга до хостинга). Всё потому, что как и на пресс-центре применено блочное кэширование и в 99% случаев страницы отдаются целиком из кэша в RAM, даже без обращения к БД.

1. Облачная распределённая платформа

Оно плотно интегрировано с пресс-центром, это не просто одна CMS и стилистика, это единая платформа в облаках. Из соображений усиления периметра безопасности платформа состоит из нескольких компонентов, связанных только по https – скажем, головной сайт не хранит и не обрабатывает данные форм и авторизации, это делает специальный ресурс. Также на фронтэнде невозможно авторизоваться в админку – её там просто нет.

2. Импорт данных

Эта платформа импортирует данные из других систем – телефонные справочники приходят в SQL-формате, ежемесячные обновления бюджета – в CSV, афиши – в JSON и т.д. После импорта данные приводятся в унифицированный внутренний формат, а потом отображаются в виде табличек, диаграмм, списков ссылок и т.д.

Особенно полезны для вдумчивого читателя интерактивные диаграммы бюджета. На секторы можно кликать. Смею предположить, что такое представление бюджета для народа – лучшее по простоте навигации из всех, что я видел. Оно основано на одной заброшенной австралийской инициативе 5-летней давности по раскрытию open data. Мы из этого сделали технологию, в которой данные обновляются в один клик.

3. Контроль устаревания

Все материалы имеют “срок годности” – дату, после которой система начнёт напоминать о необходимости обновления. Такой фичи я просто вообще нигде в CMS не встречал, а для большого госпортала она абсолютно необходима. На предыдущей версии портала нереальные завалы неактуального старья – и про то, что информация протухла редактор портала мог узнать только случайно.

Мы сделали механику для исключения такого рода бардака.

4. Обращения и вообще формы

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

Использовать СНиЛС как на госуслугах – не вариант, это другой класс защиты персональных данных, мы бы не поместились в сроки и бюджет. Да и неудобный он до смерти, “интернет по паспорту”.

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

---

Вообще, работа проделана колоссальная – переработано почти 400 страниц информационного контента, урегулированы вопросы поставки обновлений из ведомств, масса данных уточнено. Ну и портал правительства, наконец то, для простого человека стал не бесполезен.

Началось всё вот с такой картинки:

image

Ну и да,  вся эта система управляется приложениями jquerymy. Внутри системы даже IDE есть простенький для горячей замены кода системы из браузера прямо, тоже на $.my.

Такие дела.

Profile

ermouth: (Default)
ermouth

July 2017

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526 272829
3031     

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 27th, 2017 04:32 am
Powered by Dreamwidth Studios