Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

가장 기본적인 Actor의 설계방법을 살펴보겠습니다.

Actor에대한 이론적인 설명은 앞장에서 했기때문에 생략하겠습니다.

Actor에 대한 사용패턴/컨셉은 언어/플래폼이 틀려도 큰 차이가 없습니다.

다음과 같은 간단한 액트를 설계해보자

  • 인사를 받아주는 액트(Greeter)
  • 인사에 반응하여 로그를 찍는 액트( Printer)

액터메시지의 특징

Image Added

액터는 각각 고유의 메시지 큐를 가지고 있고, 하나의 액터는 메지큐에 순차적으로

끄집어 처리하기때문에 일반적인 상황에서 순서보장이 됩니다. 

더 자세한 참고자료: Actor


주요 액터 모듈

import akka.actor.ActorSystem

No Format
ActorSystem system = ActorSystem.create("helloakka");

어플리케이션 하나당, 일반적으로 액터 시스템도 하나이며

액터생성과 제어에 관련한 여러가지 함수를 제공합니다.


import akka.actor.AbstractActor

...

Code Block
languagejava
themeEmacs
public class MyActor
Code Block
languagejava
themeEmacs
titleGreeter
package com.psmon.akka.study;

import com.psmon.akka.study.Printer.Greeting;

import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;

//#greeter-messages
public class Greeter extends AbstractActor {
//#greeter-messages
  staticprivate publicfinal PropsLoggingAdapter props(String message, ActorRef printerActor) {
    return Props.create(Greeter.class, () -> new Greeter(message, printerActor));
  }

  //#greeter-messages
  static public class WhoToGreet {
    public final String who;

    public WhoToGreet(String who) {
        this.who = who;
    }
  }

  static public class Greet {
    public Greet() {
    }
  }
  //#greeter-messages

  private final String message;
  private final ActorRef printerActor;
  private String greeting = "";

  public Greeter(String message, ActorRef printerActor) {
    this.message = message;
    this.printerActor = printerActor;
  }

  log = Logging.getLogger(getContext().getSystem(), this);

  @Override
  public Receive createReceive() {
    return receiveBuilder()
        .match(WhoToGreetString.class, wtgs -> {
          this.greeting =log.info("Received String message: + {}", " + wtg.whos);
        })
        .match(Greet.class, x -> {
          //#greeter-send-message
          printerActor.tell(new Greeting(greeting), getSelf());
          //#greeter-send-message
        })
  matchAny(o -> log.info("received unknown message"))
      .build();
  }
//#greeter-messages
}
//#greeter-messages


}

액터를 설계할때 기본적으로 상속받는 준비된 추상 액터 입니다.

위코드는 AbstaractActor를 상속받아 패턴 매칭화 해서 메시지를 처리하는 고급방법입니다.

 UntypedActor 를 상속받아 우리에게 익숙한 If/Switch문을 사용할수도 있습니다.


import akka.actor.UntypedActor

Code Block
languagejava
themeEmacstitleGreeterPrinter
package com.psmon.akka.study;

import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;

//#printer-messages
public class PrinterTestActor extends AbstractActorUntypedActor {
//#printer-messages
  static public Props props() {
    return Props.create(Printer.class, () -> new Printer());
  }

  //#printer-messages
  static public class Greeting {
    public final String message;

    public Greeting(String message) {
      this.message = message;private final LoggingAdapter log = Logging
    }
  }
  //#printer-messages

  private LoggingAdapter log = Logging.getLogger(getContext().getSystemsystem(), this"TestActor");

  public Printer() {@Override
  }

  @Override
  public Receivevoid createReceiveonReceive(Object message) throws Exception {
    return	 receiveBuilder()
   	
     .match(Greeting.class, greeting -> {
    	if(message instanceof String) {	//String뿐만 아니라 모든 Java객체 통신가능
        		log.info(greeting."Incommessage {}", message);
        })
        .build();
  }
//#printer-messages
}
//#printer-messages
Code Block
languagejava
themeEmacs
title수행
package com.psmon.akka.study;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;

import java.io.IOException;

import com.psmon.akka.study.Greeter.*;

public class AkkaQuickstart		sender().tell("너의 메시지에 응답을함", ActorRef.noSender());    		
    	}else {
  public static void main(String[] args) {
    final ActorSystem system = ActorSystem.create("helloakka");
    try { 		log.info("Unhandle Message {}", message);    		
      //#create-actors	}
    	
  final ActorRef printerActor = 
        system.actorOf(Printer.props(), "printerActor");
      final ActorRef howdyGreeter = 
        system.actorOf(Greeter.props("Howdy", printerActor), "howdyGreeter");
      final ActorRef helloGreeter = 
        system.actorOf(Greeter.props("Hello", printerActor), "helloGreeter");
      final ActorRef goodDayGreeter = 
        system.actorOf(Greeter.props("Good day", printerActor), "goodDayGreeter");
      //#create-actors

      //#main-send-messages
      howdyGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender());
      howdyGreeter.tell(new Greet(), ActorRef.noSender());

      howdyGreeter.tell(new WhoToGreet("Lightbend"), ActorRef.noSender());
      howdyGreeter.tell(new Greet(), ActorRef.noSender());

      helloGreeter.tell(new WhoToGreet("Java"), ActorRef.noSender());
      helloGreeter.tell(new Greet(), ActorRef.noSender());

      goodDayGreeter.tell(new WhoToGreet("Play}
}

객체조건에 따른 분기처리를 위한 패턴매칭은 어디서 누가? 먼저 도입한지는 모르겠으나 , Java/C# 등에서도  최근버젼에서 도입되고 사용가능한 방식이며

Scala에서는 이미 초기부터 사용가능한방식입니다. 일반적으로 오픈진영을 통합해야하는 Java 진영에서 최신 모던 언어스펙적용이

느린편이나 8이후로 가속이 붙은 느낌이 듭니다. 어쨋건 위 코드는 패턴매칭이 아닌 우리에게 익숙한 케이스바이 케이스로 처리한 방식입니다.


import akka.actor.Props

...

Code Block
languagejava
themeEmacs
Props props1 = Props.create(MyActor.class);
Props props2 = Props.create(ActorWithArgs.class,
  () -> new ActorWithArgs("arg")); // careful, see below
Props props3 = Props.create(ActorWithArgs.class, "arg");

 액터 생성옵션에 대한 정보를 보관할수가 있으며 ,옵션 재사용가능하며

액터 초기화에 필요한 여러가지 초기옵션들을 관리할수가 있습니다.


import akka.actor.ActorRef

...

[INFO] [10/31/2017 15:33:29.692] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/printerActor] Good day, Play
[INFO] [10/31/2017 15:33:29.693] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/printerActor] Howdy, Akka
[INFO] [10/31/2017 15:33:29.693] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/printerActor] Hello, Java
[INFO] [10/31/2017 15:33:29.693] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/printerActor] Howdy, Lightbend
Code Block
languagec#
themeEmacs
ActorRef howdyGreeter = system.actorOf( props1  , "howdyGreeter");
howdyGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender());
      goodDayGreeter.tell(new Greet(), ActorRef.noSender());
            
      
      //#main-send-messages

      System.out.println(">>> Press ENTER to exit <<<");
      System.in.read();
    } catch (IOException ioe) {
    } finally {
      system.terminate();
    }
  }
}


Expand
title결과

액터의 참조자이며, 참조된 액터에게 메시지를 보내고자할때 이용됩니다.

액터는 기본적으로, 공유가 금지되었기때문에  상대 멤버접근이 불가능하며

모든것은 메시지를 통해 정보를 교환해야합니다. 

그래서 이야기를 해야할 또는 물음에 답할수 있는 상대를 지정하는 방법이 중요합니다.