2017-10-15 63 views
0

出於某種原因,我必須同時使用gRPC和Akka。當這個演員成爲頂級演員時,沒有任何問題(在這個小演示中)。但是,當它成爲一個兒童演員,也沒有收到任何消息,並且以下記錄:ExecutionContext導致Akka死信

[default-akka.actor.default-dispatcher-6] [akka://default/user/Grpc] Message [AkkaMessage.package$GlobalStart] from Actor[akka://default/user/TrackerCore#-808631363] to Actor[akka://default/user/Grpc#-1834173068] was not delivered. [1] dead letters encountered. 

的例子核心:

class GrpcActor() extends Actor { 
    val ec = scala.concurrent.ExecutionContext.global 
    val service = grpcService.bindService(new GrpcServerImpl(), ec) 
    override def receive: Receive = { 
     case GlobalStart() => { 
      println("GlobalStart") 
     } 
     ... 
    } 
} 

我試圖創建一個新的ExecutionContext,如:

scala.concurrent.ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10)) 

爲什麼會發生這種情況,以及如何調試像這樣的死信問題(不會引發異常)?

更新:

對不起,我沒有在這裏列出一切。我使用普通的Main方法來測試GrpcActor作爲頂級演員,而ScalaTest將其測試爲小孩演員,這是一個錯誤。

class GrpcActorTest extends FlatSpec with Matchers{ 
    implicit val system = ActorSystem() 
    val actor: ActorRef = system.actorOf(Props[GrpcActor]) 
    actor ! GlobalStart() 
} 

這是一個空的測試套件,主動關閉整個actor系統。但問題出在這條線上

val service = grpcService.bindService(new GrpcServerImpl(), ec) 

GlobalStart()的交付延遲後關閉。

沒有該行,消息可以在關閉之前傳遞。

這是正常行爲嗎?

(我的猜測:它發生的GlobalStart()與該行,其中做了一些繁重的工作和取得的時間差的停產消息後排隊)

+0

感謝@chunjef糾正我的語法錯誤,並完善這個問題。 – Skye347

回答

0

一種方法來解決這個問題是讓service一個lazy val

class GrpcActor extends Actor { 
    ... 
    lazy val service = grpcService.bindService(new GrpcServerImpl(), ec) 
    ... 
} 

一個lazy val是有用的長期運行的操作:在在這種情況下,它首先推遲service的初始化,直到它被首次使用。如果沒有lazy修改器,則在創建actor時初始化service

另一種方法是在您的測試,以防止演員系統從演員之前關停添加Thread.sleep完全初始化:

class GrpcActorTest extends FlatSpec with Matchers { 
    ... 
    actor ! GlobalStart() 
    Thread.sleep(5000) // or whatever length of time is needed to initialize the actor 
} 

(作爲一個方面說明,考慮使用阿卡Testkit您演員測試。)

0

添加主管戰略,其母公司,添加的println到演員生命週期。有什麼會殺死你的演員。最後,如果你提供一個完整的例子也許我可以多說:)