Translation Play2 Integrated Akka

Source: Internet
Author: User
Tags bind documentation static class time limit

SOURCE Https://www.playframework.com/documentation/2.5.x/JavaAkka#Scheduling-asynchronous-tasks
Akka uses the Actor model to provide an abstraction layer, providing a better platform to build the right multi-threaded and extensible applications. In terms of fault tolerance, the ' Let it Crash ' model, which has been successfully used in communications, is used primarily to build a never-stop self-health system. Actors provides an abstraction for transport distribution, providing the basis for scalable and fault-tolerant applications. The application actor System

The Akka can work with several actor system containers. An actor System Management resource, which is configured to run the system-included actors.

Play application (that is, the normal play instance, which we no longer translate) defines and uses a special actor system (perhaps called the actor systems or something else, which we do not translate, and which we are interested in to access the relevant information). The actor system has the same life cycle as the application and restarts automatically with the application reboot. Writing Actors

To use Akka, you first need to write an actor. The following is a simple actor who will simply answer hello, no matter who asks it.

Package actors;

Import akka.actor.*;
Import actors. helloactorprotocol.*;

public class Helloactor extends Untypedactor {public

    static Props Props = Props.create (helloactor.class);

    public void OnReceive (Object msg) throws Exception {
        if (msg instanceof SayHello) {
            sender (). Tell ("Hello," + ((Sa Yhello) msg). Name, self ());}}}

Note that here Helloactor defines a static domain props, which returns a props object that describes how to create an actor. This is a good Akka convention, separating the instantiated logic from the code that created the actor.

Another good point to show here is that the information sent and received by Helloactor is designated as a static inner class of another class called Helloactorprotocol.

Package actors;

public class Helloactorprotocol {public

    static class SayHello {public
        final String name;

        Public SayHello (String name) {
            this.name = name;}}
}
Create and use actors

To create (and/or) use the actor, you need a actorsystem (this kind of proper noun we do not translate). You can get actorsystem by declaring a dependency on actorsystem, and then use the Actorof method to create a new actor.

The most basic thing you can do with the actor is to send a message. When a message is sent to ctor, the message is consumed and forgotten, and the actor does not answer. This is the so-called tell (this is not translated) mode.

However, in Web apllication, the tell pattern is generally useless because HTTP is a protocol that contains requests and responses. In this case, we are more inclined to use the Ask mode. Ask mode returns a Scala future where you can use the Scala.compat.java8.FutureConverts.toJava method to convert a Scala future into a Java completionstage, Then map to your own result type.

Here's an example of using the Ask mode with our Helloactor:

Import akka.actor.*;
Import play.mvc.*;
Import scala.compat.java8.FutureConverters;
Import javax.inject.*;
Import Java.util.concurrent.CompletionStage;

Import static akka.pattern.Patterns.ask;

@Singleton public
class application extends Controller {

    final actorref helloactor;

    @Inject Public Application (Actorsystem system) {
        Helloactor = system.actorof (helloactor.props);
    }

    Public completionstage<result> SayHello (String name) {
        return Futureconverters.tojava (Ask (Helloactor, new SayHello (name), (+))
                . Thenapply (Response-OK (String) response);}
}

There are a few points to note:

The Ask mode needs to be introduced (import), and static introduction of the Ask method is usually the most convenient.
The returned future is converted to completionstage. Resulting promise is a completionstage, so when you want to get this value, you need to convert it to the actual return type of the actor.
The Ask mode requires a timeout (time limit, no translation later), we use 1000 milliseconds. If the actor response times out, retuened promise throws a timeout error.
Since we created the actor in the constructor, we need to limit our controller to a singleton (Singleton), which prevents each use of the controller from creating a new actor. Dependency Injection Actors

Some people might prefer to instantiate actors with guice and then bind specific actor refs (object references, not translations) to actors in cotrollers and components.

For example, if you want a play-configured actor, you can do this:

import akka.actor.UntypedActor; import play.

Configuration;

Import Javax.inject.Inject;

    public class Configuredactor extends Untypedactor {private configuration configuration;
    @Inject public configuredactor (configuration configuration) {this.configuration = Configuration; } @Override public void OnReceive (Object message) throws Exception {if (message instanceof configuredact
        Orprotocol.getconfig) {sender (). Tell (Configuration.getstring ("My.config"), self ()); }
    }
}

Play provides some helpers to help providing actor bindings. These allow the actor itself to being dependency injected, and allows the actor ref for the actor to being injected into other C Omponents. To bind an actor using these helpers, create a module as described in the dependency injection documentation, then mix in The Akkaguicesupport interface and use the Bindactor method to bind the actor:
Play provides some help to provide an actor binding. These allow the actor to inject itself as a dependency and allow the actor ref (quote, not translation) of this actor to be injected into other components. To bind the actor using these helpers, first create the module based on the description of the dependency injection document, then mix the Akkaguicesupport interface and use the Bindactor method to bind the actor.

Import Com.google.inject.AbstractModule;
Import Play.libs.akka.AkkaGuiceSupport;

public class MyModule extends Abstractmodule implements Akkaguicesupport {
    @Override
    protected void Configure () {
        Bindactor (configuredactor.class, "Configured-actor");
    }
}

This actor would both be named Configured-actor, and would also be qualified with the Configured-actor name for injection . You can now depend on the actor in your controllers and other components:
This actor is both named Configured-actor and requires Configur The name of the Ed-actor is injected (an injection method can refer to the relevant content of the Guice dependency injection). Now you can rely on the actor in your controllers and other components:

Import Akka.actor.ActorRef;
Import play.mvc.*;
Import scala.compat.java8.FutureConverters;

Import Javax.inject.Inject;
Import javax.inject.Named;
Import Java.util.concurrent.CompletionStage;

Import static akka.pattern.Patterns.ask;

public class Application extends Controller {

    private actorref configuredactor;

    @Inject Public
    Application (@Named ("Configured-actor") Actorref configuredactor) {
       This.configuredactor = Configuredactor;
    }

    Public completionstage<result> GetConfig () {
        return Futureconverters.tojava (Ask (Configuredactor,
                        New Configuredactorprotocol.getconfig (), +)
        . Thenapply (Response-OK (String) response);}
}
Dependency Injection Child (sub, not translated) actors

The above is good for injecting root (root) actors, but there are a lot of actors that you create are child actors, these actors do not keep the same life cycle as the Play app (lifecycle), and may also be passed to their attached state.

In order to help the dependency injection the child Actors,play took advantage of Guice's assistedinject Surpport (support).

If you have the following actor, it relies on the injected configuration, plus a key:

Import Akka.actor.UntypedActor;
Import com.google.inject.assistedinject.Assisted;
Import play. Configuration;

Import Javax.inject.Inject;

public class Configuredchildactor extends Untypedactor {

    private final configuration configuration;
    Private final String key;

    @Inject public
    configuredchildactor (configuration configuration, @Assisted String key) {
        this.configuration = configuration;
        This.key = key;
    }

    @Override public
    void OnReceive (Object message) throws Exception {
        if (message instanceof configuredchildactorprotocol.getconfig) {
            sender (). Tell (Configuration.getstring (key), self ());}}}

In this case, we have used a constructor such as-guice's assisted inject support just to be compatible with the constructor injection. Since the key parameter is provided at creation time, not through the container, we use @assisted to annotate it.

Now, in the protocol for child, we define a factory interface that receives the key and returns the actor:

Import Akka.actor.Actor;

public class Configuredchildactorprotocol {public

    static class GetConfig {} public

    interface Factory {
        Public Actor Create (String key);
    }
}

We will not implement it (Factory), Guice will provide an implementation. This implementation not only passes our key parameter, but also determines the configuration dependency and injects it (configuration). Because this feature (trait, aka Factory) just returns an actor, when testing the actor, we can inject a factor (factor) that returns any actor, for example we can inject mocked child Actor, not a real actor.

Now, the actor is depends on this can extend Injectedactorsupport, and it can depend on the factory we created:
Now, the actor who relies on this (Factory) can implement Injectedactorsupport, and it relies on the factory we created.

Import Akka.actor.ActorRef;
Import Akka.actor.UntypedActor;
Import Play.libs.akka.InjectedActorSupport;

Import Javax.inject.Inject;

public class Parentactor extends Untypedactor implements Injectedactorsupport {

    private Configuredchildactorprotocol.factory childfactory;

    @Inject public
    parentactor (configuredchildactorprotocol.factory childfactory) {
        this.childfactory = childfactory;
    }

    @Override public
    void OnReceive (Object message) throws Exception {
        if (message instanceof Parentactorprotocol.getchild) {
            String key = ((parentactorprotocol.getchild) message). Key;
            Actorref child = Injectedchild ((), Childfactory.create (key), key);
            Sender (). Tell (Child, self ());}}}

It uses Injectedchild to go to soda ash and gets a reference to the child actor, passing the key. The second argument (in this case, key) is used as the child actor's name.

Finally, we need to bind our actors. In our module, we use the Bindactorfactory method to bind Parenta ctor and also bind Achild factory to child implementation:

Import Com.google.inject.AbstractModule;
Import Play.libs.akka.AkkaGuiceSupport;

public class MyModule extends Abstractmodule implements Akkaguicesupport {
    @Override
    protected void Configure () {
        Bindactor (parentactor.class, "Parent-actor");
        Bindactorfactory (Configuredchildactor.class,
            ConfiguredChildActorProtocol.Factory.class);
    }
}

This example uses Guice to automatically bind an Configuredchildactorprotocol.factory instance, which provides a configuration instance when the Configuredchildactor is instantiated. Configuration

The default actor system configuration is read from the play application configuration file. For example, configure the application actor system by default dispatcher (dispatch. ), add the following lines to the conf/application.conf file:

Akka.actor.default-dispatcher.fork-join-executor.pool-size-max =
akka.actor.debug.receive = On

For Akka log configuration, see Configuration log. Modifying configuration prefixes

If you want to use the settings (settings, which are not translated later) for another Akka actor system that starts with akka.*, you can tell play to load Akka settings from another location.

Play.akka.config = "My-akka"

Now read the settings from the My-akka prefix instead of the Akka prefix.

My-akka.actor.default-dispatcher.fork-join-executor.pool-size-max =
my-akka.actor.debug.receive = On
built-in actor system name

By default, the name of the Play actor system is application. You can change it through the entrance to the conf/application.conf:

Play.akka.actor-system = "Custom-name"

Note: This feature is useful when you want to add your play application Actorsystem to the Akka cluster (cluster). Execute blocking code asynchronously

The common use of Akka is to perform calculations concurrently without using additional actors. If you are creating a actors pool (pool) because of a special reason for parallel execution of a parallel computation, there is a very simple (and fast) method:

Import play.mvc.*;

Import Java.util.concurrent.CompletableFuture;
Import Java.util.concurrent.CompletionStage;

public class Application extends Controller {public
    completionstage<result> index () {
        return Completablefuture.supplyasync (this::longcomputation)
                . Thenapply ((Integer i), OK ("Got" + i));
    }

Scheduling Asynchronous tasks
You can schedule sending messages to actors and executing tasks (functions or Runnable instances). You'll get a cancellable back so you can call cancel on to cancel the execution of the scheduled operation. Scheduling Asynchronous Tasks

You can dispatch messages to actors and perform tasks (methods or runnable instances). You will get a cancellable (can cancel) feedback, which can call Cancel to cancel the execution of the dispatch operation.

For example, send a message to testactor every 30 minutes.

System.scheduler (). Schedule (
    duration.create (0, Timeunit.milliseconds),//initial delay 0 MILLISECONDS
    Duration.create (timeunit.minutes),     //frequency MINUTES
    testactor,
    "tick",
    System.dispatcher (),
    null
);

Or, run the code block from now on after 10ms:

System.scheduler (). Scheduleonce (
    duration.create, Timeunit.milliseconds),
    (), File.delete (),
    System.dispatcher ()
);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.