2010-11-02 78 views
4

我正在編寫一個小測試程序來嘗試一些我需要在Scala項目中使用的Remote Actors。使Scala遠程演員更加穩定

基本目標是編寫一個服務器的測試應用程序,它可以處理一堆客戶端和更重要的客戶端,這些客戶端可以同時發送多個消息(如ping,更新請求和用戶引發的數據請求)

我想到的是這樣的: 簡要概述:客戶端啓動3個不同的角色,這些角色在不同偏移量的循環中再次啓動角色,以模擬相當隨機的消息。

import scala.actors.remote.RemoteActor 
import scala.actors.remote.Node 
import scala.actors.Actor 

trait Request 
trait Response 

case object WhoAmI extends Request 
case class YouAre(s:String) extends Response 

case object Ping extends Request 
case object Pong extends Response 

case class PrintThis(s:String) extends Request 
case object PrintingDone extends Response 

object Server { 
    def main(args: Array[String]) { 
    val server = new Server 
    server.start 
    } 
} 

class Server extends Actor { 
    RemoteActor.alive(12345) 
    RemoteActor.register('server, this) 
    var count:Int = 0 

    def act() { 
    while(true) { 
     receive { 
     case WhoAmI => { 
      count += 1 
      sender ! YouAre(count.toString) 
     } 
     case Ping => sender ! Pong 
     case PrintThis(s) => { 
      println(s) 
      sender ! PrintingDone 
     } 
     case x => println("Got a bad request: " + x) 

     } 
    } 
    } 
} 

object Act3 extends scala.actors.Actor { 
    def act = { 
    var i = 0 
    Thread.sleep(900) 
    while (i <= 12) { 
     i += 1 
     val a = new Printer 
     a.start 
     Thread.sleep(900) 
    } 
    } 
} 

class Printer extends scala.actors.Actor { 
    def act = { 
    val server = RemoteActor.select(Node("localhost",12345), 'server) 
    server ! PrintThis("gagagagagagagagagagagagaga") 
    receive { 
     case PrintingDone => println("yeah I printed") 
     case _   => println("got something bad from printing") 
    } 
    } 
} 

object Act2 extends scala.actors.Actor { 
    def act = { 
    var i = 0 

    while (i < 10) { 
     i+=1 
     val a = new Pinger 
     a.start 
     Thread.sleep(700) 
    } 
    } 
} 

class Pinger extends scala.actors.Actor { 
    def act = { 
    val server = RemoteActor.select(Node("localhost",12345), 'server) 
    server ! Ping 
    receive { 
     case Pong => println("so I pinged and it fits") 
     case x => println("something wrong with ping. Got " + x) 
    } 
    } 
} 

object Act extends scala.actors.Actor { 
    def act = { 
    var i = 0 

    while(i < 10) { 
     i+=1 
     val a = new SayHi 
     a.start() 
     Thread.sleep(200) 
    } 

    } 
} 

class SayHi extends scala.actors.Actor { 
    def act = { 
    val server = RemoteActor.select(Node("localhost",12345), 'server) 
    server ! "Hey!" 
    } 
} 

object Client { 
    def main(args: Array[String]) { 
    Act.start() 
    //Act2.start() 
    Act3.start() 
    } 
} 

的問題是,事情不跑那樣順利,因爲我想指望他們: 當我開始只在客戶端的演員之一(通過註釋了其他人,因爲我在ClientAct2一樣)事情通常但並不總是順利。如果我啓動兩個或兩個以上的演員,則打印輸出通常會大量顯示(意味着:一次沒有任何事情發生,然後打印輸出顯得相當快)。此外,客戶端有時會終止,有時不會。

這可能不是最大的問題,但它們足以讓我覺得很不舒服。我在演員和遙遠的演員做了很多讀書,但我發現可用的信息相當缺乏。

試圖添加exit聲明,如果它似乎適合。但是這並沒有幫助。

有人知道我做錯了什麼嗎?任何一般的詭計在這裏?一些dos和donts?

+0

相關HTTP:// WWW。 artima.com/shop/actors_in_scala(但可能無法解決您的問題) – oluies 2010-11-03 13:20:18

回答

3

我的猜測是,你的問題,從使用receiveThread.sleep擋住你的演員的螺紋杆。阻塞操作消耗了參與者線程池中的線程,這可以阻止其他參與者執行,直到將新線程添加到池中。 This question可能會提供一些額外的見解。

您可以使用looploopWhilereactreactWithin重寫你的許多演員的使用​​非阻塞操作。例如

import scala.actors.TIMEOUT 

object Act extends scala.actors.Actor { 
    def act = { 
     var i = 0 
     loopWhile(i < 10) { 
     reactWithin(200) { case TIMEOUT => 
      i+=1 
      val a = new SayHi 
      a.start() 
     } 
     } 
    } 
} 

當然,你也可以通過編寫自己的控制結構消除一些樣板:

def doWithin(msec: Long)(f: => Unit) = reactWithin(msec) { case TIMEOUT => f } 
def repeat(times: Int)(f: => Unit) = { 
    var i = 0 
    loopWhile(i < times) { 
     f 
     i+=1 
    } 
} 

這將使你寫

repeat(10) { 
    doWithin(200) { 
     (new SayHi).start 
    } 
} 
+0

嗨亞倫。感謝代碼,鏈接和所有建議。我知道'reactWithin',但讓我再次指出,我習慣於'Thread.sleep'來產生消息之間的偏移量。所以那是別的。無論如何,我踢出了所有「睡眠」命令。應該自己想想那個。現在它更像是一個壓力測試;)但是這並沒有真正解決問題:我嘗試了'react'和'receive'並且使用了明確的'exit'。使用'react'和no'exit'獲得最好的結果,但仍然在大約1次運行中客戶端程序不終止:( – Agl 2010-11-03 07:40:45

+0

請注意,寫在我的響應中的代碼會在消息之間產生偏移量。演員沒有收到消息,它總是超時,然後執行timout case。這應該可以解決打印輸出中出現的問題。 – 2010-11-03 16:12:56

+0

至於終止問題,我觀察到與Scala演員同樣的事情,從來沒有時間以確定發生了什麼 – 2010-11-03 16:14:37

1

您可以嘗試阿卡演員代替框架http://akkasource.org/

+1

而不是深入細節和搞清楚發生了什麼? :) – 2010-11-02 20:24:23

+0

恐怕我同意Vasil :)另一方面:與Scalas Actor相比,有什麼優勢嗎?文檔看起來不錯,這是我書中的一個很大的優點。 – Agl 2010-11-02 22:17:54

+0

@Agl此主題可能有所幫助:http://groups.google.com/group/akka-user/browse_thread/thread/a6d7014b6344b662/4306c30e74e93838?show_docid=4306c30e74e93838&pli=1 – 2010-11-02 23:00:37