четверг, 12 января 2017 г.

[prog] Бывают ли встраиваемые http-сервера для C/C++ с асинхронной обработкой запросов?

Беглым взглядом прошерстил списки встраиваемых http-серверов для C/C++ отсюда и отсюда. Показалось, что они практически все сделаны так, что когда для обработки GET или POST запроса вызывается пользовательский callback, то этот callback должен отработать синхронно, т.е. должен сразу отдать весь ответ на запрос. А вот такого, чтобы:

  • http-сервер синхронно дернул callback на какой-то своей рабочей нити (соответственно, рабочая нить блокируется);
  • callback инициировал асинхронную обработку запроса и вернул http-серверу некий future;
  • рабочая нить http-сервера разблокируется и http-сервер получает возможность обрабатывать другие запросы;
  • когда асинхронная обработка запроса завершается, future взводится;
  • http-сервер обнаруживает факт того, что future взведен, забирает готовый ответ и отсылает его клиенту.

Вот такого прям с ходу не нашел. Может быть C++ REST SDK (aka Casablanca) от Microsoft это позволяет делать, надо будет внимательнее посмотреть, вроде бы там что-то похожее на task-based parallelism-а используется.

Может кто-то сталкивался с подобным встраиваемым http-сервером? Если ли такое вообще?

PS. Пикантность ситуации в том, что нужно именно C/C++, т.к. обработчики HTTP-запросов должны дергать довольно сложные C++ные вещи. Плюс VC++ и Windows на первом месте в списке поддерживаемых платформ. Посему библиотеки, заточенные только под Unix-ы и GCC/clang, идут лесом.

PPS. На всякий случай список ссылок, по которым прошелся:

вторник, 10 января 2017 г.

[prog.thoughts] Какое тонкое различие между message-driven и event-driven...

Продавцы Akka и, заодно, главные пиарщики Reactive Manifesto, на днях опубликовали очередной white paper: Reactive Programming versus Reactive Systems. Материал наполовину технический, наполовину маркетинговый. Но, не смотря на то, что маркетингового бла-бла-бла там порядком, почитать все-таки интересно.

Мое внимание привлекли пару фрагментов, которые описывают разницу между message-driven и event-driven подходами (выделения в цитате взяты из первоисточника):

The main difference between a Message-driven system with long-lived addressable components, and an Event-driven dataflow-driven model, is that Messages are inherently directed, Events are not. Messages have a clear, single, destination; while Events are facts for others to observe. Furthermore, messaging is preferably asynchronous, with the sending and the reception decoupled from the sender and receiver respectively.

Что, в моем кривом переводе на русский язык, будет звучать как:

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

А далее приводится цитата из Reactive Manifesto, в которой эта разница раскрывается более подробно:

A message is an item of data that is sent to a specific destination. An event is a signal emitted by a component upon reaching a given state. In a message-driven system addressable recipients await the arrival of messages and react to them, otherwise lying dormant. In an event-driven system notification listeners are attached to the sources of events such that they are invoked when the event is emitted. This means that an event-driven system focuses on addressable event sources while a message-driven system concentrates on addressable recipients.

В моем пересказе это будет звучать так:

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

Вот как-то так. Вот какие проблемы людей волнуют :)

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

А у людей из Lightbend-а есть и другая головная боль: они свои Reactive Streams пытаются навесить на акторы, а это непростая задача. Поскольку акторы по природе своей асинхронны, что плохо согласуется с непрерывными потоками данных из-за отсутствия естественного back-pressure. Тут лучше подходят CSP-каналы, но это уже совсем другая парадигма получается... И, как мне думается, именно в попытках скрестить ужа с ежом разработчики из Lightbend-а и вынуждены мешать в одну кучу message-driven и event-driven, а потом старательно объяснять в чем же именно разница между первым и вторым.

У нас в SObjectizer таких проблем нет :) У нас сообщение -- это просто способ доставки информации до того, кто в этой информации заинтересован. А событие -- это факт доставки сообщения до получателя (т.е. вызов обработчика для доставленного сообщения). При этом отсылка сообщения возможна как в режиме 1:1, т.е. у сообщения есть единственный получатель, которому целенаправленно сообщение и отсылается. Так и в режиме 1:N, т.е. у сообщения будет N получателей. Так что у нас все приложения получаются event-driven, при этом унутрях у них message-driven механизм распределения информации между агентами и рабочими потоками :)

Это, конечно же, идет в разрез с Моделью Акторов, в которой сообщение отсылается конкретному актору-получателю, а массовую рассылку в режиме 1:N нужно делать ручками. Но нам пофиг ;) Publish-Subscribe, с асинхронной доставкой сообщений подписчикам рулит и бибикает :) Хотя бы потому, что с ее помощью элементарно реализуется и взаимодействие в режиме 1:1.

PS. У попыток применить publish-subscribe для dataflow-driven обработки больших потоков данных будут те же самые проблемы, что и у Модели Акторов: т.е. отсутствие естественного механизма back-pressure. Год назад в SO-5 мы добавили CSP-шные каналы. Так что dataflow на mchain-ах в SO-5 уже делать можно. А если еще придумать, как более удобным и естественным образом отобразить mchain-ы и события агентов, то можно будет удобство dataflow-driven подхода в SO-5 вывести на совсем другой уровень.

понедельник, 9 января 2017 г.

[prog] В склерозник: три основных принципа в симуляции Boids от Крейга Рейнольдса

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

С тех пор время от времени я забывал про эти правила, вспоминал, искал в Интернетах, иногда находил, иногда нет. Сейчас вот вновь нашел, решил зафиксировать в склерознике. Речь, как оказалось, шла о симуляции поведения птичьих стай, под названием Boids. Эту симуляцию в середине 1980-х разработал Крейг Рейнольдс. Вот ссылка на статью в Wiki на эту тему.

А вот эти самые три простых правила:

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

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

[prog.c++] Готовлю доклад для Corehard C++ Winter 2017

12-го февраля 2017-го года, в Минске пройдет очередная конференция сообщества Corehard C++. Я туда уже заявился с докладом "Шишки, набитые за 15 лет использования акторов в C++", в котором постараюсь рассказать про несколько "граблей", на которые довелось наступить, набить несколько шишек и задуматься о том, как этого не делать впредь.

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

Текста уже набралось на восемь страниц в Google.Doc-е. Полагаю, этого достаточно, чтобы уложиться в 40-минутный доклад. Увеличивать объем дальше стремно, повышаются риски не уложиться как в прошлый раз.

Из "граблей" в доклад попали следующие:

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

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