2012-04-10 36 views
6

Tôi đang mô hình hóa một P2P đơn giản với Scala và Akka:Akka diễn viên "yêu cầu" và "chờ đợi" với TimeoutException

class Node() extends Peer with Actor { 

    var peers: List[ActorRef] = List() 

    def receive = { 
    case _register(peer: ActorRef, p: Option[Int]) => { 
     println("registering [" + peer + "] for [" + this + "]") 
     peers = peer :: peers 
    } 
    } 

} 

sealed case class _register(val peer: ActorRef, var p: Option[Int] = None) 

và sau đó một mạng đơn giản:

class Network() extends Actor { 

    def this(name: String) = { 

    this() 

    val system = ActorSystem(name) 

    val s1 = system.actorOf(Props(new Node()), name = "s1") 
    val s2 = system.actorOf(Props(new Node()), name = "s2") 

    val c1 = system.actorOf(Props(new Node()), name = "c1") 
    val c2 = system.actorOf(Props(new Node()), name = "c2") 
    val c3 = system.actorOf(Props(new Node()), name = "c3") 
    val c4 = system.actorOf(Props(new Node()), name = "c4") 

    implicit val timeout = Timeout(5 second) 

    s1 ? _register(c1) 
    s1 ? _register(c2) 
    s1 ? _register(c3) 
    val lastRegistered = s2 ? _register(c4) 
    Await.ready(lastRegistered, timeout.duration) 

    println("initialized nodes") 
    } 
} 

Sản lượng mà tôi 'm nhận là luôn như:

registering [Actor[akka://p2p/user/c1]] for [[email protected]] 
registering [Actor[akka://p2p/user/c2]] for [[email protected]] 
registering [Actor[akka://p2p/user/c3]] for [[email protected]] 
registering [Actor[akka://p2p/user/c4]] for [[email protected]] 
[ERROR] [04/10/2012 22:07:04.34] [main-akka.actor.default-dispatcher-1] [akka://main/user/p2p] error while creating actor 
java.util.concurrent.TimeoutException: Futures timed out after [5000] milliseconds 
    at akka.dispatch.DefaultPromise.ready(Future.scala:834) 
    at akka.dispatch.DefaultPromise.ready(Future.scala:811) 
    at akka.dispatch.Await$.ready(Future.scala:64) 
    at nl.cwi.crisp.examples.p2p.scala.Network.<init>(Node.scala:136) 
    at nl.cwi.crisp.examples.p2p.scala.Main$$anonfun$11.apply(Node.scala:164) 
    at nl.cwi.crisp.examples.p2p.scala.Main$$anonfun$11.apply(Node.scala:164) 
    at akka.actor.ActorCell.newActor(ActorCell.scala:488) 
    at akka.actor.ActorCell.create$1(ActorCell.scala:506) 
    at akka.actor.ActorCell.systemInvoke(ActorCell.scala:591) 
    at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:191) 
    at akka.dispatch.Mailbox.run(Mailbox.scala:160) 
    at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:505) 
    at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259) 
    at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:997) 
    at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1495) 
    at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104) 

tôi đã theo tài liệu của Futures trên tài liệu tham khảo Akka. Trao đổi Await.ready với Await.result không có bất kỳ ảnh hưởng nào. Nhật ký cho thấy đăng ký cuối cùng đã thành công.

Tôi nên sửa lỗi này như thế nào?

Trả lời

8

Bạn đang chờ thư trả lời từ diễn viên Node, nhưng diễn viên Node không gửi lại tin nhắn cho diễn viên sender actorRef, vì vậy tương lai [Mọi] được tạo bởi s1 ? _register sẽ không bao giờ nhận được phản hồi, vì vậy Tương lai sẽ không bao giờ được hoàn thành. Bạn có thể thêm sender ! something từ bên trong phương thức Node receive để gửi câu trả lời, tôi không chắc chắn những gì something có ý nghĩa trong trường hợp này.

+1

Cảm ơn, đó là một sai lầm cẩu thả! 'người gửi! None' sẽ làm việc cho tôi. – nobeh

8

hầm đã làm đúng, nhưng bạn đã có một số mã đáng lo ngại ở nam diễn viên mạng của bạn:

val system = ActorSystem(name) 

val s1 = system.actorOf(Props(new Node()), name = "s1") 
val s2 = system.actorOf(Props(new Node()), name = "s2") 

val c1 = system.actorOf(Props(new Node()), name = "c1") 
val c2 = system.actorOf(Props(new Node()), name = "c2") 
val c3 = system.actorOf(Props(new Node()), name = "c3") 
val c4 = system.actorOf(Props(new Node()), name = "c4") 

Tại sao các bạn tạo ra một ActorSystem mới, và tại sao bạn tạo diễn viên cấp cao nhất trong hệ thống diễn viên ?

Nếu bạn cần truy cập vào hệ thống của người diễn viên, bạn đơn giản gọi:

context.system 

Và bạn nên tránh tạo diễn viên cấp cao nhất "chỉ vì", với cùng lý do mà bạn không nên lộn xộn gốc của hệ thống tệp của bạn bằng cách đặt tất cả các tệp của bạn ở đó. Để tạo trẻ em diễn viên đến Mạng, chỉ cần làm:

context.actorOf(...) 

Ngay bây giờ bạn sẽ có một vấn đề càng sớm càng tốt tạo nhiều hơn một mạng-diễn viên trong cùng một hệ thống, vì nó sẽ cố gắng để tạo ra đầu các diễn viên cùng tên.

+1

Cảm ơn các mẹo rõ ràng. – nobeh

+1

Bạn được chào đón nhiều. Chúc mừng hAkking! –

Các vấn đề liên quan