Akka Tutorial
Reference
Actor Model의 좋은 점
- 이벤트 기반의 모델
- Actor는 메시지를 통해 작업
- Actor 사이간의 통신은 비동기, blocking 없이, 응답을 기다리지 않고 다른 작업을 할수가 있다.
- 강한 격리 원칙
- 일반적인 자바 객체와 달리 Actor는 자신이 가지고 있는 상태에 대한 API 존재하지 않는다. 대신에 메세지를 통해 공유가 가능하다.
- 이는 다른 액터간의 상태(State)를 공유하는 것을 막는다.
- 오로지 메세지를 보내는 것을 통해 다른 액테의 상태를 볼수가 있다.
- 가벼움
- 백만건이상을 처리할때도 액터는 각각의 인스턴트는 몇백 바이터 정도의 메모리를 사용한다.
Akka Quick Start Main Class
package com.lightbend.akka.sample;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import com.lightbend.akka.sample.Greeter.*;
import java.io.IOException;
public class AkkaQuickstart {
public static void main(String[] args) {
final ActorSystem system = ActorSystem.create("helloakka");
try {
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");
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"), ActorRef.noSender());
goodDayGreeter.tell(new Greet(), ActorRef.noSender());
System.out.println(">>> Press ENTER to exit <<<");
System.in.read();
} catch (IOException ioe) {
} finally {
system.terminate();
}
}
}
- ActorySystem는 Actor를 생성하기 위한 Factory이다.
- actorOf 매서드는 Actor 생성하는 매서드이다. Props 객체를 통해 Actor를 생성한다.
- ActorRef의 tell 매서드를 이용하여 메세지를 보낼수가 있다.
Greeter Class
package com.lightbend.akka.sample;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import com.lightbend.akka.sample.Printer.Greeting;
public class Greeter extends AbstractActor {
static public Props props(String message, ActorRef printerActor) {
return Props.create(Greeter.class, () -> new Greeter(message, printerActor));
}
static public class WhoToGreet {
public final String who;
public WhoToGreet(String who) {
this.who = who;
}
}
static public class Greet {
public Greet() {
}
}
private final String message;
private final ActorRef printerActor;
private String greeting = "";
public Greeter(String message, ActorRef printerActor) {
this.message = message;
this.printerActor = printerActor;
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(WhoToGreet.class, wtg -> {
this.greeting = message + ", " + wtg.who;
})
.match(Greet.class, x -> {
printerActor.tell(new Greeting(greeting), getSelf());
})
.build();
}
}
- Greeter Class는 akka.actor.AbstractActor 클래스를 상속받아 createReceive 매서드를 구현한다.
- Static prop method는 Props 객체를 생성해준다. Prop은 Actor의 설정 클래스이다.
- receiveBuilder method는 메서지 처리 핸들러를 등록해준다.
Printer Class
package com.lightbend.akka.sample;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class Printer extends AbstractActor {
static public Props props() {
return Props.create(Printer.class, () -> new Printer());
}
static public class Greeting {
public final String message;
public Greeting(String message) {
this.message = message;
}
}
private LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
public Printer() {
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(Greeting.class, greeting -> {
log.info(greeting.message);
})
.build();
}
}
Testing Actor
package com.lightbend.akka.sample;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.testkit.javadsl.TestKit;
import com.lightbend.akka.sample.Greeter.*;
import com.lightbend.akka.sample.Printer.*;
import static org.junit.Assert.assertEquals;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class AkkaQuickstartTest {
static ActorSystem system;
@BeforeClass
public static void setup() {
system = ActorSystem.create();
}
@AfterClass
public static void teardown() {
TestKit.shutdownActorSystem(system);
system = null;
}
@Test
public void testGreeterActorSendingOfGreeting() {
final TestKit testProbe = new TestKit(system);
final ActorRef helloGreeter = system.actorOf(Greeter.props("Hello", testProbe.getRef()));
helloGreeter.tell(new WhoToGreet("Akka"), ActorRef.noSender());
helloGreeter.tell(new Greet(), ActorRef.noSender());
Greeting greeting = testProbe.expectMsgClass(Greeting.class);
assertEquals("Hello, Akka", greeting.message);
}
}
akka.test.javadsl.TestKit
와 junit
를 이용하여 테스트 케이스를 작성을 할수 있다.