SlideShare una empresa de Scribd logo
1 de 49
Descargar para leer sin conexión
Школа актерского
     мастерства
            @remeniuk
• 70-ые, концепция «Актеров»
• 80-ые, Erlang, популяризация
  и развитие
  – OTP – фреймворк для создания
    надежных систем,
    толерантных к ошибкам
• 00-ые, Scala, cовременное
  представление
Почему актеры?

• Параллелизм без страха
• Хороший дизайн
• Простая расширяемость
  – location transparency         WIN!
• Инструментарий для создания надежных
  систем
• scala.actors
• Akka
• Scalaz
• Kilim
• Lift
Будущее: scala.actors + Akka




Как будет происходить объединение scala.actors и
Akka?
Предположение: единый API, и fault-tolerance
стек из Akka.
scala.actors

Thread-based        Event-driven
actor{              actor{
  while(true){        loop{
    receive{            react{
      case msg =>         case msg =>
    }                   }
  }                   }
}                   }



     ! !! !? ?
Актер с состоянием
Актер с состоянием
• Модель publisher/subscriber
  – тривиальный подход - хранение в переменной

 protected var subscribers = List[Subscriber]()

 loop {
   react{
      case AddSubscriber(subscriber) =>
           subscribers = subscriber :: subscribers
      case Publish(event) =>
          subscribers.foreach(_ ! event)
Хранение состояния в Erlang
Передача состояния в рекурсии:
•   «чистый» функциональный подход
•   требует поддержки оптимизации рекурсии


      loop(State) ->
         receive
            Msg ->
               NewState = whatever(Msg),
               loop(NewState)
         end.
Модель publisher/subscriber
• Передача состояния в рекурсии

 def loop(subscribers: List[Subscriber]): Unit
 = react{

      case AddSubscriber(subscriber) =>
       loop(subscriber :: subscribers)
      case Publish(event) =>
       subscribers.foreach(_ ! event)
       loop(subscribers)
  }

 def act = loop(Nil)
Идемпотентный актер
Идемпотентный актер

Актер, устойчивый к получению
    дупликатов сообщений


       f(x) = f(f(x))
Nested react/receive (вложенный
обработчик)
  • обрабатывается только первое
  сообщение – остальные пропускаются

loop {
   react {
    case Event(evt) =>
     // необходимые вычисления...
     def skip: Unit = reactWithin(0) {
       case Event(event) if(event == evt) => skip
       case TIMEOUT =>
     }
     skip
Nested react/receive способен на
большее:
• обработка с приоритетом

reactWithin(0){
   case Event(evt: String) =>
     subscribers.foreach(_ ! evt)

  case TIMEOUT => react {
    case AddSubscriber(subscriber) =>
         subscribers = subscriber :: subscribers
    case Event(evt) =>
         subscribers.foreach(_ ! evt)
Типизированный актер
Типизированный актер
• Процессы в Erlang не типизированы
  – Придает гибкость модели
     • Актеры, по своей природе, динамичны
     • HotSwap обработчика

• Базовые актеры в Scala и Akka,
  следующие идеологии Erlang, тоже не
  типизированы
Типизированные актеры иногда полезны:
• !?, !!, !!! – известный тип «ответа»
• специализация обработчиков
• Scala <2.7.x - InputChannel[T]
• Scala 2.8.x+ - Reactor[T]


 sealed trait Message
 class Foo extends Message
 class Bar extends Message

 class DatatypeReceiver[T >: Null <: Message]
 extends Reactor[T]


                      Принимает сообщения
                        подтипа Message
Типизация актеров позволяет использовать
всю мощь системы типов Scala
  – Typeclass паттерн


implicit val fooReceiver = new DatatypeReceiver[Foo]
implicit val barReceiver = new DatatypeReceiver[Bar]

def send[T >: Null <: Message : DatatypeReceiver]
  (message: T) =
      implicitly[DatatypeReceiver[T]] ! message

send(new Foo)
                       Находит в контексте обработчик
                                нужного типа
Альтернативный подход
• декларирование возможных типов
  сообщений в объекте-компаньоне
• паттерн Active Object
  – типизированные актеры в Akka:
 trait Service {
     def serve(arg: String)
 }
 class ServiceImpl extends TypedActor with Service {
     def serve(arg: String) = //…
 }
                                    Выполняется
 service.serve(“foo”)               асинхронно
Scatter/Gather
 рассеять/собрать
Scatter/Gather
 рассеять/собрать
Тривиальное решение – блокирующий
 синхронный аггрегатор
 • аггрегатор не может обрабатывать новые
   сообщения, пока собирает ответы


                                           FAIL!
             react{
               case Event(event) =>
                 val results = Futures.awaitAll(1000,
reply(res)          subscribers.map(_ !! event):_*)
                 // обработка собранных ответов...
                 reply(results)
Можно прибегнуть к хитрости – перенести
ожидание, обработку и ответ в другой поток
• неэффективное использование – выделенный
  поток просто ждет


 react{
   case Event(event) =>
     actor{
         val results = Futures.awaitAll(1000,
        subscribers.map(_ !! event):_*)
         // обработка собранных ответов...
         reply(results)
     }
Aсинхронная аггрегация – решение в Erlang-
стиле

  1) канал для передачи результатов аггрегации
  2) асинхронная сборка результатов:
     • ответы «рабочих» обрабатываются
       аггрегатором наравне с другими
       сообщениями
     • промежуточные результаты передаются
       рекурсивно
class AsynchAggregator(workers: Iterable[Subscriber],
replyChannel: Channel[Any]) extends Actor {

 def loop(results: List[Any]): Unit = react {
  case event: Event[Any] =>
   workers foreach(_ ! event); loop(results)
                                              reply(Result(res))
  case Result(res) =>
   if(results.size != workers.size - 1) loop(res :: results)
   else {
     // обработка собранных результатов...
     replyChannel ! (res :: results); loop(Nil)
   }
Клиентская сторона (синхронное окружение)
• клиент ждет сообщение в канале, блокируя
  поток


val aggregator = new AsynchAggregator(subscribers,
    replyChannel)

aggregator ! Event("hello")
replyChannel.receive{
  case message => // результат работы аггрегатора
}
Клиентская сторона (синхронное окружение)
• клиент ждет сообщение в канале, блокируя
  поток


val aggregator = new AsynchAggregator(subscribers,
    replyChannel)

actor { aggregator ! Event("hello") }
replyChannel.receive{
  case message => // результат работы аггрегатора
}
Другие библиотеки

• Функциональный подход c Promises в
  Scalaz
• Псевдо-императивный подход с
  Dataflow в Akka
Scalaz Promise[T]
  Актер-работник асинхронно дает
  аггрегатору обещание (promise), и выполняет
  его

 react {
    case Message(msg) =>
     val rez = new Promise[String]()(Strategy.Sequential)
     reply(rez)
     rez.fulfill{Thread sleep 1000; “Hello!”}
}
Scalaz Promise[T]
 Аггрегатор дает клиенту обещание результата,
 декларируя будущую аггрегацию и обработку

case msg: Message =>
   val res = workerz.map(worker => (worker !? msg)
   .asInstanceOf[Promise[String]])
   .sequence
   .map{results =>
     // обработка                      PROFIT!!!
     results
   }
                      List[Promise[String]] => Promise[List[String]]
   reply(res)
Akka Dataflow
Dataflow concurrency – декларативная модель
безопасного параллелизма

                     Dataflow-переменная

                     • Изменение значения
                       вызывает цепную реакцию
                     • Инициализируется единожды
                     • Может безопасно
                       использоваться в
                       многопоточном окружении
Akka Dataflow*
                                       Dataflow-переменные
def sample{
 val x0, x1, y0, y1 = Promise[Int]()
                                        Присвоение значения
    flow{
      y0 << x0() + 1;    println("y0 = " + y0())
      y1 << x1() + y0(); println("y1 = " + y1())
    }
    flow{ x0 << 1 }
    flow{ x1 << 2 }           scala> sample
}                            y0 = 2
                             y1 = 4


       *базируется на continuations → нет lock’ов
Как применить dataflow для scatter /
gather?
•     Рассылка, и асинхронная инициализация
      dataflow-переменных

    val result = Promise[String]()
    val promises = List.fill(recipients.size)(Promise[String]())

    recipients.zip(promises).map{case (recipient, promise) =>
      (recipient !!! msg).map{result: String =>
        flow{
          promise << result
        }
      }
    }
Аггрегатор

def gather(promises: List[CompletableFuture[String]],
           result: String = ""): String @cps[Future[Any]] =
    promises match {
        case head :: tail =>
             gather(tail, head() + result)
        case Nil => result
    }

flow {
    result << gather(promises)
 }
Балансировка нагрузки
• Балансировка на уровне инфраструктуры

  • Актер-роутер, работающий с пулом актеров,
    выбирающий «работника» согласно некому
    алгоритму балансировки


• Балансировка на уровне
  планировщика/диспетчера потоков

  • scala.actors: fork-join pool
  • Akka: work-stealing dispatchers
Актер-роутер
case class Ready(actor:   class Balancer[A <: Actor](workers:
Actor)                    Iterable[A]) extends Actor{

def worker = actor{        def act = loop{
 loop{                       react{
   react{                      case msg: Ready =>
    case msg: Ready =>         case msg =>
       reply(this)              val _sender = sender
    case msg =>                 workers foreach {_ ! Ready(this)}
       //обработка              react {
                                  case Ready(worker) =>
                                    worker.send(msg, _sender)
                                }
                             }
                           }
+
• роутер незамедлительно узнает, когда
  появляется незанятый работник
• роутер может работать с любыми типами
  актеров (локальные, удаленные)



                   -
• сообщения о статусе работников создают
  много «шума»
• роутер заблокирован, пока не освободится
  какой-нибудь «работник»
Более эффективное решение в рамках одной
JVM - балансировка на уровне планировщика/
диспетчера потоков.


                      Akka
Пул актеров управляется work-stealing dispatcher.
Если какой-то актер из пула не занят, он «крадет»
сообщения из mailbox’а другого актера
Akka: work-stealing dispatcher
object MyActor {
  val dispatcher = Dispatchers.newExecutorBasedEvent>
        DrivenWorkStealingDispatcher(name).build
}

class MyActor extends Actor {
  self.dispatcher = MyActor.dispatcher ; ...
}

val actor1= actorOf[MyActor].start               actor2
val actor2= actorOf[MyActor].start              «крадет»
                                               сообщение
actor1 ! LongRunningTask
actor1 ! LongRunningTask
Супервизор
“If somebody dies, other people
will notice”
        Programming Erlang, Joe Armstrong
Линки и ловушки – базовые элементы для
построения систем на основе актеров

Линки объединяют группу актеров в единую
подсистему. Если один из актеров «умирает»,
прилинкованные актеры тоже прекращают работу

      actor {
        self link anotherActor
        …
      }

Ловушка перехватывает сигнал выхода
      actor {
        self.trapExit = true
        …
      }
Супервизор

• супервизор – любой актер, прилинкованный к
  другому, и обрабатывающий сигнал выхода
• supervisor (OTP) - если контролируемый актер
  умирает, перехватывает сигнал выхода, и
  принимает меры, в соответствии с выбранной
  стратегией
Доступные реализации

• Akka Supervisors
• Scala-OTP
  – хороший выбор, если вы работаете с
    scala.actors
Akka Supervisors
  Вдохновлены супервизорами из Erlang/OTP

SupervisorConfig(
 OneForOneStrategy(List(classOf[Exception]), 3, 10),
 Supervise(
  myFirstActor,
                                Стратегия поведения в
  Permanent) ::                случае «смерти» актера
 Supervise(
  mySecondActor,
                                Наблюдаемые актеры
  Permanent) ::
 Nil)
•   транзакционный актер
•   каталог актеров и ресурсов
•   фасад процессов
•   многие другие
Спасибо за внимание!




      Вопросы?

Más contenido relacionado

La actualidad más candente

06 - Hadoop. Java API и Hadoop Streaming
06 - Hadoop. Java API и Hadoop Streaming06 - Hadoop. Java API и Hadoop Streaming
06 - Hadoop. Java API и Hadoop StreamingRoman Brovko
 
08 - Hadoop. Алгоритмы на графах в MapReduce
08 - Hadoop. Алгоритмы на графах в MapReduce08 - Hadoop. Алгоритмы на графах в MapReduce
08 - Hadoop. Алгоритмы на графах в MapReduceRoman Brovko
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularizationIvan Krylov
 
07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в Java07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в JavaRoman Brovko
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"LogeekNightUkraine
 
Александр Сычев "Разделяй и властвуй: CQRS в iOS"
Александр Сычев "Разделяй и властвуй: CQRS в iOS"Александр Сычев "Разделяй и властвуй: CQRS в iOS"
Александр Сычев "Разделяй и властвуй: CQRS в iOS"IT Event
 
Сетевое взаимодействие
Сетевое взаимодействиеСетевое взаимодействие
Сетевое взаимодействиеUnguryan Vitaliy
 
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶ отладки в Tarantool
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶  отладки в TarantoolИнструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶  отладки в Tarantool
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶ отладки в TarantoolTimur Safin
 
DF1 - BD - Baranov - Mining Large Datasets with Apache Spark
DF1 - BD - Baranov - Mining Large Datasets with Apache SparkDF1 - BD - Baranov - Mining Large Datasets with Apache Spark
DF1 - BD - Baranov - Mining Large Datasets with Apache SparkMoscowDataFest
 
13 - Hadoop. Парадигма Spark
13 - Hadoop. Парадигма Spark13 - Hadoop. Парадигма Spark
13 - Hadoop. Парадигма SparkRoman Brovko
 
05 - Java. Collections Framework и Generics
05 - Java. Collections Framework и Generics05 - Java. Collections Framework и Generics
05 - Java. Collections Framework и GenericsRoman Brovko
 
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...JetBrains Russia
 
Мифы и легенды Java Stream API
Мифы и легенды Java Stream APIМифы и легенды Java Stream API
Мифы и легенды Java Stream APICEE-SEC(R)
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Roman Brovko
 

La actualidad más candente (19)

06 - Hadoop. Java API и Hadoop Streaming
06 - Hadoop. Java API и Hadoop Streaming06 - Hadoop. Java API и Hadoop Streaming
06 - Hadoop. Java API и Hadoop Streaming
 
08 - Hadoop. Алгоритмы на графах в MapReduce
08 - Hadoop. Алгоритмы на графах в MapReduce08 - Hadoop. Алгоритмы на графах в MapReduce
08 - Hadoop. Алгоритмы на графах в MapReduce
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Xtend
XtendXtend
Xtend
 
Scala On Rest
Scala On RestScala On Rest
Scala On Rest
 
07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в Java07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в Java
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"
 
JDBC
JDBCJDBC
JDBC
 
Александр Сычев "Разделяй и властвуй: CQRS в iOS"
Александр Сычев "Разделяй и властвуй: CQRS в iOS"Александр Сычев "Разделяй и властвуй: CQRS в iOS"
Александр Сычев "Разделяй и властвуй: CQRS в iOS"
 
Сетевое взаимодействие
Сетевое взаимодействиеСетевое взаимодействие
Сетевое взаимодействие
 
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶ отладки в Tarantool
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶  отладки в TarantoolИнструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶  отладки в Tarantool
Инструменты для з̶а̶х̶в̶а̶т̶а̶ ̶м̶и̶р̶а̶ отладки в Tarantool
 
Apache spark
Apache sparkApache spark
Apache spark
 
DF1 - BD - Baranov - Mining Large Datasets with Apache Spark
DF1 - BD - Baranov - Mining Large Datasets with Apache SparkDF1 - BD - Baranov - Mining Large Datasets with Apache Spark
DF1 - BD - Baranov - Mining Large Datasets with Apache Spark
 
13 - Hadoop. Парадигма Spark
13 - Hadoop. Парадигма Spark13 - Hadoop. Парадигма Spark
13 - Hadoop. Парадигма Spark
 
XML Magic
XML MagicXML Magic
XML Magic
 
05 - Java. Collections Framework и Generics
05 - Java. Collections Framework и Generics05 - Java. Collections Framework и Generics
05 - Java. Collections Framework и Generics
 
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
 
Мифы и легенды Java Stream API
Мифы и легенды Java Stream APIМифы и легенды Java Stream API
Мифы и легенды Java Stream API
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.
 

Similar a Курсы актерского мастерства

DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...it-people
 
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptСтажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptSmartTools
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?Vasil Remeniuk
 
Введение в Akka
Введение в AkkaВведение в Akka
Введение в AkkaZheka Kozlov
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Vasya Petrov
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Vasya Petrov
 
Живые приложения с Rx
Живые приложения с RxЖивые приложения с Rx
Живые приложения с RxGoSharp
 
Codefest-2015 Reactive Streams
Codefest-2015 Reactive StreamsCodefest-2015 Reactive Streams
Codefest-2015 Reactive StreamsAlexey Romanchuk
 
Reactive Extensions
Reactive ExtensionsReactive Extensions
Reactive ExtensionsGetDev.NET
 
Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Dmitry Stropalov
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)ScalaNsk
 
Михаил Давыдов - JavaScript. Асинхронность
Михаил Давыдов - JavaScript. АсинхронностьМихаил Давыдов - JavaScript. Асинхронность
Михаил Давыдов - JavaScript. АсинхронностьYandex
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. SparkTechnopark
 

Similar a Курсы актерского мастерства (20)

DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
DUMP-2015: «Распределенная обработка миллионов документов на Scala и Akka» Ст...
 
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptСтажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
Асинхронный JavaScript
Асинхронный JavaScriptАсинхронный JavaScript
Асинхронный JavaScript
 
Введение в Akka
Введение в AkkaВведение в Akka
Введение в Akka
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
Урок 7. Интерпретация и компиляция функциональных программ.
Урок 7. Интерпретация и компиляция функциональных программ.Урок 7. Интерпретация и компиляция функциональных программ.
Урок 7. Интерпретация и компиляция функциональных программ.
 
Javascript 1
Javascript 1Javascript 1
Javascript 1
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
Reactive extensions
Reactive extensionsReactive extensions
Reactive extensions
 
Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)
 
Живые приложения с Rx
Живые приложения с RxЖивые приложения с Rx
Живые приложения с Rx
 
Codefest-2015 Reactive Streams
Codefest-2015 Reactive StreamsCodefest-2015 Reactive Streams
Codefest-2015 Reactive Streams
 
Scala - my path
Scala - my pathScala - my path
Scala - my path
 
Reactive Extensions
Reactive ExtensionsReactive Extensions
Reactive Extensions
 
Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)Scala and LiftWeb presentation (Russian)
Scala and LiftWeb presentation (Russian)
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
 
Михаил Давыдов - JavaScript. Асинхронность
Михаил Давыдов - JavaScript. АсинхронностьМихаил Давыдов - JavaScript. Асинхронность
Михаил Давыдов - JavaScript. Асинхронность
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. Spark
 
Stream API
Stream APIStream API
Stream API
 

Más de Vasil Remeniuk

Product Minsk - РТБ и Программатик
Product Minsk - РТБ и ПрограмматикProduct Minsk - РТБ и Программатик
Product Minsk - РТБ и ПрограмматикVasil Remeniuk
 
Работа с Akka Сluster, @afiskon, scalaby#14
Работа с Akka Сluster, @afiskon, scalaby#14Работа с Akka Сluster, @afiskon, scalaby#14
Работа с Akka Сluster, @afiskon, scalaby#14Vasil Remeniuk
 
Cake pattern. Presentation by Alex Famin at scalaby#14
Cake pattern. Presentation by Alex Famin at scalaby#14Cake pattern. Presentation by Alex Famin at scalaby#14
Cake pattern. Presentation by Alex Famin at scalaby#14Vasil Remeniuk
 
Scala laboratory: Globus. iteration #3
Scala laboratory: Globus. iteration #3Scala laboratory: Globus. iteration #3
Scala laboratory: Globus. iteration #3Vasil Remeniuk
 
Testing in Scala by Adform research
Testing in Scala by Adform researchTesting in Scala by Adform research
Testing in Scala by Adform researchVasil Remeniuk
 
Spark Intro by Adform Research
Spark Intro by Adform ResearchSpark Intro by Adform Research
Spark Intro by Adform ResearchVasil Remeniuk
 
Types by Adform Research, Saulius Valatka
Types by Adform Research, Saulius ValatkaTypes by Adform Research, Saulius Valatka
Types by Adform Research, Saulius ValatkaVasil Remeniuk
 
Types by Adform Research
Types by Adform ResearchTypes by Adform Research
Types by Adform ResearchVasil Remeniuk
 
Scalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex GryzlovScalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex GryzlovVasil Remeniuk
 
Scalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex GryzlovScalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex GryzlovVasil Remeniuk
 
Spark by Adform Research, Paulius
Spark by Adform Research, PauliusSpark by Adform Research, Paulius
Spark by Adform Research, PauliusVasil Remeniuk
 
Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)Vasil Remeniuk
 
Spark intro by Adform Research
Spark intro by Adform ResearchSpark intro by Adform Research
Spark intro by Adform ResearchVasil Remeniuk
 
SBT by Aform Research, Saulius Valatka
SBT by Aform Research, Saulius ValatkaSBT by Aform Research, Saulius Valatka
SBT by Aform Research, Saulius ValatkaVasil Remeniuk
 
Scala laboratory: Globus. iteration #2
Scala laboratory: Globus. iteration #2Scala laboratory: Globus. iteration #2
Scala laboratory: Globus. iteration #2Vasil Remeniuk
 
Testing in Scala. Adform Research
Testing in Scala. Adform ResearchTesting in Scala. Adform Research
Testing in Scala. Adform ResearchVasil Remeniuk
 
Scala laboratory. Globus. iteration #1
Scala laboratory. Globus. iteration #1Scala laboratory. Globus. iteration #1
Scala laboratory. Globus. iteration #1Vasil Remeniuk
 
Cassandra + Spark + Elk
Cassandra + Spark + ElkCassandra + Spark + Elk
Cassandra + Spark + ElkVasil Remeniuk
 
Опыт использования Spark, Основано на реальных событиях
Опыт использования Spark, Основано на реальных событияхОпыт использования Spark, Основано на реальных событиях
Опыт использования Spark, Основано на реальных событияхVasil Remeniuk
 

Más de Vasil Remeniuk (20)

Product Minsk - РТБ и Программатик
Product Minsk - РТБ и ПрограмматикProduct Minsk - РТБ и Программатик
Product Minsk - РТБ и Программатик
 
Работа с Akka Сluster, @afiskon, scalaby#14
Работа с Akka Сluster, @afiskon, scalaby#14Работа с Akka Сluster, @afiskon, scalaby#14
Работа с Akka Сluster, @afiskon, scalaby#14
 
Cake pattern. Presentation by Alex Famin at scalaby#14
Cake pattern. Presentation by Alex Famin at scalaby#14Cake pattern. Presentation by Alex Famin at scalaby#14
Cake pattern. Presentation by Alex Famin at scalaby#14
 
Scala laboratory: Globus. iteration #3
Scala laboratory: Globus. iteration #3Scala laboratory: Globus. iteration #3
Scala laboratory: Globus. iteration #3
 
Testing in Scala by Adform research
Testing in Scala by Adform researchTesting in Scala by Adform research
Testing in Scala by Adform research
 
Spark Intro by Adform Research
Spark Intro by Adform ResearchSpark Intro by Adform Research
Spark Intro by Adform Research
 
Types by Adform Research, Saulius Valatka
Types by Adform Research, Saulius ValatkaTypes by Adform Research, Saulius Valatka
Types by Adform Research, Saulius Valatka
 
Types by Adform Research
Types by Adform ResearchTypes by Adform Research
Types by Adform Research
 
Scalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex GryzlovScalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex Gryzlov
 
Scalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex GryzlovScalding by Adform Research, Alex Gryzlov
Scalding by Adform Research, Alex Gryzlov
 
Spark by Adform Research, Paulius
Spark by Adform Research, PauliusSpark by Adform Research, Paulius
Spark by Adform Research, Paulius
 
Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)
 
Spark intro by Adform Research
Spark intro by Adform ResearchSpark intro by Adform Research
Spark intro by Adform Research
 
SBT by Aform Research, Saulius Valatka
SBT by Aform Research, Saulius ValatkaSBT by Aform Research, Saulius Valatka
SBT by Aform Research, Saulius Valatka
 
Scala laboratory: Globus. iteration #2
Scala laboratory: Globus. iteration #2Scala laboratory: Globus. iteration #2
Scala laboratory: Globus. iteration #2
 
Testing in Scala. Adform Research
Testing in Scala. Adform ResearchTesting in Scala. Adform Research
Testing in Scala. Adform Research
 
Scala laboratory. Globus. iteration #1
Scala laboratory. Globus. iteration #1Scala laboratory. Globus. iteration #1
Scala laboratory. Globus. iteration #1
 
Cassandra + Spark + Elk
Cassandra + Spark + ElkCassandra + Spark + Elk
Cassandra + Spark + Elk
 
Опыт использования Spark, Основано на реальных событиях
Опыт использования Spark, Основано на реальных событияхОпыт использования Spark, Основано на реальных событиях
Опыт использования Spark, Основано на реальных событиях
 
ETL со Spark
ETL со SparkETL со Spark
ETL со Spark
 

Курсы актерского мастерства

  • 1. Школа актерского мастерства @remeniuk
  • 2. • 70-ые, концепция «Актеров» • 80-ые, Erlang, популяризация и развитие – OTP – фреймворк для создания надежных систем, толерантных к ошибкам • 00-ые, Scala, cовременное представление
  • 3. Почему актеры? • Параллелизм без страха • Хороший дизайн • Простая расширяемость – location transparency WIN! • Инструментарий для создания надежных систем
  • 4. • scala.actors • Akka • Scalaz • Kilim • Lift
  • 5. Будущее: scala.actors + Akka Как будет происходить объединение scala.actors и Akka? Предположение: единый API, и fault-tolerance стек из Akka.
  • 6. scala.actors Thread-based Event-driven actor{ actor{ while(true){ loop{ receive{ react{ case msg => case msg => } } } } } } ! !! !? ?
  • 8. Актер с состоянием • Модель publisher/subscriber – тривиальный подход - хранение в переменной protected var subscribers = List[Subscriber]() loop { react{ case AddSubscriber(subscriber) => subscribers = subscriber :: subscribers case Publish(event) => subscribers.foreach(_ ! event)
  • 9. Хранение состояния в Erlang Передача состояния в рекурсии: • «чистый» функциональный подход • требует поддержки оптимизации рекурсии loop(State) -> receive Msg -> NewState = whatever(Msg), loop(NewState) end.
  • 10. Модель publisher/subscriber • Передача состояния в рекурсии def loop(subscribers: List[Subscriber]): Unit = react{ case AddSubscriber(subscriber) => loop(subscriber :: subscribers) case Publish(event) => subscribers.foreach(_ ! event) loop(subscribers) } def act = loop(Nil)
  • 12. Идемпотентный актер Актер, устойчивый к получению дупликатов сообщений f(x) = f(f(x))
  • 13. Nested react/receive (вложенный обработчик) • обрабатывается только первое сообщение – остальные пропускаются loop { react { case Event(evt) => // необходимые вычисления... def skip: Unit = reactWithin(0) { case Event(event) if(event == evt) => skip case TIMEOUT => } skip
  • 14. Nested react/receive способен на большее: • обработка с приоритетом reactWithin(0){ case Event(evt: String) => subscribers.foreach(_ ! evt) case TIMEOUT => react { case AddSubscriber(subscriber) => subscribers = subscriber :: subscribers case Event(evt) => subscribers.foreach(_ ! evt)
  • 16. Типизированный актер • Процессы в Erlang не типизированы – Придает гибкость модели • Актеры, по своей природе, динамичны • HotSwap обработчика • Базовые актеры в Scala и Akka, следующие идеологии Erlang, тоже не типизированы
  • 17. Типизированные актеры иногда полезны: • !?, !!, !!! – известный тип «ответа» • специализация обработчиков
  • 18. • Scala <2.7.x - InputChannel[T] • Scala 2.8.x+ - Reactor[T] sealed trait Message class Foo extends Message class Bar extends Message class DatatypeReceiver[T >: Null <: Message] extends Reactor[T] Принимает сообщения подтипа Message
  • 19. Типизация актеров позволяет использовать всю мощь системы типов Scala – Typeclass паттерн implicit val fooReceiver = new DatatypeReceiver[Foo] implicit val barReceiver = new DatatypeReceiver[Bar] def send[T >: Null <: Message : DatatypeReceiver] (message: T) = implicitly[DatatypeReceiver[T]] ! message send(new Foo) Находит в контексте обработчик нужного типа
  • 20. Альтернативный подход • декларирование возможных типов сообщений в объекте-компаньоне • паттерн Active Object – типизированные актеры в Akka: trait Service { def serve(arg: String) } class ServiceImpl extends TypedActor with Service { def serve(arg: String) = //… } Выполняется service.serve(“foo”) асинхронно
  • 23. Тривиальное решение – блокирующий синхронный аггрегатор • аггрегатор не может обрабатывать новые сообщения, пока собирает ответы FAIL! react{ case Event(event) => val results = Futures.awaitAll(1000, reply(res) subscribers.map(_ !! event):_*) // обработка собранных ответов... reply(results)
  • 24. Можно прибегнуть к хитрости – перенести ожидание, обработку и ответ в другой поток • неэффективное использование – выделенный поток просто ждет react{ case Event(event) => actor{ val results = Futures.awaitAll(1000, subscribers.map(_ !! event):_*) // обработка собранных ответов... reply(results) }
  • 25. Aсинхронная аггрегация – решение в Erlang- стиле 1) канал для передачи результатов аггрегации 2) асинхронная сборка результатов: • ответы «рабочих» обрабатываются аггрегатором наравне с другими сообщениями • промежуточные результаты передаются рекурсивно
  • 26. class AsynchAggregator(workers: Iterable[Subscriber], replyChannel: Channel[Any]) extends Actor { def loop(results: List[Any]): Unit = react { case event: Event[Any] => workers foreach(_ ! event); loop(results) reply(Result(res)) case Result(res) => if(results.size != workers.size - 1) loop(res :: results) else { // обработка собранных результатов... replyChannel ! (res :: results); loop(Nil) }
  • 27. Клиентская сторона (синхронное окружение) • клиент ждет сообщение в канале, блокируя поток val aggregator = new AsynchAggregator(subscribers, replyChannel) aggregator ! Event("hello") replyChannel.receive{ case message => // результат работы аггрегатора }
  • 28. Клиентская сторона (синхронное окружение) • клиент ждет сообщение в канале, блокируя поток val aggregator = new AsynchAggregator(subscribers, replyChannel) actor { aggregator ! Event("hello") } replyChannel.receive{ case message => // результат работы аггрегатора }
  • 29. Другие библиотеки • Функциональный подход c Promises в Scalaz • Псевдо-императивный подход с Dataflow в Akka
  • 30. Scalaz Promise[T] Актер-работник асинхронно дает аггрегатору обещание (promise), и выполняет его react { case Message(msg) => val rez = new Promise[String]()(Strategy.Sequential) reply(rez) rez.fulfill{Thread sleep 1000; “Hello!”} }
  • 31. Scalaz Promise[T] Аггрегатор дает клиенту обещание результата, декларируя будущую аггрегацию и обработку case msg: Message => val res = workerz.map(worker => (worker !? msg) .asInstanceOf[Promise[String]]) .sequence .map{results => // обработка PROFIT!!! results } List[Promise[String]] => Promise[List[String]] reply(res)
  • 32. Akka Dataflow Dataflow concurrency – декларативная модель безопасного параллелизма Dataflow-переменная • Изменение значения вызывает цепную реакцию • Инициализируется единожды • Может безопасно использоваться в многопоточном окружении
  • 33. Akka Dataflow* Dataflow-переменные def sample{ val x0, x1, y0, y1 = Promise[Int]() Присвоение значения flow{ y0 << x0() + 1; println("y0 = " + y0()) y1 << x1() + y0(); println("y1 = " + y1()) } flow{ x0 << 1 } flow{ x1 << 2 } scala> sample } y0 = 2 y1 = 4 *базируется на continuations → нет lock’ов
  • 34. Как применить dataflow для scatter / gather? • Рассылка, и асинхронная инициализация dataflow-переменных val result = Promise[String]() val promises = List.fill(recipients.size)(Promise[String]()) recipients.zip(promises).map{case (recipient, promise) => (recipient !!! msg).map{result: String => flow{ promise << result } } }
  • 35. Аггрегатор def gather(promises: List[CompletableFuture[String]], result: String = ""): String @cps[Future[Any]] = promises match { case head :: tail => gather(tail, head() + result) case Nil => result } flow { result << gather(promises) }
  • 37. • Балансировка на уровне инфраструктуры • Актер-роутер, работающий с пулом актеров, выбирающий «работника» согласно некому алгоритму балансировки • Балансировка на уровне планировщика/диспетчера потоков • scala.actors: fork-join pool • Akka: work-stealing dispatchers
  • 38. Актер-роутер case class Ready(actor: class Balancer[A <: Actor](workers: Actor) Iterable[A]) extends Actor{ def worker = actor{ def act = loop{ loop{ react{ react{ case msg: Ready => case msg: Ready => case msg => reply(this) val _sender = sender case msg => workers foreach {_ ! Ready(this)} //обработка react { case Ready(worker) => worker.send(msg, _sender) } } }
  • 39. + • роутер незамедлительно узнает, когда появляется незанятый работник • роутер может работать с любыми типами актеров (локальные, удаленные) - • сообщения о статусе работников создают много «шума» • роутер заблокирован, пока не освободится какой-нибудь «работник»
  • 40. Более эффективное решение в рамках одной JVM - балансировка на уровне планировщика/ диспетчера потоков. Akka Пул актеров управляется work-stealing dispatcher. Если какой-то актер из пула не занят, он «крадет» сообщения из mailbox’а другого актера
  • 41. Akka: work-stealing dispatcher object MyActor { val dispatcher = Dispatchers.newExecutorBasedEvent> DrivenWorkStealingDispatcher(name).build } class MyActor extends Actor { self.dispatcher = MyActor.dispatcher ; ... } val actor1= actorOf[MyActor].start actor2 val actor2= actorOf[MyActor].start «крадет» сообщение actor1 ! LongRunningTask actor1 ! LongRunningTask
  • 43. “If somebody dies, other people will notice” Programming Erlang, Joe Armstrong
  • 44. Линки и ловушки – базовые элементы для построения систем на основе актеров Линки объединяют группу актеров в единую подсистему. Если один из актеров «умирает», прилинкованные актеры тоже прекращают работу actor { self link anotherActor … } Ловушка перехватывает сигнал выхода actor { self.trapExit = true … }
  • 45. Супервизор • супервизор – любой актер, прилинкованный к другому, и обрабатывающий сигнал выхода • supervisor (OTP) - если контролируемый актер умирает, перехватывает сигнал выхода, и принимает меры, в соответствии с выбранной стратегией
  • 46. Доступные реализации • Akka Supervisors • Scala-OTP – хороший выбор, если вы работаете с scala.actors
  • 47. Akka Supervisors Вдохновлены супервизорами из Erlang/OTP SupervisorConfig( OneForOneStrategy(List(classOf[Exception]), 3, 10), Supervise( myFirstActor, Стратегия поведения в Permanent) :: случае «смерти» актера Supervise( mySecondActor, Наблюдаемые актеры Permanent) :: Nil)
  • 48. транзакционный актер • каталог актеров и ресурсов • фасад процессов • многие другие