akka - RIP Tutorial · Akka - это инструментарий с открытым...

30
akka #akka

Transcript of akka - RIP Tutorial · Akka - это инструментарий с открытым...

Page 1: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

akka

#akka

Page 2: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

1

1: 2

2

Examples 2

2

2: Akka HTTP 4

4

Examples 4

Akka HTTP: Hello World (Scala DSL) 4

3: DSL 5

Examples 5

DSL 5

5

5

6

6

6

4: 8

Examples 8

8

5: 11

Examples 11

11

11

6: 13

13

Examples 13

? 13

16

? 16

17

Page 3: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

7: akka-streams 18

18

Examples 18

TwoThreeShape 18

8: Akka 20

Examples 20

Akka Streams: Hello World 20

-: 22

9: , 23

Examples 23

Akka hello world (Scala) 23

24

Akka Hello World (Java 8) 25

27

Page 4: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

ОколоYou can share this PDF with anyone you feel could benefit from it, downloaded the latest version from: akka

It is an unofficial and free akka ebook created for educational purposes. All the content is extracted from Stack Overflow Documentation, which is written by many hardworking individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official akka.

The content is released under Creative Commons BY-SA, and the list of contributors to each chapter are provided in the credits section at the end of this book. Images may be copyright of their respective owners unless otherwise specified. All trademarks and registered trademarks are the property of their respective company owners.

Use the content presented in this book at your own risk; it is not guaranteed to be correct nor accurate, please send your feedback and corrections to [email protected]

https://riptutorial.com/ru/home 1

Page 5: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 1: Начало работы с аккой

замечания

Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание параллельных и распределенных приложений на JVM. Он реализует модель актера, известную из Erlang.

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

Examples

Установка или настройка

Установите JDK 8 ( Windows , Linux ) и установите путь ( Windows ).1.

Установите Scala ( Linux ), для Windows посетите http://www.scala-lang.org/download/ загрузите и установите бинарный дистрибутив, установите переменную среды для scala в PATH, которая находится в \scala\bin .

2.

Установка активатора Typesafe (содержит Scala, Akka, Play, SBT) + проектные леса и шаблоны. Для быстрого запуска загрузите mini-package .

3.

Извлеките активатор Typesafe и установите PATH на activator-xxxx-minimal\bin minimum activator-xxxx-minimal\bin (он включает сценарии bash и bat для запуска активатора).

4.

Время для создания образца проекта и импорта в вашу любимую среду IDE.5.

Введите activator new в cmd / terminal.•

Вы можете выбрать 4 потому что пример Hello World основан на Scala.•

Импортируйте проект в свою любимую среду IDE и начинайте с примера Hello World .•

Готово !.•

https://riptutorial.com/ru/home 2

Page 6: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

Скачайте akka-2.0.zip дистрибутив Akka с http://akka.io/downloads/1.

Разархивируйте akka-2.0.zip в любом каталоге. (Пример - /home/USERNAME/tools/akka-2.0) Вы хотели бы установить Akka.

2.

Установите AKKA_HOME3.

Для Linux.

# First got to the installed location cd /home/USERNAME/tools/akka-2.0 # Export the location as AKKA_HOME export AKKA_HOME=`pwd` # Check if PATH is Exported. echo $AKKA_HOME /home/USERNAME/tools/akka-2.0

4.

Для Windows

# First got to the installed location C:\USERNAME\akka> cd akka-2.0 # Set the location as AKKA_HOME C:\USERNAME\akka\akka-2.0> set AKKA_HOME=%cd% # Check if PATH is Exported. C:\USERNAME\akka\akka\akka-2.0> echo %AKKA_HOME% C:\USERNAME\akka\akka-2.0

5.

Прочитайте Начало работы с аккой онлайн: https://riptutorial.com/ru/akka/topic/2041/начало-работы-с-аккой

https://riptutorial.com/ru/home 3

Page 7: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 2: Akka HTTP

Вступление

Akka HTTP - это легкий HTTP-сервер и клиентская библиотека, использующие akka-streams

под капотом

Examples

Сервер Akka HTTP: Hello World (Scala DSL)

Следующее приложение запустит HTTP-сервер, прослушивающий порт 8080, который возвращает Hello world в GET /hello/world

import akka.actor.ActorSystem import akka.http.scaladsl.Http import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server._ import akka.stream.ActorMaterializer import scala.concurrent.Await import scala.concurrent.duration.Duration object HelloWorld extends App { implicit val system = ActorSystem("ProxySystem") implicit val mat = ActorMaterializer() val route: Route = get { path("hello" / "world") { complete("Hello world") } } val bindingFuture = Http().bindAndHandle(Route.handlerFlow(route), "127.0.0.1", port = 8080) Await.result(system.whenTerminated, Duration.Inf) }

Прочитайте Akka HTTP онлайн: https://riptutorial.com/ru/akka/topic/10108/akka-http

https://riptutorial.com/ru/home 4

Page 8: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 3: Актер DSL

Examples

Простой актер DSL

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

import akka.actor.ActorDSL._ import akka.actor.ActorSystem implicit val system = ActorSystem("demo") val a = actor(new Act { become { case "hello" ⇒ sender() ! "hi" } })

Контекстное переключение

Два возможных способа выдачи контекста. (Заменяя или добавляя новое поведение) предлагаются отдельно, чтобы включить беспорядочную нотацию вложенных получателей:

val a = actor(new Act { become { // this will replace the initial (empty) behavior case "info" ⇒ sender() ! "A" case "switch" ⇒ becomeStacked { // this will stack upon the "A" behavior case "info" ⇒ sender() ! "B" case "switch" ⇒ unbecome() // return to the "A" behavior } case "lobotomize" ⇒ unbecome() // OH NOES: Actor.emptyBehavior } })

Управление жизненным циклом

Крючки жизненного цикла также отображаются как элементы DSL, где последующие вызовы методов, показанных ниже, заменят содержимое соответствующих крючков:

val a = actor(new Act { whenStarting { testActor ! "started" } whenStopping { testActor ! "stopped" } })

Вышеописанное достаточно, если логический жизненный цикл актера соответствует

https://riptutorial.com/ru/home 5

Page 9: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

циклам перезапуска (т. Е. КогдаStopping выполняется до перезапуска и когда начинается после этого). Если это нежелательно, используйте следующие два крючка:

val a = actor(new Act { become { case "die" ⇒ throw new Exception } whenFailing { case m @ (cause, msg) ⇒ testActor ! m } whenRestarted { cause ⇒ testActor ! cause } })

Вложенные актеры

Также возможно создать вложенных актеров, то есть внуков, таких как:

// here we pass in the ActorRefFactory explicitly as an example val a = actor(system, "fred")(new Act { val b = actor("barney")(new Act { whenStarting { context.parent ! ("hello from " + self.path) } }) become { case x ⇒ testActor ! x } })

надзор

Также можно назначить стратегию надзора для этих участников следующим образом:

superviseWith(OneForOneStrategy() { case e: Exception if e.getMessage == "hello" ⇒ Stop case _: Exception ⇒ Resume })

Поддержка прошивки

И последнее, но не менее важное: встроенная функция удобной магии, которая определяет, будет ли класс времени выполнения статически заданного подтипа субъекта расширять черту RequiresMessageQueue через черту Stash (это сложный способ сказать, что новый закон с Stash не работает, потому что его стираемый тип времени является просто анонимным подтипом Act). Целью является автоматическое использование соответствующего типа почтового ящика, требуемого Stash. Если вы хотите использовать эту магию, просто добавьте ActWithStash:

val a = actor(new ActWithStash { become { case 1 ⇒ stash() case 2 ⇒ testActor ! 2; unstashAll(); becomeStacked { case 1 ⇒ testActor ! 1; unbecome()

https://riptutorial.com/ru/home 6

Page 10: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

} } })

Прочитайте Актер DSL онлайн: https://riptutorial.com/ru/akka/topic/2392/актер-dsl

https://riptutorial.com/ru/home 7

Page 11: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 4: Включение зависимостей в актера

Examples

Весенний проводник

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

import akka.actor.Actor; import akka.actor.IndirectActorProducer; import java.lang.reflect.Constructor; import java.util.Arrays; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; /** * An actor producer that lets Spring autowire dependencies into created actors. */ public class SpringWiredActorProducer implements IndirectActorProducer { private final ApplicationContext applicationContext; private final Class<? extends Actor> actorBeanClass; private final Object[] args; public SpringWiredActorProducer(ApplicationContext applicationContext, Class<? extends Actor> actorBeanClass, Object... args) { this.applicationContext = applicationContext; this.actorBeanClass = actorBeanClass; this.args = args; } @Override public Actor produce() { Class[] argsTypes = new Class[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] == null) { argsTypes[i] = null; } else { argsTypes[i] = args[i].getClass(); } } Actor result = null; try { if (args.length == 0) { result = (Actor) actorBeanClass.newInstance(); } else { try { result = (Actor) actorBeanClass.getConstructor(argsTypes).newInstance(args); } catch (NoSuchMethodException ex) { // if types of constructor don't match exactly, try to find appropriate

https://riptutorial.com/ru/home 8

Page 12: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

constructor for (Constructor<?> c : actorBeanClass.getConstructors()) { if (c.getParameterCount() == args.length) { boolean match = true; for (int i = 0; match && i < argsTypes.length; i++) { if (argsTypes[i] != null) { match = c.getParameters()[i].getType().isAssignableFrom(argsTypes[i]); } } if (match) { result = (Actor) c.newInstance(args); break; } } } } } if (result == null) { throw new RuntimeException(String.format("Cannot find appropriate constructor for %s and types (%s)", actorBeanClass.getName(), Arrays.toString(argsTypes))); } else { applicationContext.getAutowireCapableBeanFactory().autowireBeanProperties(result, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true); } } catch (ReflectiveOperationException e) { throw new RuntimeException("Cannot instantiate an action of class " + actorBeanClass.getName(), e); } return result; } @Override public Class<? extends Actor> actorClass() { return (Class<? extends Actor>) actorBeanClass; } }

Этот продюсер создает экземпляр актера и вводит зависимости перед возвратом экземпляра актера.

Мы можем подготовить Props для создания актера с помощью SpringWiredActorProducer следующим образом:

Props.create(SpringWiredActorProducer.class, applicationContext, actorBeanClass, args);

Однако было бы лучше обернуть этот призыв следующей весенней фасолью:

import akka.actor.Extension; import akka.actor.Props; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component;

https://riptutorial.com/ru/home 9

Page 13: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

/** * An Akka Extension to inject dependencies to {@link akka.actor.Actor}s with * Spring. */ @Component public class SpringProps implements Extension, ApplicationContextAware { private volatile ApplicationContext applicationContext; /** * Creates a Props for the specified actorBeanName using the * {@link SpringWiredActorProducer}. * * @param actorBeanClass The class of the actor bean to create Props for * @param args arguments of the actor's constructor * @return a Props that will create the named actor bean using Spring */ public Props create(Class actorBeanClass, Object... args) { return Props.create(SpringWiredActorProducer.class, applicationContext, actorBeanClass, args); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }

Вы можете автоматически создавать SpringProps везде, где актер создается (даже в самом актере) и создавать пружинные актеры следующим образом:

@Autowired private SpringProps springProps; //... actorSystem.actorOf(springProps.create(ActorClass.class), actorName); //or inside an actor context().actorOf(springProps.create(ActorClass.class), actorName);

Предполагая, что ActorClass расширяет UntypedActor и имеет свойства, аннотированные с помощью @Autowired , эти зависимости будут введены сразу после создания экземпляра.

Прочитайте Включение зависимостей в актера онлайн: https://riptutorial.com/ru/akka/topic/4717/включение-зависимостей-в-актера

https://riptutorial.com/ru/home 10

Page 14: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 5: диспетчеры

Examples

Диспетчер по умолчанию

Акка MessageDispatcher - это то, что делает Акка Актеры «тикают», это двигатель машины, так сказать. Все реализации MessageDispatcher также являются ExecutionContext, а это означает, что они могут использоваться для выполнения произвольного кода, например Futures.

Каждая система ActorSystem будет иметь диспетчер по умолчанию, который будет использоваться в случае, если для актера не настроено ничего другого. Диспетчер по умолчанию может быть настроен и по умолчанию является Dispatcher с указанным default-executor . Если создается ActorSystem с переданным ExecutionContext , этот ExecutionContext

будет использоваться как исполнитель по умолчанию для всех диспетчеров в этой ActorSystem. Если не указан ExecutionContext, он будет akka.actor.default-dispatcher.default-executor.fallback исполнителю, указанному в akka.actor.default-dispatcher.default-executor.fallback . По умолчанию это fork-join-executor , который дает отличную производительность в большинстве случаев.

Настройка диспетчера для актера

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

my-dispatcher { # Dispatcher is the name of the event-based dispatcher type = Dispatcher # What kind of ExecutionService to use executor = "fork-join-executor" # Configuration for the fork join pool fork-join-executor { # Min number of threads to cap factor-based parallelism number to parallelism-min = 2 # Parallelism (threads) ... ceil(available processors * factor) parallelism-factor = 2.0 # Max number of threads to cap factor-based parallelism number to parallelism-max = 10 } # Throughput defines the maximum number of messages to be # processed per actor before the thread jumps to the next actor. # Set to 1 for as fair as possible. throughput = 100 }

И вот еще один пример, который использует «thread-pool-executor»:

https://riptutorial.com/ru/home 11

Page 15: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

my-thread-pool-dispatcher { # Dispatcher is the name of the event-based dispatcher type = Dispatcher # What kind of ExecutionService to use executor = "thread-pool-executor" # Configuration for the thread pool thread-pool-executor { # minimum number of threads to cap factor-based core number to core-pool-size-min = 2 # No of core threads ... ceil(available processors * factor) core-pool-size-factor = 2.0 # maximum number of threads to cap factor-based number to core-pool-size-max = 10 } # Throughput defines the maximum number of messages to be # processed per actor before the thread jumps to the next actor. # Set to 1 for as fair as possible. throughput = 100 }

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

akka.actor.deployment { /myactor { dispatcher = my-dispatcher } }

и создайте этого актера с именем, указанным в config:

import akka.actor.Props val myActor = context.actorOf(Props[MyActor], "myactor")

Или вы можете найти своего диспетчера с помощью:

import akka.actor.Props val myActor = context.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), "myactor1")

Прочитайте диспетчеры онлайн: https://riptutorial.com/ru/akka/topic/3228/диспетчеры

https://riptutorial.com/ru/home 12

Page 16: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 6: Надзор и мониторинг в Акке

замечания

Ссылки: akka.io/docs

Просмотрите мой блог: https://blog.knoldus.com/2016/08/07/supervision-and-monitoring-in-akka/

Examples

Что такое надзор?

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

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

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

Перезапуск: родитель запускает дочернего актера, очищая его внутреннее состояние.

Остановить: остановить ребенка навсегда.

Эскалация: эскалация сбоя путем отказа от себя и распространения отказа его родителям.

https://riptutorial.com/ru/home 13

Page 17: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

Жизненный цикл Akka

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

https://riptutorial.com/ru/home 14

Page 18: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

Система исполнителей: Источник: doc.akka.io

/ пользователь: Актер пользователя Guardian

Актер, созданный с использованием system.actorOf (), является дочерним элементом пользователя-опекуна. Всякий раз, когда опекун пользователя завершается, все созданные пользователем участники также будут прерваны. Пользователь, созданный пользователем верхнего уровня, определяется персонажем-хранителем, как они будут контролироваться. Root Guardian - супервизор пользователя-хранителя.

/ root: Корневой хранитель

Коренный опекун-актер является отцом всей системы актеров. Он контролирует актера-опекуна и системного опекуна-актера.

https://riptutorial.com/ru/home 15

Page 19: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

Стратегии надзора

Существует два типа стратегий надзора, которыми мы следуем, чтобы контролировать любого актера:

Стратегия «один-к-одному»1.

Стратегия «один для всех»2.

case object ResumeException extends Exception case object StopException extends Exception case object RestartException extends Exception override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 second){ case ResumeException => Resume case RestartException => Restart case StopException => Stop case _: Exception => Escalate }

Что такое мониторинг?

Мониторинг жизненного цикла в Акке обычно называется DeathWatch.

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

https://riptutorial.com/ru/home 16

Page 20: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

мониторинг

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

Репозиторий кода

Наблюдение и мониторинг

Прочитайте Надзор и мониторинг в Акке онлайн: https://riptutorial.com/ru/akka/topic/7831/

надзор-и-мониторинг-в-акке

https://riptutorial.com/ru/home 17

Page 21: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 7: Пользовательские формы akka-streams

замечания

akka предоставляет некоторые предопределенные формы, которые, вероятно, должны соответствовать 99,9% вашего использования. создание новой формы должно выполняться только в очень редких случаях. предопределенные формы:

Source - 1 розетка, нет входов•

Sink - 1 вход, без розетки•

Flow - 1 вход, 1 выход•

BidiFlow - 2 входа, 2 выхода•

Closed - нет входов, нет выходов•

FanInN - N ( N <= 22), 1 выход•

FanOutN - N ( N <= 22), 1 вход•

UniformFanIn - любое количество входов одного и того же типа, 1 выход•

UniformFanOut - любое количество выходов одного типа, 1 вход•

Amorphous - любое количество входов или выходов, но нетипизированное.•

Examples

TwoThreeShape

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

case class TwoThreeShape[-In1, -In2, +Out1, +Out2, +Out3]( in1: Inlet[In1@uncheckedVariance], in2: Inlet[In2@uncheckedVariance], out1: Outlet[Out1@uncheckedVariance], out2: Outlet[Out2@uncheckedVariance], out3: Outlet[Out3@uncheckedVariance]) extends Shape { override val inlets: immutable.Seq[Inlet[_]] = List(in1, in2) override val outlets: immutable.Seq[Outlet[_]] = List(out1, out2, out3) override def deepCopy(): TwoThreeShape[In1, In2, Out1, Out2, Out3] = TwoThreeShape(in1.carbonCopy(), in2.carbonCopy(), out1.carbonCopy(), out2.carbonCopy(), out3.carbonCopy()) override def copyFromPorts(inlets: immutable.Seq[Inlet[_]], outlets: immutable.Seq[Outlet[_]]): Shape = {

https://riptutorial.com/ru/home 18

Page 22: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

require(inlets.size == 2, s"proposed inlets [${inlets.mkString(", ")}] do not fit TwoThreeShape") require(outlets.size == 3, s"proposed outlets [${outlets.mkString(", ")}] do not fit TwoThreeShape") TwoThreeShape(inlets(0), inlets(1), outlets(0), outlets(1), outlets(2)) } }

пример использования для этой странной формы: этап, который пройдет через элементы из 2 потоков, сохраняя при этом соотношение количества элементов, переданных в потоках:

def ratioCount[X,Y]: Graph[TwoThreeShape[X,Y,X,Y,(Int,Int)],NotUsed] = { GraphDSL.create() { implicit b => import GraphDSL.Implicits._ val x = b.add(Broadcast[X](2)) val y = b.add(Broadcast[Y](2)) val z = b.add(Zip[Int,Int]) x.out(1).conflateWithSeed(_ => 1)((count,_) => count + 1) ~> z.in0 y.out(1).conflateWithSeed(_ => 1)((count,_) => count + 1) ~> z.in1 TwoThreeShape(x.in,y.in,x.out(0),y.out(0),z.out) } }

Прочитайте Пользовательские формы akka-streams онлайн: https://riptutorial.com/ru/akka/topic/3282/пользовательские-формы-akka-streams

https://riptutorial.com/ru/home 19

Page 23: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 8: Потоки Akka

Examples

Akka Streams: Hello World

Akka Streams позволяет вам легко создавать поток, используя возможности инфраструктуры Akka без явного определения поведения и сообщений актера. Каждый поток будет иметь по крайней мере один Source (источник данных) и по крайней мере один Sink (назначение данных).

import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl.{Sink, Source} import java.io.File val stream = Source(Seq("test1.txt", "test2.txt", "test3.txt")) .map(new File(_)) .filter(_.exists()) .filter(_.length() != 0) .to(Sink.foreach(f => println(s"Absolute path: ${f.getAbsolutePath}")))

В этом кратком примере у нас есть Seq имен файлов, которые мы вводим в поток. Сначала мы сопоставляем их с File , затем отфильтровываем файлы, которые не существуют, а затем файлы, длина которых равна 0. Если файл прошел через фильтры, он печатается в stdout .

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

import akka.actor.ActorSystem import akka.stream.ActorMaterializer import akka.stream.scaladsl.{Sink, Source} import java.io.File implicit val actorSystem = ActorSystem("system") implicit val actorMaterializer = ActorMaterializer() val source = Source(List("test1.txt", "test2.txt", "test3.txt")) val mapper = Flow[String].map(new File(_)) val existsFilter = Flow[File].filter(_.exists()) val lengthZeroFilter = Flow[File].filter(_.length() != 0) val sink = Sink.foreach[File](f => println(s"Absolute path: ${f.getAbsolutePath}")) val stream = source .via(mapper) .via(existsFilter) .via(lengthZeroFilter) .to(sink)

https://riptutorial.com/ru/home 20

Page 24: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

stream.run()

Во второй версии мы можем видеть , что mapper , existsFilter , lengthZeroFilter являются Flow s. Вы можете создать их в потоке, используя метод via . Эта возможность позволит вам повторно использовать фрагменты кода. Важно отметить, что Flow может быть апатридом или состоянием. В случае состояния состояния вы должны быть осторожны при повторном использовании.

Вы также можете думать о потоках как о Graphs . Akka Streams также предоставляет мощный GraphDSL для GraphDSL определения сложных потоков. Следуя тому же примеру, мы могли бы сделать:

import java.io.File import akka.actor.ActorSystem import akka.stream.{ActorMaterializer, ClosedShape} import akka.stream.scaladsl.{Flow, GraphDSL, RunnableGraph, Sink, Source} implicit val actorSystem = ActorSystem("system") implicit val actorMaterializer = ActorMaterializer() val graph = RunnableGraph.fromGraph(GraphDSL.create() { implicit b => import GraphDSL.Implicits._ val source = Source(List("test1.txt", "test2.txt", "test3.txt")) val mapper = Flow[String].map(new File(_)) val existsFilter = Flow[File].filter(_.exists()) val lengthZeroFilter = Flow[File].filter(_.length() != 0) val sink = Sink.foreach[File](f => println(s"Absolute path: ${f.getAbsolutePath}")) source ~> mapper ~> existsFilter ~> lengthZeroFilter ~> sink ClosedShape }) graph.run()

Также возможно создать агрегированный поток, используя GraphDSL . Например, если мы хотим объединить картограф и два фильтра в одном, что мы могли бы сделать:

val combinedFlow = Flow.fromGraph(GraphDSL.create() { implicit builder => import GraphDSL.Implicits._ val mapper = builder.add(Flow[String].map(new File(_))) val existsFilter = builder.add(Flow[File].filter(_.exists())) val lengthZeroFilter = builder.add(Flow[File].filter(_.length() != 0)) mapper ~> existsFilter ~> lengthZeroFilter FlowShape(mapper.in, lengthZeroFilter.out) })

И затем используйте его как отдельный блок. combinedFlow FlowShape будет FlowShape или PartialGraph . Мы можем, например, с via :

https://riptutorial.com/ru/home 21

Page 25: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

val stream = source .via(combinedFlow) .to(sink) stream.run()

Или используя GraphDSL :

val graph = RunnableGraph.fromGraph(GraphDSL.create() { implicit b => import GraphDSL.Implicits._ val source = Source(List("test1.txt", "test2.txt", "test3.txt")) val sink = Sink.foreach[File](f => println(s"Absolute path: ${f.getAbsolutePath}")) source ~> combinedFlow ~> sink ClosedShape }) graph.run()

Акка-потоки: субпотоки

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

val sumByKey: Flow[(String, Int), Int, NotUsed] = Flow[(String, Int)]. groupBy(Int.maxValue, _._1). //forks the flow map(_._2). //this is applied to each subflow fold(0)(_ + _). mergeSubstreams //the subflow outputs are merged back together

Прочитайте Потоки Akka онлайн: https://riptutorial.com/ru/akka/topic/7394/потоки-akka

https://riptutorial.com/ru/home 22

Page 26: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

глава 9: Привет, мир

Examples

Akka hello world (Scala)

Добавить зависимость akka-actor (пример SBT)1.

libraryDependencies += "com.typesafe.akka" % "akka-actor_2.11" % "2.4.8"

Создание классов актеров:2.

Актер для вывода строки:

class OutputActor extends Actor { override def receive: Receive = { case message => println(message) } }

Актер для модификации строки:

class AppendActor(outputActor: ActorRef) extends Actor { override def receive: Receive = { case message: String => val changed = s"Hello, $message!" outputActor ! changed case unknown => println(s"unknown message: $unknown") } }

Создавать актерские системы и отправлять сообщения3.

object HelloWorld extends App { val system = ActorSystem("HelloWorld") val outputActor = system.actorOf(Props[OutputActor], name = "output") val appendActor = system.actorOf(Props(classOf[AppendActor], outputActor), name = "appender") appendActor ! "Akka" // send test message Thread.sleep(500) // wait for async evaluation system.terminate() // terminate actors system }

Выход программы:

Привет, Акка!

https://riptutorial.com/ru/home 23

Page 27: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

Простая актерская реализация

Рассмотрите связь между Сотрудником и его отделом кадров.

В широком смысле это объясняется в следующих шести шагах, когда сообщение передается актеру:

Сотрудник создает что-то, называемое ActorSystem .1.

https://riptutorial.com/ru/home 24

Page 28: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

Он использует ActorSystem для создания чего-то, называемого ActorRef . Сообщение (MSG) отправляется в ActorRef (прокси-сервер для ActorRef HR).

2.

Актер ref передает сообщение вместе с Message Dispatcher .3.

Грузоотправитель ставит в очередь сообщения в целевом Актере MailBox .4.

Затем Диспетчер помещает Mailbox в поток (подробнее об этом в следующем разделе).5.

MailBox удаляет сообщение и, в конечном итоге, делегирует его фактическому методу receive персонажа.

6.

/** The Main Program consider it as a Employee Actor that is sending the requests **/ object EmployeeActorApp extends App{ //Initialize the ActorSystem val actorSystem=ActorSystem("HrMessageingSystem") //construct the HR Actor Ref val hrActorRef=actorSystem.actorOf(Props[HrActor]) //send a message to the HR Actor hrActorRef!Message //Let's wait for a couple of seconds before we shut down the system Thread.sleep (2000) //Shut down the ActorSystem. actorSystem.shutdown() } /** The HRActor reads the message sent to it and performs action based on the message Type **/ class HRActor extends Actor { def receive = { case s: String if(s.equalsIgnoreCase(“SICK”)) => println("Sick Leave applied”) case s: String if(s.equalsIgnoreCase(“PTO”)) => println("PTO applied “) }

}

Akka Hello World (Java 8)

Добавьте эту зависимость в свой проект POM:

<dependency> <groupId>com.typesafe.akka</groupId> <artifactId>akka-actor_2.11</artifactId> <version>2.4.4</version> </dependency>

Создать актер

https://riptutorial.com/ru/home 25

Page 29: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

public class HelloWorldActor extends AbstractActor { public HelloActor() { receive(ReceiveBuilder .match(SayHello.class, this::sayHello) .match(SayBye.class, this::sayBye) .build()); } private void sayHello(final SayHello message) { System.out.println("Hello World"); } private void sayHello(final SayBye message) { System.out.println("Bye World"); } public static Props props() { return Props.create(HelloWorldActor.class); } }

Создайте тест Junit для актера

public class HelloActorTest { private ActorSystem actorSystem; @org.junit.Before public void setUp() throws Exception { actorSystem = ActorSystem.create(); } @After public void tearDown() throws Exception { JavaTestKit.shutdownActorSystem(actorSystem); } @Test public void testSayHello() throws Exception { new JavaTestKit(actorSystem) { { ActorRef helloActorRef = actorSystem.actorOf(HelloWorldActor.props()); helloActorRef.tell(new SayHello(), ActorRef.noSender()); helloActorRef.tell(new SayBye(), ActorRef.noSender()); } }; } }

Прочитайте Привет, мир онлайн: https://riptutorial.com/ru/akka/topic/3283/привет--мир

https://riptutorial.com/ru/home 26

Page 30: akka - RIP Tutorial · Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание

кредиты

S. No

Главы Contributors

1Начало работы с аккой

12Sandy, Community, noelyahan

2 Akka HTTP Cyrille Corpet, Konrad 'ktoso' Malawski

3 Актер DSL Martin Seeler

4Включение зависимостей в актера

Oleg Kurbatov

5 диспетчеры Martin Seeler

6Надзор и мониторинг в Акке

Prabhat Kashyap

7Пользовательские формы akka-streams

gilad hoch

8 Потоки Akka Cyrille Corpet, hveiga

9 Привет, мир12Sandy, Cortwave, Fabien Benoit-Koch, Konrad 'ktoso' Malawski, tmbo

https://riptutorial.com/ru/home 27