akka · introduction akka http est un serveur http léger et une bibliothèque client, utilisant...

30
akka #akka

Upload: others

Post on 22-May-2020

23 views

Category:

Documents


0 download

TRANSCRIPT

akka

#akka

Table des matières

À propos 1

Chapitre 1: Commencer avec akka 2

Remarques 2

Examples 2

Installation ou configuration 2

Chapitre 2: Acteur DSL 4

Examples 4

Simple Acteur DSL 4

Changement de contexte 4

La gestion du cycle de vie 4

Acteurs imbriqués 5

Surveillance 5

Support stash 5

Chapitre 3: Akka HTTP 7

Introduction 7

Examples 7

Serveur HTTP Akka: Hello World (Scala DSL) 7

Chapitre 4: Akka Streams 8

Examples 8

Akka Streams: Bonjour tout le monde 8

Akka-Streams: sous-flux 10

Chapitre 5: akka-streams formes personnalisées 11

Remarques 11

Examples 11

TwoThreeShape 11

Chapitre 6: Bonjour le monde 13

Examples 13

Akka hello world (Scala) 13

Implémentation simple d'acteur 14

Akka Hello World (Java 8) 15

Chapitre 7: Injecter des dépendances dans un acteur 17

Examples 17

Acteur de printemps 17

Chapitre 8: Répartiteurs 20

Examples 20

Répartiteur par défaut 20

Définition du répartiteur pour un acteur 20

Chapitre 9: Supervision et surveillance à Akka 22

Remarques 22

Examples 22

Qu'est ce que la supervision? 22

Stratégies de supervision 24

Qu'est-ce que la surveillance? 25

Référentiel de code 26

Crédits 27

À propos

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/fr/home 1

Chapitre 1: Commencer avec akka

Remarques

Akka est un toolkit open source et une exécution simplifiant la construction d'applications concurrentes et distribuées sur la JVM. Il implémente le modèle d'acteur connu d'Erlang.

Il devrait également mentionner tous les grands sujets dans Akka, et établir un lien avec les sujets connexes. La documentation pour Akka étant nouvelle, vous devrez peut-être créer des versions initiales de ces rubriques connexes.

Examples

Installation ou configuration

Installez JDK 8 ( Windows , Linux ) et définissez le chemin ( Windows ).1. Installez Scala ( Linux ), pour Windows visitez http://www.scala-lang.org/download/ download et installez la distribution binaire, définissez la variable d'environnement pour scala dans PATH qui se trouve dans \scala\bin .

2.

Installation de l' activateur Typesafe (contient Scala, Akka, Play, SBT) + échafaudages et modèles de projet. Pour un démarrage rapide, téléchargez le mini-package .

3.

Extrayez l'activateur Typesafe et définissez PATH sur activator-xxxx-minimal\bin (il inclut les scripts bash et bat pour exécuter l'activateur).

4.

Il est temps de créer un projet exemple et d'importer dans votre IDE préféré.5.

Type d' activator new en cmd / terminal.•

Vous pouvez choisir 4 car l' exemple de Hello World est basé sur Scala.•Importez le projet dans votre IDE favori et commencez par l' exemple Hello World .•Terminé !.•

Téléchargez la distribution akka-2.0.zip d'Akka depuis http://akka.io/downloads/1.

Décompressez akka-2.0.zip dans n'importe quel répertoire. (Exemple - /home/USERNAME/tools/akka-2.0) Vous souhaitez que Akka soit installé.

2.

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

Définir le AKKA_HOME3.

Pour 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.

Pour les fenêtres

# 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.

Lire Commencer avec akka en ligne: https://riptutorial.com/fr/akka/topic/2041/commencer-avec-akka

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

Chapitre 2: Acteur DSL

Examples

Simple Acteur DSL

Pour créer des acteurs simples sans créer de nouvelle classe, vous pouvez utiliser:

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

Changement de contexte

Les deux manières possibles d’émettre un contexte.et devenir (remplacer ou ajouter le nouveau comportement) sont offertes séparément pour permettre une notation sans encombrement des réceptions imbriquées:

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 } })

La gestion du cycle de vie

Les hooks de cycle de vie sont également exposés en tant qu'éléments DSL, où les invocations ultérieures des méthodes indiquées ci-dessous remplaceront le contenu des hooks respectifs:

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

Ce qui précède est suffisant si le cycle de vie logique de l'acteur correspond aux cycles de redémarrage (c'est-à-dire lorsque WhenStopping est exécuté avant un redémarrage et quand Startart est lancé ultérieurement). Si cela n'est pas souhaité, utilisez les deux crochets suivants:

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

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

Acteurs imbriqués

Il est également possible de créer des acteurs imbriqués, par exemple des petits-enfants, comme ceci:

// 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 } })

Surveillance

Il est également possible d'affecter une stratégie de supervision à ces acteurs avec les éléments suivants:

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

Support stash

Last but not least, il y a un petit peu de commodité intégré à la magie, qui détecte si la classe d'exécution du sous-type d'acteur donné de manière statique étend le caractèreéchelle RequiertMessageQueue (c'est une manière compliquée de dire que ne fonctionne pas parce que son type d’exécution est juste un sous-type anonyme de Act). Le but est d'utiliser automatiquement le type de boîte aux lettres basé sur Deque requis par Stash. Si vous voulez utiliser cette magie, étendez simplement ActWithStash:

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

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

Lire Acteur DSL en ligne: https://riptutorial.com/fr/akka/topic/2392/acteur-dsl

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

Chapitre 3: Akka HTTP

Introduction

Akka HTTP est un serveur HTTP léger et une bibliothèque client, utilisant des flux Akka sous le capot

Examples

Serveur HTTP Akka: Hello World (Scala DSL)

L'application suivante va démarrer un serveur HTTP écoutant sur le port 8080 qui renvoie Hello world sur 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) }

Lire Akka HTTP en ligne: https://riptutorial.com/fr/akka/topic/10108/akka-http

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

Chapitre 4: Akka Streams

Examples

Akka Streams: Bonjour tout le monde

Akka Streams vous permet de créer facilement un flux exploitant la puissance du framework Akka sans définir explicitement les comportements et les messages des acteurs. Chaque flux aura au moins une Source (origine des données) et au moins un Sink (destination des données).

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}")))

Dans cet exemple , nous avons un rapide Seq de noms de fichiers que nous entrée dans le flux. Tout d'abord, nous les mappons sur un File , puis nous filtrons les fichiers qui n'existent pas, puis les fichiers dont la longueur est 0. Si un fichier passe par les filtres, il est imprimé dans la stdout .

Les flux Akka vous permettent également de faire des flux de manière modulaire. Vous pouvez créer des Flow avec les modules partiels de votre flux. Si nous prenons le même exemple, nous pourrions aussi faire:

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) stream.run()

Dans cette seconde version, nous pouvons voir que mapper , existsFilter , lengthZeroFilter est

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

Flow s. Vous pouvez les composer en flux en utilisant la méthode via . Cette fonctionnalité vous permettrait de réutiliser vos morceaux de code. Une chose importante à mentionner est que Flow peut être sans état ou avec état. Dans le cas de stateful, vous devez faire attention lorsque vous les réutilisez.

Vous pouvez également penser aux flux sous forme de Graphs . Akka Streams fournit également un puissant GraphDSL pour définir des flux complexes de manière simple. Suivant le même exemple que nous pourrions faire:

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

Il est également possible de créer un flux agrégé à l'aide de GraphDSL . Par exemple, si nous aimerions combiner le mappeur et deux filtres en un, nous pourrions faire:

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) })

Et ensuite l'utiliser comme un bloc individuel. combinedFlow serait un FlowShape ou un PartialGraph . Nous pouvons nous par exemple avec via :

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

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

stream.run()

Ou en utilisant le 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()

Akka-Streams: sous-flux

Vous pouvez dynamiser dynamiquement un flux dans plusieurs sous-flux à l'aide de groupBy . Les étapes continues sont appliquées à chaque sous-flux jusqu'à ce que vous les mergeSubstreams aide de 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

Lire Akka Streams en ligne: https://riptutorial.com/fr/akka/topic/7394/akka-streams

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

Chapitre 5: akka-streams formes personnalisées

Remarques

Akka fournit des formes prédéfinies, qui devraient probablement correspondre à 99,9% de votre utilisation. créer une nouvelle forme ne devrait être fait que dans de très rares cas. les formes prédéfinies sont:

Source - 1 sortie, pas de prise•Sink - 1 entrée, pas de sortie•Flow - 1 entrée, 1 sortie•BidiFlow - 2 entrées, 2 sorties•Closed - pas d'entrée, pas de sortie•FanInN - N entrées ( N <= 22), 1 sortie•FanOutN - N sorties ( N <= 22), 1 entrée•UniformFanIn - n'importe quel nombre d'entrées du même type, 1 prise•UniformFanOut - nombre quelconque de prises du même type, 1 entrée•Amorphous - nombre quelconque d’entrées ou de sorties, mais non typé.•

Examples

TwoThreeShape

Un exemple simple de définition d'une forme personnalisée avec 2 entrées et 3 sorties.

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 = { 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")

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

TwoThreeShape(inlets(0), inlets(1), outlets(0), outlets(1), outlets(2)) } }

un exemple d'utilisation de cette forme étrange: une étape qui traversera des éléments de 2 flux, tout en gardant un ratio du nombre d'éléments passés dans les flux:

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) } }

Lire akka-streams formes personnalisées en ligne: https://riptutorial.com/fr/akka/topic/3282/akka-streams-formes-personnalisees

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

Chapitre 6: Bonjour le monde

Examples

Akka hello world (Scala)

Ajouter une dépendance akka-actor (exemple SBT)1.

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

Créer des classes d'acteur:2.

Acteur pour la sortie de chaîne:

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

Acteur de modification de chaîne:

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") } }

Créer des systèmes d'acteurs et envoyer des messages3.

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 }

Sortie du programme:

Bonjour, Akka!

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

Implémentation simple d'acteur

Envisagez une communication entre un employé et son service des ressources humaines.

En gros, ceux-ci sont expliqués dans les six étapes suivantes lorsqu'un message est transmis à l'acteur:

L'employé crée un système appelé ActorSystem .1.

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

Il utilise ActorSystem pour créer quelque chose appelé ActorRef . Le message (MSG) est envoyé à ActorRef (un proxy pour HR Actor).

2.

Actor ref transmet le message à un Message Dispatcher .3.

Le répartiteur place le message dans la MailBox aux MailBox l'acteur cible.4.

Le répartiteur place alors la Mailbox aux Mailbox sur un fil (plus à ce sujet dans la section suivante).

5.

MailBox un message et le délègue éventuellement à la méthode de receive l'acteur HR.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)

Ajoutez cette dépendance à votre projet POM:

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

Créer un acteur

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

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); } }

Créer un test Junit pour l'acteur

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()); } }; } }

Lire Bonjour le monde en ligne: https://riptutorial.com/fr/akka/topic/3283/bonjour-le-monde

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

Chapitre 7: Injecter des dépendances dans un acteur

Examples

Acteur de printemps

En raison de l'instanciation d'acteur très spécifique, l'injection de dépendances dans une instance d'acteur n'est pas triviale. Afin d'intervenir dans l'instanciation de l'acteur et permettre à Spring d'injecter des dépendances, il convient de mettre en œuvre quelques extensions akka. Le premier est un 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) {

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

// if types of constructor don't match exactly, try to find appropriate 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; } }

Ce producteur instancie un acteur et injecte des dépendances avant de renvoyer l'instance d'acteur.

Nous pouvons préparer Props pour la création d'un acteur en utilisant le SpringWiredActorProducer la manière suivante:

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

Cependant, il serait préférable d'envelopper cet appel dans la fève de printemps suivante:

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/fr/home 18

/** * 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; } }

Vous pouvez créer automatiquement des SpringProps partout où un acteur est créé (même dans l'acteur lui-même) et créer des acteurs au printemps de la manière suivante:

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

En supposant ActorClass étend UntypedActor et possède des propriétés annotées avec @Autowired , ces dépendances seront injectées juste après l'instanciation.

Lire Injecter des dépendances dans un acteur en ligne: https://riptutorial.com/fr/akka/topic/4717/injecter-des-dependances-dans-un-acteur

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

Chapitre 8: Répartiteurs

Examples

Répartiteur par défaut

Un Akka MessageDispatcher est ce qui fait que les Acteurs Akka "cèdent", c'est le moteur de la machine pour ainsi dire. Toutes les implémentations MessageDispatcher sont également un ExecutionContext, ce qui signifie qu'elles peuvent être utilisées pour exécuter du code arbitraire, par exemple Futures.

Chaque ActorSystem aura un répartiteur par défaut qui sera utilisé si rien d'autre n'est configuré pour un acteur. Le répartiteur par défaut peut être configuré et est, par défaut, un Dispatcher avec l' default-executor spécifié. Si un ActorSystem est créé avec un objet ExecutionContext transmis, cet objet ExecutionContext sera utilisé comme exécuteur par défaut pour tous les répartiteurs de ce système ActorSystem. Si aucun ExecutionContext n'est donné, il sera renvoyé à l'exécuteur spécifié dans akka.actor.default-dispatcher.default-executor.fallback . Par défaut, il s’agit d’un fork-join-executor , ce qui donne d’excellentes performances dans la plupart des cas.

Définition du répartiteur pour un acteur

Donc, si vous voulez donner à votre acteur un répartiteur différent de celui par défaut, vous devez faire deux choses, la première étant de configurer le répartiteur dans votre 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 }

Et voici un autre exemple qui utilise le "thread-pool-executor":

my-thread-pool-dispatcher { # Dispatcher is the name of the event-based dispatcher type = Dispatcher # What kind of ExecutionService to use

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

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 }

Vous pouvez ensuite définir le distributeur à utiliser pour votre acteur à l'intérieur de votre configuration, par exemple

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

et créez cet acteur avec le nom spécifié dans la configuration:

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

Ou vous pouvez rechercher votre répartiteur avec:

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

Lire Répartiteurs en ligne: https://riptutorial.com/fr/akka/topic/3228/repartiteurs

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

Chapitre 9: Supervision et surveillance à Akka

Remarques

Références: akka.io/docs

Consultez mon blog: https://blog.knoldus.com/2016/08/07/supervision-and-monitoring-in-akka/

Examples

Qu'est ce que la supervision?

Décrit une relation de dépendance entre les acteurs, la relation parent-enfant. Le parent est unique car il a créé l'acteur enfant, de sorte que le parent est responsable de réagir lorsque des échecs surviennent chez son enfant.

Et le parent décide quel choix doit être sélectionné. Lorsqu'un parent reçoit le signal d'échec de son enfant, en fonction de la nature de l'échec, le parent décide parmi les options suivantes:

CV: Parent démarre l'acteur enfant en conservant son état interne.

Redémarrer: le parent démarre l'acteur enfant en effaçant son état interne.

Stop: Arrêtez l'enfant en permanence.

Escalate: Escalade la panne en échouant elle-même et propage la panne à son parent.

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

Cycle de vie Akka

Il est toujours important de voir une partie de la hiérarchie de supervision, ce qui explique l'option d'escalade. Chaque superviseur doit couvrir tous les cas d'échec possibles.

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

Système d'acteur: Source: doc.akka.io

/ user: L'acteur User Guardian

Les acteurs créés à l'aide de system.actorOf () sont des enfants de l'acteur utilisateur gardien. Chaque fois que l'utilisateur gardien se termine, tous les acteurs créés par l'utilisateur seront également terminés. Les acteurs créés par les utilisateurs de haut niveau sont déterminés par l'utilisateur acteur gardien de la manière dont ils seront supervisés. Root Guardian est le superviseur du tuteur utilisateur.

/ root: Le gardien racine

L'acteur de gardien racine est le père de tous les acteurs. Il supervise l'utilisateur acteur gardien et acteur système gardien.

Stratégies de supervision

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

Il existe deux types de stratégies de supervision que nous suivons pour superviser un acteur:

Stratégie un pour un1.

Stratégie Un pour Tous2.

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 }

Qu'est-ce que la surveillance?

La surveillance du cycle de vie dans Akka est généralement appelée DeathWatch.

La surveillance est donc utilisée pour lier un acteur à un autre afin de réagir à la terminaison de l'autre acteur, contrairement à la supervision qui réagit à un échec.

surveillance

La surveillance est particulièrement utile si un superviseur ne peut pas simplement redémarrer ses enfants et doit les terminer, par exemple en cas d'erreurs lors de l'initialisation des acteurs. Dans ce cas, il convient de surveiller ces enfants et de les recréer ou de planifier leur exécution

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

ultérieurement.

Référentiel de code

Supervision et surveillance

Lire Supervision et surveillance à Akka en ligne: https://riptutorial.com/fr/akka/topic/7831/supervision-et-surveillance-a-akka

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

Crédits

S. No

Chapitres Contributeurs

1Commencer avec akka

12Sandy, Community, noelyahan

2 Acteur DSL Martin Seeler

3 Akka HTTP Cyrille Corpet, Konrad 'ktoso' Malawski

4 Akka Streams Cyrille Corpet, hveiga

5akka-streams formes personnalisées

gilad hoch

6 Bonjour le monde12Sandy, Cortwave, Fabien Benoit-Koch, Konrad 'ktoso' Malawski, tmbo

7Injecter des dépendances dans un acteur

Oleg Kurbatov

8 Répartiteurs Martin Seeler

9Supervision et surveillance à Akka

Prabhat Kashyap

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