1. Akka Actor中的方法
preStart
在Actor启动之后立即调用,在重启过程中默认调用postRestart
postStop
在一个Actor停止之后,它可以执行任何的清扫工作(clean up)。在Akka documentation中,必须保证在消息队列对于这个Actor禁用之后才能执行
preRestart
当一个新的Actor重启,进程会通知老的Actor(之前执行异常任务重启)和触发异常的消息
postRestart
当有新的异常导致重启时,会调用postRestart方法
2.启动一个Actor
如果你想启动一个actor,或者是想控制actor的启动
Akka actor 是异步启动的,当通过actorOf的方法生成一个actor并启动时。
你可以使用context.actorOf方法创造一个child actor
假设有一个actor,它的一个功能过于复杂,为了降低复杂度,可以将这个功能划分成多个更小粒度的,更易管理的子任务,启动新的child actors,
例子:
import akka.actor._
class HelloActor extends Actor{
def receive = {
....
}
}
object LifecycleDemo{
def main(args: Array[String]): Unit = {
val system = ActorSystem("HelloSystem")
//创造一个actor并启动
val helloActor = system.actorOf(Props[HelloActor],name = "helloactor")
helloActor ! "hello"
}
}
父类子类
class Child extends Actor{
def receive ={
.....
}
}
class Parent extends Actor{
val child = context.actorOf(Props[Child],name = "Child")
def receive={
......
}
}
3.Actor Path
可以把Actor Path是通过字符串对Actor层级关系进行组合用以标识唯一Actor的一种方式。在创建Actor Path时,不用创建Actor,但如果没有创建对应的Actor,则不能创建Actor Reference。还可以创建一个Actor,再终止它,然后再以相同的Actor Path再创建一个新的Actor。新创建的Actor是Actor的新化身(Incarnation),但与旧的Actor并不是同一个。对于这个新化身而言,持有旧Actor的Actor Reference并不是有效的。消息发送给旧的Actor Reference,但不会被传递给新化身,即使它们具有相同的路径。
有两种方式可以获得Actor Reference:创建Actor或查找。
要创建Actor,可以调用ActorSystem.actorOf(),它创建的Actor在guardian actor之下;接着可以调用ActorContext.actorOf()在刚才创建的Actor内生成Actor树。这些方法会返回新创建的Actor的引用。每个Actor都可以直接访问Actor Context来或得它自身、Parent以及所有Children的引用。
要查找Actor Reference,则可调用ActorSystem.actorSelection()方法。要获得限定到特定Actor的生命周期中的ActorRef,可以使用sender引用来发送一条消息如内建的Identity消息给Actor。
//本地path
"akka://my-sys/user/service-a/worker1"
//远程path
"akka.tcp://my-sys@host.example.com:5678/user/service-b"
//akka集群
"cluster://my-cluster/service-c"
4.Stopping Actors
这里有几种方法去停止Akka actors s
常用的方法:System.stop(actorRef) / context.stop(actorRef)
还有其他两种方法: Send the actor a PosionPill message
Program a gracefulStop
1. actorSystem.stop(actorRef) 在ActorSystem level 停止actor
2. 隐式的被认定为在一个actor内使用,可以用context.stop(childActor)方式停止child actor
3. Actor可以停止本身 context.stop(self)
4.通过发送PosionPill message 来stop actor
区别:
Stop 方法:actor会继续处理当前的消息(如果有),但是不会处理additional message
PosionPill message : 对已经传进来的消息(mailbox)全部进行处理,处理完毕之后在停止
在 official Akka actor documentation 中描述 actorSystem.stop()和context.stop()
1. actor的终止是异步的,stop方法可能在actor停止之前就返回了
2.actor会继续处理的当前消息,但不会再处理附加的消息
3.actor 停止分为两步:a.挂起(suspends)mailbox,向该actor的所有child发送stop消息
b.当所有的child终止,当有actor不回应(block)会等待
4 .当没有额外的消息被处理,它们被发送到ActorSystem的deadLetters actor中
gracefulStop 方法
正如名字所描述的,如果你想等待一段再时间停止。
例子:package actortests.gracefulstop
import akka.actor._
import akka.pattern.gracefulStop
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration._
import scala.language.postfixOps
class TestActor extends Actor {
def receive = {
case _ => println("TestActor got message")
}
override def postStop { println("TestActor: postStop") }
}
object GracefulStopTest extends App {
val system = ActorSystem("GracefulStopTest")
val testActor = system.actorOf(Props[TestActor], name = "TestActor")
// try to stop the actor gracefully
try {
val stopped: Future[Boolean] = gracefulStop(testActor, 2 seconds)(system)
Await.result(stopped, 3 seconds)
println("testActor was stopped")
} catch {
case e:Exception => e.printStackTrace
} finally {
system.shutdown
}
}
在Scaladoc中,gracefulStop(actorRef , timeout),返回一个Future[actor中存在的消息被成功处理,然后actor被终止],如果actor没有在时间内终止,Future返回一个ActorTimeoutException。为了让这个例子更加简单,使用了Await.result,会加长等待时间