ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • AKKA 샘플 예제 분석하기 - akka QUICKSTART java
    Java/Akka 2021. 5. 21. 16:35

    Akka 솔직히 좀 개념이 좀 생소해서 어떨때에 어떻게 사용해야하는지 분간이 안가서 학습중이다.

     

    Akka 정의

     

    Akka는 오픈 소스 툴킷으로, JVM 상의 동시성과 분산 애플리케이션을 단순화하는 런타임이다. 

     

    pom.xml

    
    <dependency>
      <groupId>com.typesafe.akka</groupId>
      <artifactId>akka-actor-typed_2.13</artifactId>
      <version>2.6.14</version>
    </dependency>
    <dependency>
      <groupId>com.typesafe.akka</groupId>
      <artifactId>akka-actor-testkit-typed_2.13</artifactId>
      <version>2.6.14</version>
      <scope>test</scope>
    </dependency>

     

    AKKA 프로젝트 템플릿 다운로드

    http://dev.lightbend.com/start/?group=akka&project=akka-quickstart-java   

     

    AKKA 는 자바개발환경에서는 maven, gradle 로 실행 가능하고, 스칼라 사용시 SBT 로 빌드 후 사용 가능하다.

    프로젝트를 받게되면

    AkkaQuickstart 라는 java 파일이 있다.

    //#actor-system
    final ActorSystem<GreeterMain.SayHello> greeterMain = ActorSystem.create(GreeterMain.create(), "helloakka");
    //#actor-system
    
    //#main-send-messages
    greeterMain.tell(new GreeterMain.SayHello("Charles"));
    //#main-send-messages

    ActorSystem 을 생성하고 

    main 액터에 메시지를 보낸다.

     

    GreeterMain

    public class GreeterMain extends AbstractBehavior<GreeterMain.SayHello> {
    
        public static class SayHello {
            public final String name;
            public SayHello(String name) {
                this.name = name;
            }
        }
    
        private final ActorRef<Greeter.Greet> greeter;
    
        public static Behavior<SayHello> create() {
            return Behaviors.setup(GreeterMain::new);
        }
    
        private GreeterMain(ActorContext<SayHello> context) {
            super(context);
            //#create-actors
            greeter = context.spawn(Greeter.create(), "greeter");
            //#create-actors
        }
    
        @Override
        public Receive<SayHello> createReceive() {
            return newReceiveBuilder().onMessage(SayHello.class, this::onSayHello).build();
        }
    
    
    	// 3개의 GreetoerBot 을 생성 후 Greeter 에게 메시지와 누구에게 메시지를 보낼지 대상을 전달한다.
        private Behavior<SayHello> onSayHello(SayHello command) {
            //#create-actors
            ActorRef<Greeter.Greeted> replyTo =
                    getContext().spawn(GreeterBot.create(3), command.name);
            greeter.tell(new Greeter.Greet(command.name, replyTo));
            //#create-actors
            return this;
        }
    }

    AbstractBehavior 클래스를 상속받은 GreeterMain 에게 Charles 라는 메시지를 보내면 

    AbstractBehavior 클래스의 createReceive 메소드에서 receive 받기로 한 메소드가 실행이 된다.

     

    createReceive 에는 메시지 받는 타입과 메시지 받은 이후의 처리를 담당하는 handler 를 설정할 수 있다.

    예제에서는 handler 가 onSayHello 메소드 이다.

     

    onSayHello 의 메소드는 응답받을 3개의 GreeterBot 을 만든다.

    그 후

    ActorRef<Greeter.Greet> greeter

    ActorRef 변수 greeter 에게 메시지와 메시지를 보낼 대상일 GreeterBot(ActorRef) 객체를 보낸다.

    Greeter.class

    public class Greeter extends AbstractBehavior<Greeter.Greet> {
    
      public static final class Greet {
        public final String whom;
        public final ActorRef<Greeted> replyTo;
    
        public Greet(String whom, ActorRef<Greeted> replyTo) {
          this.whom = whom;
          this.replyTo = replyTo;
        }
      }
    
      public static final class Greeted {
        public final String whom;
        public final ActorRef<Greet> from;
    
        public Greeted(String whom, ActorRef<Greet> from) {
          this.whom = whom;
          this.from = from;
        }
    
      public static Behavior<Greet> create() {
        return Behaviors.setup(Greeter::new);
      }
    
      private Greeter(ActorContext<Greet> context) {
        super(context);
      }
    
      @Override
      public Receive<Greet> createReceive() {
        return newReceiveBuilder().onMessage(Greet.class, this::onGreet).build();
      }
      
      // GreeterMain actorRef 가 tell 할 경우 실행된다.
      private Behavior<Greet> onGreet(Greet command) {
        getContext().getLog().info("Hello {}!", command.whom);
        //#greeter-send-message
        command.replyTo.tell(new Greeted(command.whom, getContext().getSelf()));
        //#greeter-send-message
        return this;
      }
    }

     

    여기서 또 AbstractBehavior 클래스를 상속받은 Greeter 가

    createReceive 에서 연결된 Greet 타입으로 onGreet 메소드를 실행한다.

     

    이번 onGreet 메소드에는 특이하게 GreeterMain 의 onSayHello 에서 보낸 GreeterBot(ActorRef)  가 있어서 

    GreeterBot 이 tell 하도록 한다.

     

    GreeterBot.class

    public class GreeterBot extends AbstractBehavior<Greeter.Greeted> {
    
        public static Behavior<Greeter.Greeted> create(int max) {
            return Behaviors.setup(context -> new GreeterBot(context, max));
        }
    
        private final int max;
        private int greetingCounter;
    
        private GreeterBot(ActorContext<Greeter.Greeted> context, int max) {
            super(context);
            this.max = max;
        }
    
        @Override
        public Receive<Greeter.Greeted> createReceive() {
            return newReceiveBuilder().onMessage(Greeter.Greeted.class, this::onGreeted).build();
        }
    	
        // Greeter actorRef 가 onGreet 할때 tell 시킨다.
        private Behavior<Greeter.Greeted> onGreeted(Greeter.Greeted message) {
            greetingCounter++;
            getContext().getLog().info("Greeting {} for {}", greetingCounter, message.whom);
            if (greetingCounter == max) {
                return Behaviors.stopped();
            } else {
                message.from.tell(new Greeter.Greet(message.whom, getContext().getSelf()));
                return this;
            }
        }
    }

     

    코드 요약 

    GreeterMain 에게 tell 을 한 후 Main 에 생성 되어 있는 ActorRef(greeter) 에게 tell 을 하고, 응답을 ActoerRef(greeterBot) 이 응답한다.

     

    실행   

     

    akka 자바 공식문서

    https://doc.akka.io/docs/akka/2.5/testing.html

    반응형

    댓글

Designed by Tistory.