2017-11-10 8 views
0

나는 RoundRobinPool 라우터와 OneForOneStrategy 재시작 전략을 사용하는 간단한 "hello world"배우 시스템을 보유하고 있습니다. 다음 코드는 결국 (몇 가지 실패 후) 10 "work done" 메시지를 인쇄 할 것으로 예상하지만, 실제로는 그 Worker 배우가 다시 시작되지 않는 실패한 것 같다 : 내가 잘못 뭐하는 거지OneForOneStrategy Restart가 포함 된 Akka RoundRobinPool

import java.time.LocalDateTime 

import akka.actor.SupervisorStrategy._ 
import akka.actor.{Actor, ActorSystem, OneForOneStrategy, Props} 
import akka.routing.{RoundRobinPool, RouterConfig} 

import scala.concurrent.duration._ 

/** 
    * Worker Actor 
    */ 
class Worker extends Actor { 

    override def receive: Receive = { 
    case DoIt => doit 
    } 

    def doit = { 
    Thread.sleep(900) 
    val dt = LocalDateTime.now().getSecond 
    if ((dt % 2) == 0) throw new Exception("Error") 
    else println("work done") 
    } 
} 

/** 
    * Message 
    */ 
case object DoIt 

/** 
    * Entry point 
    */ 
object PoolHelloWorld { 

    def main(args: Array[String]): Unit = { 
    val system = ActorSystem("PoolSystem") 

    val supervisorStrategy = 
     OneForOneStrategy(maxNrOfRetries = 20, withinTimeRange = 60 seconds) { 
     case _: Exception => Restart 
     } 
    val routerConfig: RouterConfig = 
     RoundRobinPool(2).withSupervisorStrategy(supervisorStrategy) 
    val prop: Props = Props[Worker].withRouter(routerConfig) 

    val worker = system.actorOf(prop, "Worker") 
    (1 to 10).foreach { p => 
     worker ! DoIt 
    } 

    Thread.sleep(40000) 
    system.terminate() 
    } 
} 

?

답변

2

한 가지 잘못된 것은 액터에 Thread.sleep(900)을 포함하는 것입니다. 이상한 행동을 일으킬 수 있기 때문에 그 전화를 제거하십시오.

또한 재시작 전략을 적용한 경우에도 항상 인쇄 문을 보려고합니다. 아시다시피

, 당신의 배우의 동작은 결정적이다 : dt 당신이 배우로 보내는 모든 10 DoIt 메시지 홀수 될 일이

val dt = LocalDateTime.now().getSecond 
if ((dt % 2) == 0) throw new Exception("Error") 
else println("work done") 

경우, 분명히 당신은 10 "work done" 문을 볼 수 있습니다 . dt이 짝수 인 경우 예외가 발생하고 경로 이 다시 시작됩니다. routee가 다시 시작되면

class Worker extends Actor { 
    ... 
    override def postRestart(t: Throwable): Unit = { 
    println(s"Restarted ${self.path} ...") 
    } 
} 

documentation으로는 처리가 다시 처리되지 않습니다이었다 DoIt 메시지가 나타냅니다 :

당신이 배우에 postRestart 후크를 오버라이드 (override)하는 경우는 명확하게 볼 수 있습니다

... 재시작은 액터 자체 외부에서 볼 수 없으며 예외가 발생한 동안의 메시지는 재 처리되지 않습니다. dt 변수가 모두 10 DoIt 메시지를 홀수로 발생하는 경우 요약

, 당신은 10 "work done" 인쇄 문을 볼 수있는 유일한 시나리오입니다. 해당 DoIt 메시지 중 하나 인 dt이 짝수이면 해당 메시지를 처리하던 route가 다시 시작됩니다. 다시 시작과 동시에 해당 DoIt 메시지는 이 아니며이 다시 처리되지 않으며 1"work done" 개의 인쇄 문 (있는 경우)이 표시됩니다.

+0

장시간 실행되는 프로세스를 에뮬레이트하기 위해'Thread.sleep (900)'을 액터에 추가합니다. 이것이 틀린 경우, 어떻게하면 좋을까요 (장기 실행 프로세스를 에뮬레이트하는 것을 의미합니다). 그래서'DoIt' 메시지가 재전송되지 않는다면'receive' 메쏘드가 호출되지 않는다는 것을 의미합니다. 즉, Actor의 처리 로직의 호출은 항상 Actor의 메서드에서 정의 된 다음'receive' 와'postRestart' 메쏘드? –