akka & pekko/actors
Messages and Behavior
wefree
2023. 7. 17. 13:23
ref ! s"Forwards: $message"
1. messages can be of any type
- messages must be IMMUTABLE
- messages must be SERIALIZABLE (in practice use case class and case objects
import akka.actor.{Actor, ActorSystem, Props}
object TestActor {
def main(args: Array[String]): Unit = {
val actorSystem: ActorSystem = ActorSystem(name = "actorCapabilitiesDemo")
class SimpleActor extends Actor {
override def receive: Receive = {
case message: String => println(s"String message: $message")
case number: Int => println(s"Int number: $number")
}
}
val simpleActor = actorSystem.actorOf(Props[SimpleActor], "simpleActor")
simpleActor ! "A"
simpleActor ! 1
}
}
2. actors have information about their context and about themselves
- context.self == `this` in OOP
- context.self 대신 self (aliased) 사용 가능
import akka.actor.{Actor, ActorSystem, Props}
object TestActor {
def main(args: Array[String]): Unit = {
val actorSystem: ActorSystem = ActorSystem(name = "actorCapabilitiesDemo")
class SimpleActor extends Actor {
override def receive: Receive = {
case message: String =>
println(s"[${context.self}] String message: $message")
self ! message.toInt
case number: Int =>
println(s"[${self.path}] Int number: $number")
}
}
val simpleActor = actorSystem.actorOf(Props[SimpleActor], "simpleActor")
simpleActor ! "1"
}
}
결과
[Actor[akka://actorCapabilitiesDemo/user/simpleActor#969381549]] String message: 1
[akka://actorCapabilitiesDemo/user/simpleActor] Int number: 1
3. actors can REPLY to messages
- context.sender() 활용
package com.github.windbird123
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
object TestActor {
def main(args: Array[String]): Unit = {
val actorSystem: ActorSystem = ActorSystem(name = "actorCapabilitiesDemo")
class SimpleActor extends Actor {
override def receive: Receive = {
case "Hello" =>
println(s"[${context.sender()} --> $self] Hello")
case message: String =>
println(s"[${context.sender()} --> $self] String message: $message")
context.sender() ! "Hello"
case SayHiTo(ref) =>
println(s"[${context.sender()} --> $self] SayHiTo message")
ref ! "Hi"
}
}
val alice = actorSystem.actorOf(Props[SimpleActor], "alice")
val bob = actorSystem.actorOf(Props[SimpleActor], "bob")
case class SayHiTo(ref: ActorRef)
// Actor.noSender --> alice --> bob(reply) --> alice
alice ! SayHiTo(bob)
}
}
결과
[Actor[akka://actorCapabilitiesDemo/deadLetters] --> Actor[akka://actorCapabilitiesDemo/user/alice#2067059408]] SayHiTo message
[Actor[akka://actorCapabilitiesDemo/user/alice#2067059408] --> Actor[akka://actorCapabilitiesDemo/user/bob#538084463]] String message: Hi
[Actor[akka://actorCapabilitiesDemo/user/bob#538084463] --> Actor[akka://actorCapabilitiesDemo/user/alice#2067059408]] Hello
4. dead letters (Actor.noSender)
import akka.actor.{Actor, ActorSystem, Props}
object TestActor {
def main(args: Array[String]): Unit = {
val actorSystem: ActorSystem = ActorSystem(name = "actorCapabilitiesDemo")
class SimpleActor extends Actor {
override def receive: Receive = {
case message: String =>
println(s"[${context.sender()} --> $self] String message: $message")
}
}
val alice = actorSystem.actorOf(Props[SimpleActor], "alice")
alice ! "Hi" // who is a sender ?
}
}
결과
[Actor[akka://actorCapabilitiesDemo/deadLetters] --> Actor[akka://actorCapabilitiesDemo/user/alice#906235305]] String message: Hi
5. forwarding messages
- deadLetters -> A -> B
- forwarding: sending a message with the ORIGINAL sender
object TestActor {
def main(args: Array[String]): Unit = {
val actorSystem: ActorSystem = ActorSystem(name = "actorCapabilitiesDemo")
case class ForwardMessage(message: String, ref: ActorRef)
class SimpleActor extends Actor {
override def receive: Receive = {
case message: String =>
println(s"[${context.sender()} --> $self] String message: $message")
case ForwardMessage(message, ref) =>
println(s"[${context.sender()} --> $self] String message: $message")
ref forward s"Forwards: $message"
}
}
val A = actorSystem.actorOf(Props[SimpleActor], "A")
val B = actorSystem.actorOf(Props[SimpleActor], "B")
// Actor.noSender (ForwardMessage) -> A (Hi) -> B
A ! ForwardMessage("Hi", B)
}
}
결과
[Actor[akka://actorCapabilitiesDemo/deadLetters] --> Actor[akka://actorCapabilitiesDemo/user/A#130061245]] String message: Hi
[Actor[akka://actorCapabilitiesDemo/deadLetters] --> Actor[akka://actorCapabilitiesDemo/user/B#1295696439]] String message: Forwards: Hi
참고
아래처럼 forward 대신에 tell(!) 로 코드를 변경했을 때
// ref forward s"Forwards: $message"
ref ! s"Forwards: $message"
결과는 다음과 같이 ORIGINAL sender 대신에, 두번째 로그에서 바로 직전의 sender(/user/A) 가 로깅된다.
[Actor[akka://actorCapabilitiesDemo/deadLetters] --> Actor[akka://actorCapabilitiesDemo/user/A#1641879570]] String message: Hi
[Actor[akka://actorCapabilitiesDemo/user/A#1641879570] --> Actor[akka://actorCapabilitiesDemo/user/B#1749142701]] String message: Forwards: Hi