2010-11-02 48 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