Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Это важно и актуально.Что именно важно и актуально?
а, значит, разработчиками уже выработаны какие-то оптимальные решения. Или, всё же, не совсем?Не знаю, что творится в этой теме с точки зрения computer science. На практике же есть несколько широко известных реализаций: Erlang и Akka. Erlang — это отдельный язык и виртуальная машина (т.е. настоящая платформа). Akka — это просто фреймворк для JVM (для Java и Scala). Кроме них существуют и другие реализации для разных языков и платформ (например, Elixir для Erlang VM, Quasar для Java, Orleans для .NET, Celluloid для Ruby и т.д.) Для C++ полный разброд и шатание (немного подробнее здесь). Впрочем, для C++ это нормально, т.к. C++ применяется для совершенно разных задач.
А почему нельзя реализовать протокол подобный ReactiveStreams в таком случае?А где можно посмотреть на описание этого протокола?
The Flow API does not provide any APIs to signal or deal with back pressure as such, but there could be various strategies one could implement by oneself to deal with back pressure.Т.е. стандартного API для этого нет, нужно делать что-то по месту бедствия.
How elements are transmitted, their representation during transfer, or how back-pressure is signaled is not part of this specification.Из описания API для Reactive Streams следует, что основная идея в периодическом запросе N новых сообщений Subscriber-ом после того, как он разобрался со своей текущей нагрузкой. Для каких-то задач это вполне себе нормально. И может быть без особых усилий реализовано поверх асинхронного общения акторов.
Вы часто упоминаете сложности организации back-pressure в модели акторов, но не вдавались в подробности, в чём эти сложности заключаются.Я попытался объяснить, с чем приходится сталкиваться в общем случае. Понятно, что бывают частные случаи, в которых реализация back-pressure более очевидно (как, например, в ограниченном контексте с Reactive Streams). Вообще, вот здесь я специально подчеркивал, что хороший механизм защиты от перегрузки должен быть заточен под конкретную задачу.
Akka Streams например поверх протокола ReactiveStreams реализует много чего. И отбрасывание лишних сообщений, и группировку, и непосылание новых запросов.А можно ссылочку попросить, дабы не перелопачивать всю документацию по Akka Streams?
Штуки, про которые я рассказывал реализованы вместе с буферизацией на асинхронных границах http://doc.akka.io/docs/akka/2.4.14/scala/stream/stream-rate.htmlПохоже, что задачи, возлагаемые на Akka Streams, в мире C++ решаются с помощью Data Flow and Dependency Graphs из Threading Building Blocks. Это вообще отдельная ниша со своими особенностями. Решения для нее можно строить на базе Модели Акторов (например, акторами могут быть отдельные вычислительные узлы графа, так же акторами могут быть координаторы, которые решают, какому вычислительному узлу выделить время на рабочей нити в пуле). Можно строить на базе CSP и короутин. Это может быть даже проще и удобнее: связи между узлами представляются в виде CSP-каналов, вычислительные узлы графа — в виде короутин. Когда короутина-поставщик пытается записать очередной элемент данных в заполненный канал, то она просто приостанавливается. Когда короутина-потребитель пытается прочитать очередную порцию данных из пустого канала, она так же просто приостанавливается. Тем самым получается относительно несложное отображение большого количества короутин на небольшое количество рабочих потоков.
Нужно иметь какой-то баланс между проведением вычислений и передачей данных.При использовании CSP-каналов и короутин здесь неоткуда ожидать больших накладных расходов, чем при использовании акторов.
Но мне кажется, что протокол, когда обработчик говорит, сколько сообщений он может принять и не умереть (плюс возможно что делать с другими сообщениями) вполне имеет право на жизнь почти везде.Имеет. Но, во-первых, как один из набора возможных. Во-вторых, с ним тоже не все так просто, примеры чего можно найти даже по приведенной вами ссылке. Так что изначальный тезис о том, что backpressure для асинхронных агентов — это не так просто, как хотелось бы, на мой взгляд, пока сохраняет свою актуальность.
Преимущество в том, что мы передаем сообщения вместе с их длиной (как в UDP), но имеем надежную передачу (как в TCP)Не очень понял вашу мысль. Сообщение при передаче по TCP точно так же должно предваряться длиной. Ну или придется искать в потоке данных специальные разделители (как это сделано в HTTP), что совсем неудобно при передаче BLOB-ов.
Подводные камни для самодельной распределенности «из коробки» в С++ном акторном фреймворке