[번역] 플레이 2 통합 akka

20526 단어 play2
소스https://www.playframework.com/documentation/2.5.x/JavaAkka#Scheduling-asynchronous-tasks Akka는 Actor Model을 사용하여 추상적인 층을 제공하고 정확한 다중 루틴과 확장 가능한 응용을 구축하기 위해 더 좋은 플랫폼을 제공합니다.용량 오류 측면에서'Let it crash'모델을 사용했는데 이 모델은 이미 통신 분야에서 매우 성공적인 응용을 얻었고 주로 영원히 멈추지 않는 자체 건강 시스템을 구축하는 데 사용된다.Actors는 전송 분포를 추상화하고 확장 및 내결함성 응용에 기반을 제공합니다.
The application actor system
Akka는 여러 actor system 컨테이너와 함께 작업할 수 있습니다.이 부분의 자원 설정은 시스템이 포함하는actors를 실행하는 데 사용됩니다.
플레이 앱(정상적으로 운영되는 플레이 실례, 앞으로 우리는 번역을 하지 않을 것이다)은 특수한 actor 시스템(배우 시스템이나 다른 것일 수도 있다. 이것은 번역도 하지 않고 관심 있는 자료도 찾아볼 수 있다)을 정의하고 사용한다.이 actor 시스템은 응용 프로그램과 같은 생명 주기를 가지고 있으며, 응용 프로그램이 다시 시작됨에 따라 자동으로 다시 시작됩니다.
Writing actors
Akka를 사용하려면 먼저 actor를 써야 합니다.다음은 간단한 actor입니다. 누가 물어보든지 간에 Hello에게 간단하게 대답합니다.
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, " + ((SayHello) msg).name, self());
        }
    }
}

이 HelloActor에서 정적 영역 props를 정의했습니다. 이 대상은 어떻게 actor를 만드는지 설명합니다.이것은 실례화된 논리를 actor를 만드는 코드에서 분리하는 좋은 Akka 관례이다.
여기서 보여주는 또 다른 좋은 점은 Hello Actor가 보내고 받는 정보가 Hello Actor Protocol이라는 클래스의 정적 내부 클래스로 정해져 있다는 것이다.
package actors;

public class HelloActorProtocol {

    public static class SayHello {
        public final String name;

        public SayHello(String name) {
            this.name = name;
        }
    }
}

actors 만들기 및 사용
actor를 사용하려면 ActorSystem이 필요합니다.ActorSystem에 대한 의존도를 성명해서 ActorSystem을 가져오고actorOf 방법으로 새 actor를 만들 수 있습니다.
actor로 할 수 있는 가장 기본적인 일은 메시지를 보내는 것이다.ctor에 메시지를 보낼 때, 메시지가 소비되고 잊혀지며,actor는 응답하지 않습니다.이것이 바로 이른바 텔레콤 모델이다.
그러나 웹 apllication에서 텔레 모드는 일반적으로 쓸모가 없다. 왜냐하면 HTTP는 요청과 응답을 포함하는 프로토콜이기 때문이다.이런 상황에서 우리는 ask 모드를 사용하는 경향이 더욱 강하다.ask 모드에서 Scala Future를 반환합니다. scala를 사용할 수 있습니다.compat.java8.FutureConverts.자바 방법은 Scala Future를 자바 Completion Stage로 전환한 다음 자신의 결과 형식에 비추는 것입니다.
다음은 ASk 모드에서 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 sayHello(String name) {
        return FutureConverters.toJava(ask(helloActor, new SayHello(name), 1000))
                .thenApply(response -> ok((String) response));
    }
}

몇 가지 주의가 필요합니다.
ask 모드는 도입(import)이 필요합니다. 정적 도입 방법은 일반적으로 가장 편리합니다.반환된 future가 CompletionStage로 전환됩니다.resultingpromise는CompletionStage이기 때문에 이 값을 얻으려면 actor의 실제 반환 형식으로 전환해야 합니다.ask 모드는 타임아웃이 필요합니다. 우리는 1000밀리초를 사용합니다.actor 응답 시간이 초과되면,retuened promise는timeout error를 던집니다.구조기에서 actor를 만들기 때문에, 이 controller를 사용할 때마다 새로운actor를 만들지 못하도록 단례 (Singleton) 로 제한해야 합니다.
의존 주입actors
어떤 사람들은 Guice 실례화actors를 사용한 다음에cotrollers와 구성 요소(components)에서actors에 구체적인actorrefs를 연결하는 것을 더 좋아할 수도 있다.
예를 들어, Play 구성의 actor를 원한다면 다음과 같이 할 수 있습니다.
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 ConfiguredActorProtocol.GetConfig) {
            sender().tell(configuration.getString("my.config"), self());
        }
    }
}

Play provides some helpers to help providing actor bindings. These allow the actor itself to be dependency injected, and allows the actor ref for the actor to be injected into other components. To bind an actor using these helpers, create a module as described in the dependency injection documentation, the n mix in the AkaGuice Support interface and use the bind Actor method to bind the actor: Play는 actor 바인딩을 위한 도움말을 제공합니다.이것들은 actor 자신을 의존으로 주입할 수 있고, 이 actor의 actor ref (인용, 번역 없음) 를 다른components에 주입할 수 있습니다.이 helpers 귀속actor를 사용하려면 주입 문서에 의존하는 설명에 따라 모듈(module)을 만들고 AkkaguiceSupport 인터페이스를 혼합한 다음bindActor 방법으로 귀속합니다.
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 will both be named configured-actor, and will also be qualified with the configured-actor name for injection. You can now depend on the actor in your controllers and other components: 이 actor는 configured-actor로 명명될 뿐만 아니라 configured-actor의 명칭에 따라 주입되어야 한다(주입 방식은 구체적으로 Guice 의존 주입과 관련된 내용을 참고할 수 있다).이제 너는 너의 controllers와 다른 components에서 이 actor에 의존할 수 있다.
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 getConfig() {
        return FutureConverters.toJava(ask(configuredActor,
                        new ConfiguredActorProtocol.GetConfig(), 1000)
        ).thenApply(response -> ok((String) response));
    }
}

의존 주입child (자, 뒤에 번역하지 않음)actors
이상은 루트(뿌리)actors를 주입하는 데 유리하지만, 당신이 만든 actors는child actors인 경우가 많습니다. 이런 actors는Play app와 같은 생명주기(lifecycle)를 유지하지 않고 그것들에게 추가 상태를 전달할 수도 있습니다.
플레이는 child actors 주입에 의존하는 데 도움이 되도록 Guice의 Assisted Inject surport(지원)를 활용했다.
만약 아래에 있는 actor가 있다면, 주입된 설정에 의존하여 키를 추가합니다.
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());
        }
    }
}

이러한 상황에서 Guice의 assisted inject support 같은 구조기는 호환 구조기 주입일 뿐입니다.키 매개 변수는 용기를 통해 만들어지지 않기 때문에 @Assisted를 사용하여 설명합니다.
이제 child에 대한 프로토콜에서 키를 받고 Actor로 되돌아오는 Factory 인터페이스를 정의합니다.
import akka.actor.Actor;

public class ConfiguredChildActorProtocol {

    public static class GetConfig {}

    public interface Factory {
        public Actor create(String key);
    }
}

우리는 그것을 실현하지 않을 것이다. Guice는 실현을 제공할 것이다.이 실현은 키 파라미터를 전달할 뿐만 아니라, Configuration의 의존도를 확인하고 주입해야 한다.이 특징(trait, 즉factory)은 단지 하나의 액터만 되돌려주기 때문에 이 액터를 테스트할 때 우리는 어떤 액터의 인자(factor)를 되돌려줄 수 있다. 예를 들어 우리는 진짜 액터가 아니라 모키드 child 액터를 주입할 수 있다.
Now, the actor that depends on this can extend Injected Actor Support, and it can depend on the factory we created: 현재 이 (Factory)에 의존하는 actor는 Injected Actor Support를 실현할 수 있으며 우리가 만든 공장에 의존합니다.
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());
        }
    }
}

이것은 injected Child를 사용하여 알칼리성을 제거하고child actor의 인용을 가져와 키를 전달합니다.두 번째 인자 (이 예는 키) 는child actor의 이름으로 사용됩니다.
마지막으로, 우리는 우리의actors를 귀속시켜야 한다.Module에서는 bindActorFactory 방법을 사용하여 parenta ctor를 바인딩하고 achild factory를 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);
    }
}

이 예에서는 Guice를 사용하여 ConfiguredChildActorProtocol을 자동으로 바인딩합니다.Factory 실례, 이 실례는 ConfiguredChildActor가 실례화할 때 Configuration 실례를 제공합니다.
Configuration
기본 actor system configuration은 Play application 구성 파일에서 읽습니다.예를 들어 응용 프로그램 actor 시스템의 기본 디스패치 (파견?) 를 설정합니다.다음 몇 줄을 conf/application에 추가합니다.conf 파일:
akka.actor.default-dispatcher.fork-join-executor.pool-size-max = 64
akka.actor.debug.receive = on

Akka 로그 구성에 대해서는 구성 로그를 참조하십시오.
구성 접두어 수정
만약 당신이 다른 Akka actor 시스템에 대해akka.*를 사용하고 싶다면처음에 settings (설정, 번역하지 않음) 를 사용하면 플레이에게 다른 위치에서 Akka settings를 불러오는 것을 알려줄 수 있습니다.
play.akka.config = "my-akka"

현재 my-akka 접두사에서settings를 읽습니다.akka 접두사가 아니라 settings를 읽습니다.
my-akka.actor.default-dispatcher.fork-join-executor.pool-size-max = 64
my-akka.actor.debug.receive = on

내장 actor 시스템 이름
기본적으로 Play actor system의 이름은 응용 프로그램입니다.conf/application을 통해서 사용할 수 있습니다.conf의 포털이 변경됩니다.
play.akka.actor-system = "custom-name"

주의: 이 기능은 플레이 응용 프로그램 ActorSystem을 akka 그룹 (cluster) 에 추가하려고 할 때 매우 유용합니다.
비동기 실행 차단 코드
Akka는 추가 Actor 없이 동시에 계산을 수행하는 경우가 많습니다.병렬 컴퓨팅을 병렬로 수행하는 특수한 이유로 Actors pool (풀) 을 만들고 있다면, 매우 간단하고 빠른 방법이 있습니다.
import play.mvc.*;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

public class Application extends Controller {
    public CompletionStage 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 will get a Cancellable back that you can call cancel on to cancel the execution of the scheduled operation.
비동기 작업 스케줄링
actors에 메시지를 보내고 작업을 수행할 수 있습니다. (방법이나 Runnable 실례)Cancellable (취소 가능) 피드백을 받을 수 있습니다. 이 피드백은 cancel에서 스케줄링 작업의 실행을 취소할 수 있습니다.
예를 들어 테스트 액터에게 30분마다 메시지를 보냅니다.
system.scheduler().schedule(
    Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay 0 milliseconds
    Duration.create(30, TimeUnit.MINUTES),     //Frequency 30 minutes
    testActor,
    "tick",
    system.dispatcher(),
    null
);

또는 지금부터 10ms 후에 코드 블록을 실행합니다.
system.scheduler().scheduleOnce(
    Duration.create(10, TimeUnit.MILLISECONDS),
    () -> file.delete(),
    system.dispatcher()
);

좋은 웹페이지 즐겨찾기